From 514db668472ac00d18fc789b4631c6d776f29047 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Thu, 16 Mar 2023 22:14:14 -0400 Subject: [PATCH 01/53] Added global definitions --- global.d.ts | 5 +++++ jest.setup.ts | 6 +----- tsconfig.json | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) create mode 100644 global.d.ts diff --git a/global.d.ts b/global.d.ts new file mode 100644 index 0000000..73436f5 --- /dev/null +++ b/global.d.ts @@ -0,0 +1,5 @@ +declare global { + var FRAME_TIME: number; +} + +export {}; \ No newline at end of file diff --git a/jest.setup.ts b/jest.setup.ts index bcf666a..b245498 100644 --- a/jest.setup.ts +++ b/jest.setup.ts @@ -1,8 +1,4 @@ -declare global { - var FRAME_TIME: number; -} - -export const FRAME_TIME: number = global.FRAME_TIME = 16; +global.FRAME_TIME = 16; Object.defineProperty(window, 'navigator', {value: 'node'}); Object.defineProperty(window, 'userAgent', {value: 'node'}); diff --git a/tsconfig.json b/tsconfig.json index 5ea86d0..4fff4ee 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,6 +7,6 @@ "outDir": "./lib", "strict": true }, - "include": ["src"], + "include": ["src", "global.d.ts"], "exclude": ["node_modules", "**/__tests__/*"] } \ No newline at end of file From 6f6fe0e3ff21363b991b89b5a132fc819bd8b80b Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Thu, 16 Mar 2023 22:15:00 -0400 Subject: [PATCH 02/53] Updated dev dependencies --- package-lock.json | 184 +++++++++++++++++++++++++++++++++------------- package.json | 12 +-- 2 files changed, 138 insertions(+), 58 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6dc4d72..ca60373 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,32 +1,30 @@ { "name": "simple-observable-proxy", - "version": "1.0.0", - "lockfileVersion": 2, + "version": "2.0.0", + "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "simple-observable-proxy", - "version": "1.0.0", + "version": "2.0.0", "license": "MIT", - "dependencies": { - "@rollup/plugin-terser": "^0.4.0", - "@rollup/plugin-typescript": "^11.0.0", - "rollup-plugin-prettier": "^3.0.0" - }, "devDependencies": { "@babel/cli": "^7.21.0", "@babel/core": "^7.21.3", "@babel/parser": "^7.21.3", "@babel/preset-env": "^7.20.2", "@babel/preset-typescript": "^7.21.0", - "@types/jest": "^27.5.1", - "jest": "^28.1.0", + "@rollup/plugin-terser": "^0.4.0", + "@rollup/plugin-typescript": "^11.0.0", + "@types/jest": "^27.5.2", + "jest": "^28.1.3", "jest-environment-jsdom": "^28.1.0", "prettier": "^2.8.4", "rollup": "^3.19.1", - "ts-jest": "^28.0.3", + "rollup-plugin-prettier": "^3.0.0", + "ts-jest": "^28.0.8", "tslib": "^2.4.0", - "typescript": "^4.6.4" + "typescript": "^4.9.5" } }, "node_modules/@ampproject/remapping": { @@ -2210,6 +2208,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, "engines": { "node": ">=6.0.0" } @@ -2218,6 +2217,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, "engines": { "node": ">=6.0.0" } @@ -2226,6 +2226,7 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -2235,6 +2236,7 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, "dependencies": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -2247,12 +2249,14 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.17", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "dev": true, "dependencies": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.14" @@ -2269,6 +2273,7 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.0.tgz", "integrity": "sha512-Ipcf3LPNerey1q9ZMjiaWHlNPEHNU/B5/uh9zXLltfEQ1lVSLLeZSgAtTPWGyw8Ip1guOeq+mDtdOlEj/wNxQw==", + "dev": true, "dependencies": { "serialize-javascript": "^6.0.0", "smob": "^0.0.6", @@ -2290,6 +2295,7 @@ "version": "11.0.0", "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-11.0.0.tgz", "integrity": "sha512-goPyCWBiimk1iJgSTgsehFD5OOFHiAknrRJjqFCudcW8JtWiBlK284Xnn4flqMqg6YAjVG/EE+3aVzrL5qNSzQ==", + "dev": true, "dependencies": { "@rollup/pluginutils": "^5.0.1", "resolve": "^1.22.1" @@ -2315,6 +2321,7 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", + "dev": true, "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", @@ -2409,7 +2416,8 @@ "node_modules/@types/estree": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", - "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==" + "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", + "dev": true }, "node_modules/@types/graceful-fs": { "version": "4.1.6", @@ -2480,7 +2488,8 @@ "node_modules/@types/prettier": { "version": "2.7.2", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", - "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==" + "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", + "dev": true }, "node_modules/@types/stack-utils": { "version": "2.0.1", @@ -2519,6 +2528,7 @@ "version": "8.8.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -2862,7 +2872,8 @@ "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true }, "node_modules/callsites": { "version": "3.1.0", @@ -3035,7 +3046,8 @@ "node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true }, "node_modules/concat-map": { "version": "0.0.1", @@ -3193,6 +3205,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "dev": true, "engines": { "node": ">=0.3.1" } @@ -3316,7 +3329,8 @@ "node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true }, "node_modules/esutils": { "version": "2.0.3", @@ -3523,6 +3537,7 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -3535,7 +3550,8 @@ "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, "node_modules/gensync": { "version": "1.0.0-beta.2", @@ -3628,6 +3644,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, "dependencies": { "function-bind": "^1.1.1" }, @@ -3777,6 +3794,7 @@ "version": "2.11.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "dev": true, "dependencies": { "has": "^1.0.3" }, @@ -5011,17 +5029,20 @@ "node_modules/lodash.hasin": { "version": "4.5.2", "resolved": "https://registry.npmjs.org/lodash.hasin/-/lodash.hasin-4.5.2.tgz", - "integrity": "sha512-AFAitwTSq1Ka/1J9uBaVxpLBP5OI3INQvkl4wKcgIYxoA0S3aqO1QWXHR9aCcOrWtPFqP7GzlFncZfe0Jz0kNw==" + "integrity": "sha512-AFAitwTSq1Ka/1J9uBaVxpLBP5OI3INQvkl4wKcgIYxoA0S3aqO1QWXHR9aCcOrWtPFqP7GzlFncZfe0Jz0kNw==", + "dev": true }, "node_modules/lodash.isempty": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", - "integrity": "sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg==" + "integrity": "sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg==", + "dev": true }, "node_modules/lodash.isnil": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz", - "integrity": "sha512-up2Mzq3545mwVnMhTDMdfoG1OurpA/s5t88JmQX809eH3C8491iu2sfKhTfhQtKY78oPNhiaHJUpT/dUDAAtng==" + "integrity": "sha512-up2Mzq3545mwVnMhTDMdfoG1OurpA/s5t88JmQX809eH3C8491iu2sfKhTfhQtKY78oPNhiaHJUpT/dUDAAtng==", + "dev": true }, "node_modules/lodash.memoize": { "version": "4.1.2", @@ -5032,7 +5053,8 @@ "node_modules/lodash.omitby": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.omitby/-/lodash.omitby-4.6.0.tgz", - "integrity": "sha512-5OrRcIVR75M288p4nbI2WLAf3ndw2GD9fyNv3Bc15+WCxJDdZ4lYndSxGd7hnG6PVjiJTeJE2dHEGhIuKGicIQ==" + "integrity": "sha512-5OrRcIVR75M288p4nbI2WLAf3ndw2GD9fyNv3Bc15+WCxJDdZ4lYndSxGd7hnG6PVjiJTeJE2dHEGhIuKGicIQ==", + "dev": true }, "node_modules/lru-cache": { "version": "5.1.1", @@ -5047,6 +5069,7 @@ "version": "0.26.7", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.7.tgz", "integrity": "sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==", + "dev": true, "dependencies": { "sourcemap-codec": "^1.4.8" }, @@ -5342,7 +5365,8 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true }, "node_modules/picocolors": { "version": "1.0.0", @@ -5354,6 +5378,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, "engines": { "node": ">=8.6" }, @@ -5404,6 +5429,7 @@ "version": "2.8.4", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.4.tgz", "integrity": "sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw==", + "dev": true, "bin": { "prettier": "bin-prettier.js" }, @@ -5478,6 +5504,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, "dependencies": { "safe-buffer": "^5.1.0" } @@ -5591,6 +5618,7 @@ "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, "dependencies": { "is-core-module": "^2.9.0", "path-parse": "^1.0.7", @@ -5652,6 +5680,7 @@ "version": "3.19.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.19.1.tgz", "integrity": "sha512-lAbrdN7neYCg/8WaoWn/ckzCtz+jr70GFfYdlf50OF7387HTg+wiuiqJRFYawwSPpqfqDNYqK7smY/ks2iAudg==", + "dev": true, "bin": { "rollup": "dist/bin/rollup" }, @@ -5667,6 +5696,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/rollup-plugin-prettier/-/rollup-plugin-prettier-3.0.0.tgz", "integrity": "sha512-E0UqeVX1F+ATrHsXKXIywddjK+iFKOeOGI/drZY/wVq/xfHPjghviIhsFz7I0Wfuzp8jeN+4L7kVwQ/X84mOBw==", + "dev": true, "dependencies": { "@types/prettier": "^1.0.0 || ^2.0.0", "diff": "5.1.0", @@ -5688,6 +5718,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, "funding": [ { "type": "github", @@ -5734,6 +5765,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "dev": true, "dependencies": { "randombytes": "^2.1.0" } @@ -5783,12 +5815,14 @@ "node_modules/smob": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/smob/-/smob-0.0.6.tgz", - "integrity": "sha512-V21+XeNni+tTyiST1MHsa84AQhT1aFZipzPpOFAVB8DkHzwJyjjAmt9bgwnuZiZWnIbMo2duE29wybxv/7HWUw==" + "integrity": "sha512-V21+XeNni+tTyiST1MHsa84AQhT1aFZipzPpOFAVB8DkHzwJyjjAmt9bgwnuZiZWnIbMo2duE29wybxv/7HWUw==", + "dev": true }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -5807,7 +5841,8 @@ "version": "1.4.8", "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "deprecated": "Please use @jridgewell/sourcemap-codec instead" + "deprecated": "Please use @jridgewell/sourcemap-codec instead", + "dev": true }, "node_modules/sprintf-js": { "version": "1.0.3", @@ -5925,6 +5960,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -5958,6 +5994,7 @@ "version": "5.16.6", "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.6.tgz", "integrity": "sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg==", + "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", @@ -5975,6 +6012,7 @@ "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, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -6128,7 +6166,7 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", - "devOptional": true + "dev": true }, "node_modules/type-check": { "version": "0.3.2", @@ -6167,6 +6205,7 @@ "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -8059,17 +8098,20 @@ "@jridgewell/resolve-uri": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true }, "@jridgewell/set-array": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true }, "@jridgewell/source-map": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, "requires": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -8079,6 +8121,7 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, "requires": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -8090,12 +8133,14 @@ "@jridgewell/sourcemap-codec": { "version": "1.4.14", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true }, "@jridgewell/trace-mapping": { "version": "0.3.17", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "dev": true, "requires": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.14" @@ -8112,6 +8157,7 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.0.tgz", "integrity": "sha512-Ipcf3LPNerey1q9ZMjiaWHlNPEHNU/B5/uh9zXLltfEQ1lVSLLeZSgAtTPWGyw8Ip1guOeq+mDtdOlEj/wNxQw==", + "dev": true, "requires": { "serialize-javascript": "^6.0.0", "smob": "^0.0.6", @@ -8122,6 +8168,7 @@ "version": "11.0.0", "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-11.0.0.tgz", "integrity": "sha512-goPyCWBiimk1iJgSTgsehFD5OOFHiAknrRJjqFCudcW8JtWiBlK284Xnn4flqMqg6YAjVG/EE+3aVzrL5qNSzQ==", + "dev": true, "requires": { "@rollup/pluginutils": "^5.0.1", "resolve": "^1.22.1" @@ -8131,6 +8178,7 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", + "dev": true, "requires": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", @@ -8211,7 +8259,8 @@ "@types/estree": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", - "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==" + "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", + "dev": true }, "@types/graceful-fs": { "version": "4.1.6", @@ -8282,7 +8331,8 @@ "@types/prettier": { "version": "2.7.2", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", - "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==" + "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", + "dev": true }, "@types/stack-utils": { "version": "2.0.1", @@ -8320,7 +8370,8 @@ "acorn": { "version": "8.8.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==" + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true }, "acorn-globals": { "version": "6.0.0", @@ -8575,7 +8626,8 @@ "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true }, "callsites": { "version": "3.1.0", @@ -8690,7 +8742,8 @@ "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true }, "concat-map": { "version": "0.0.1", @@ -8818,7 +8871,8 @@ "diff": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", - "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==" + "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "dev": true }, "diff-sequences": { "version": "27.5.1", @@ -8902,7 +8956,8 @@ "estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true }, "esutils": { "version": "2.0.3", @@ -9069,12 +9124,14 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, "optional": true }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, "gensync": { "version": "1.0.0-beta.2", @@ -9140,6 +9197,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -9253,6 +9311,7 @@ "version": "2.11.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "dev": true, "requires": { "has": "^1.0.3" } @@ -10198,17 +10257,20 @@ "lodash.hasin": { "version": "4.5.2", "resolved": "https://registry.npmjs.org/lodash.hasin/-/lodash.hasin-4.5.2.tgz", - "integrity": "sha512-AFAitwTSq1Ka/1J9uBaVxpLBP5OI3INQvkl4wKcgIYxoA0S3aqO1QWXHR9aCcOrWtPFqP7GzlFncZfe0Jz0kNw==" + "integrity": "sha512-AFAitwTSq1Ka/1J9uBaVxpLBP5OI3INQvkl4wKcgIYxoA0S3aqO1QWXHR9aCcOrWtPFqP7GzlFncZfe0Jz0kNw==", + "dev": true }, "lodash.isempty": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", - "integrity": "sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg==" + "integrity": "sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg==", + "dev": true }, "lodash.isnil": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz", - "integrity": "sha512-up2Mzq3545mwVnMhTDMdfoG1OurpA/s5t88JmQX809eH3C8491iu2sfKhTfhQtKY78oPNhiaHJUpT/dUDAAtng==" + "integrity": "sha512-up2Mzq3545mwVnMhTDMdfoG1OurpA/s5t88JmQX809eH3C8491iu2sfKhTfhQtKY78oPNhiaHJUpT/dUDAAtng==", + "dev": true }, "lodash.memoize": { "version": "4.1.2", @@ -10219,7 +10281,8 @@ "lodash.omitby": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.omitby/-/lodash.omitby-4.6.0.tgz", - "integrity": "sha512-5OrRcIVR75M288p4nbI2WLAf3ndw2GD9fyNv3Bc15+WCxJDdZ4lYndSxGd7hnG6PVjiJTeJE2dHEGhIuKGicIQ==" + "integrity": "sha512-5OrRcIVR75M288p4nbI2WLAf3ndw2GD9fyNv3Bc15+WCxJDdZ4lYndSxGd7hnG6PVjiJTeJE2dHEGhIuKGicIQ==", + "dev": true }, "lru-cache": { "version": "5.1.1", @@ -10234,6 +10297,7 @@ "version": "0.26.7", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.7.tgz", "integrity": "sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==", + "dev": true, "requires": { "sourcemap-codec": "^1.4.8" } @@ -10459,7 +10523,8 @@ "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true }, "picocolors": { "version": "1.0.0", @@ -10470,7 +10535,8 @@ "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true }, "pify": { "version": "4.0.1", @@ -10502,7 +10568,8 @@ "prettier": { "version": "2.8.4", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.4.tgz", - "integrity": "sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw==" + "integrity": "sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw==", + "dev": true }, "pretty-format": { "version": "27.5.1", @@ -10555,6 +10622,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, "requires": { "safe-buffer": "^5.1.0" } @@ -10652,6 +10720,7 @@ "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, "requires": { "is-core-module": "^2.9.0", "path-parse": "^1.0.7", @@ -10692,6 +10761,7 @@ "version": "3.19.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.19.1.tgz", "integrity": "sha512-lAbrdN7neYCg/8WaoWn/ckzCtz+jr70GFfYdlf50OF7387HTg+wiuiqJRFYawwSPpqfqDNYqK7smY/ks2iAudg==", + "dev": true, "requires": { "fsevents": "~2.3.2" } @@ -10700,6 +10770,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/rollup-plugin-prettier/-/rollup-plugin-prettier-3.0.0.tgz", "integrity": "sha512-E0UqeVX1F+ATrHsXKXIywddjK+iFKOeOGI/drZY/wVq/xfHPjghviIhsFz7I0Wfuzp8jeN+4L7kVwQ/X84mOBw==", + "dev": true, "requires": { "@types/prettier": "^1.0.0 || ^2.0.0", "diff": "5.1.0", @@ -10713,7 +10784,8 @@ "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -10740,6 +10812,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "dev": true, "requires": { "randombytes": "^2.1.0" } @@ -10780,12 +10853,14 @@ "smob": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/smob/-/smob-0.0.6.tgz", - "integrity": "sha512-V21+XeNni+tTyiST1MHsa84AQhT1aFZipzPpOFAVB8DkHzwJyjjAmt9bgwnuZiZWnIbMo2duE29wybxv/7HWUw==" + "integrity": "sha512-V21+XeNni+tTyiST1MHsa84AQhT1aFZipzPpOFAVB8DkHzwJyjjAmt9bgwnuZiZWnIbMo2duE29wybxv/7HWUw==", + "dev": true }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true }, "source-map-support": { "version": "0.5.13", @@ -10800,7 +10875,8 @@ "sourcemap-codec": { "version": "1.4.8", "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true }, "sprintf-js": { "version": "1.0.3", @@ -10887,7 +10963,8 @@ "supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true }, "symbol-tree": { "version": "3.2.4", @@ -10909,6 +10986,7 @@ "version": "5.16.6", "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.6.tgz", "integrity": "sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg==", + "dev": true, "requires": { "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", @@ -10920,6 +10998,7 @@ "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, "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -11026,7 +11105,7 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", - "devOptional": true + "dev": true }, "type-check": { "version": "0.3.2", @@ -11052,7 +11131,8 @@ "typescript": { "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==" + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true }, "unicode-canonical-property-names-ecmascript": { "version": "2.0.0", diff --git a/package.json b/package.json index a5be65b..00a4ebf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "simple-observable-proxy", - "version": "1.1.0", + "version": "2.0.0", "description": "Simple observable ES6 proxy.", "browser": "dist/simple-observable-proxy.js", "main": "lib/index.js", @@ -49,14 +49,14 @@ "@babel/preset-typescript": "^7.21.0", "@rollup/plugin-terser": "^0.4.0", "@rollup/plugin-typescript": "^11.0.0", - "rollup-plugin-prettier": "^3.0.0", - "@types/jest": "^27.5.1", - "jest": "^28.1.0", + "@types/jest": "^27.5.2", + "jest": "^28.1.3", "jest-environment-jsdom": "^28.1.0", "prettier": "^2.8.4", "rollup": "^3.19.1", - "ts-jest": "^28.0.3", + "rollup-plugin-prettier": "^3.0.0", + "ts-jest": "^28.0.8", "tslib": "^2.4.0", - "typescript": "^4.6.4" + "typescript": "^4.9.5" } } From a86746b875cbf693e44c93dfb8bea62185325f0d Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Thu, 16 Mar 2023 22:15:41 -0400 Subject: [PATCH 03/53] Modified TypeScript definitions --- src/index.ts | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/index.ts b/src/index.ts index aace5a2..9471586 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,5 @@ -export type PlainObject = { [name: string]: any } -type ObservableCallback = () => void; +export type Observable = {[name: string]: any;}; +export type ObservableCallback = () => void; // data that is being observed const observables = new Set(); @@ -10,11 +10,11 @@ const observersByProxy = new Map(); // observers to call on tick const proxiesToNotify = new Set(); -const objectConstructor = {}.constructor; -const isPlainObject = (data: any): data is PlainObject => !!data && typeof data === 'object' && data.constructor === objectConstructor; -const canBeObservable = (data: any): boolean => Array.isArray(data) || /*#__INLINE__*/isPlainObject(data); +const plainObjectConstructor = {}.constructor; +const isPlainObject = (data: Observable): boolean => !!data && typeof data === 'object' && data.constructor === plainObjectConstructor; +const canBeObservable = (data: Observable): boolean => Array.isArray(data) || /*#__INLINE__*/isPlainObject(data); -const tick = ():void => { +const tick = (): void => { proxiesToNotify.forEach(proxy => { observersByProxy.get(proxy).forEach((callback: ObservableCallback) => callback()); }); @@ -23,27 +23,27 @@ const tick = ():void => { else setTimeout(tick, 16); }; -const makeObservableProxy = (data: any, rootProxy?: any): PlainObject => { - if(observables.has(data)) throw new Error('Can’t observe Object or Array again'); +const makeObservableProxy = (data: Observable, rootProxy?: Observable): Observable => { + if(observables.has(data)) throw new Error('Only Arrays and plain Objects are observable'); if(observablesByProxy.has(data)) throw new Error('rootProxy isn’t an observable'); let observers: Set; const proxy = new Proxy(data, { get(target, key): any { - return target[key]; + return target[key as string]; }, set(target, key, value): boolean { - if(target[key] !== value) { + if(target[key as string] !== value) { if(observers) { if(observablesByProxy.has(value)) throw new Error('Can’t nest observables'); proxiesToNotify.add(rootProxy || proxy) } - target[key] = value; + target[key as string] = value; } return true; }, deleteProperty(target, key): boolean { if (key in target) { - delete target[key]; + delete target[key as string]; proxiesToNotify.add(rootProxy || proxy); return true; } @@ -51,7 +51,7 @@ const makeObservableProxy = (data: any, rootProxy?: any): PlainObject => { } }); (Array.isArray(data) ? [...Array(data.length).keys()] : Object.keys(data)).forEach(key => { - const value = data[key]; + const value = data[key as string]; if(observablesByProxy.has(value)) throw new Error('Can’t nest observables'); if(/*#__INLINE__*/canBeObservable(value)) proxy[key] = makeObservableProxy(value, rootProxy || proxy); }); @@ -59,24 +59,25 @@ const makeObservableProxy = (data: any, rootProxy?: any): PlainObject => { observables.add(data); observablesByProxy.set(proxy, data); observersByProxy.set(proxy, observers); - return proxy as PlainObject; + return proxy; }; -export const observable = (data: any): PlainObject | boolean => { - return /*#__INLINE__*/canBeObservable(data) && makeObservableProxy(data); +export const observable = (data: Observable): Observable => { + if(/*#__INLINE__*/canBeObservable(data)) return makeObservableProxy(data); + else throw new Error('Only Arrays and plain Objects are observable'); } -export const observe = (observableProxy: any, callback: ObservableCallback): boolean => { +export const observe = (observableProxy: Observable, callback: ObservableCallback): boolean => { const observers = observersByProxy.get(observableProxy); return observers && typeof callback === 'function' ? observers.add(callback) : false; } -export const unobserve = (observableProxy: any | PlainObject, callback: ObservableCallback): boolean => { +export const unobserve = (observableProxy: Observable, callback: ObservableCallback): boolean => { const observers = observersByProxy.get(observableProxy); return observers && typeof callback === 'function' ? observers.delete(callback) : false; } -export const destroy = (observableProxy: any): boolean => { +export const destroy = (observableProxy: Observable): boolean => { const observers = observersByProxy.get(observableProxy); if(observers) { observers.clear(); From b8366282a3a053833ddf229ddfecc262066d336d Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Thu, 16 Mar 2023 22:15:58 -0400 Subject: [PATCH 04/53] Modified tests with new TypeScript definitions --- scripts/test.ts | 131 +++++++++++++++++++++++++----------------------- 1 file changed, 69 insertions(+), 62 deletions(-) diff --git a/scripts/test.ts b/scripts/test.ts index 501f147..713814a 100644 --- a/scripts/test.ts +++ b/scripts/test.ts @@ -1,6 +1,6 @@ -import { observable, observe, unobserve, destroy, PlainObject } from '../src/index'; +import { observable, observe, unobserve, destroy, Observable } from '../src/index'; -function createState() { +function createState(): Observable { return { array: [1, 2, 3], boolean: true, @@ -13,72 +13,79 @@ function createState() { } test('Creates observable from plain object', () => { - const state = observable(createState()) as PlainObject; + const state = observable(createState()); expect(state.array).toEqual([1, 2, 3]); expect(state.boolean).toEqual(true); expect(state.number).toEqual(0); expect(state.object).toEqual({ string: 'test' }); - expect(state.string).toEqual("test"); + expect(state.string).toEqual('test'); }); test('Creates observable from array', () => { - const state = observable([1, 2, 3]) as PlainObject; + const state = observable([1, 2, 3]); expect(state).toEqual([1, 2, 3]); }); test('Creates observable from sparse array', () => { - const state = observable([1, , 3]) as PlainObject; + const state = observable([1, , 3]); expect(state.length).toEqual(3); expect(state[0]).toEqual(1); expect(state[1]).toEqual(undefined); expect(state[2]).toEqual(3); }); -test('observable returns false when passed boolean', () => { - const state = observable(false); - expect(state).toEqual(false); +test('observable() throws error when passed boolean', () => { + expect(() => { + const state = observable(false as any); + }).toThrow(Error); }); -test('observable returns false when passed string', () => { - const state = observable('test'); - expect(state).toEqual(false); +test('observable() throws error when passed string', () => { + expect(() => { + const state = observable('test' as any); + }).toThrow(Error); }); -test('observable returns false when passed number', () => { - const state = observable(1); - expect(state).toEqual(false); +test('observable() throws error when passed number', () => { + expect(() => { + const state = observable(1 as any); + }).toThrow(Error); }); -test('observable returns false when passed null', () => { - const state = observable(null); - expect(state).toEqual(false); +test('observable() throws error when passed null', () => { + expect(() => { + const state = observable(null as any); + }).toThrow(Error); }); -test('observable returns false when passed undefined', () => { - const state = observable(undefined); - expect(state).toEqual(false); +test('observable() throws error when passed undefined', () => { + expect(() => { + const state = observable(undefined as any); + }).toThrow(Error); }); -test('observable returns false when passed instance of built-in class', () => { - const state = observable(new Date()); - expect(state).toEqual(false); +test('observable() throws error when passed instance of built-in class', () => { + expect(() => { + const state = observable(new Date() as any); + }).toThrow(Error); }); -test('observable returns false when passed instance of custom class', () => { - class customClass {constructor(){}}; - const state = observable(new customClass()); - expect(state).toEqual(false); +test('observable() throws error when passed instance of custom class', () => { + class CustomClass {constructor(){}}; + expect(() => { + const state = observable(new CustomClass() as any); + }).toThrow(Error); }); test('Deferred callback when adding object key', done => { const callback = jest.fn(); - const state = observable(createState()) as PlainObject; + const state = observable(createState()); observe(state, callback); state.string2 = 'test2'; expect(callback).not.toBeCalled(); - jest.advanceTimersByTime(FRAME_TIME); + jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); expect(state.string2).toEqual('test2'); done(); @@ -86,12 +93,12 @@ test('Deferred callback when adding object key', done => { test('Deferred callback when modifying object key', done => { const callback = jest.fn(); - const state = observable(createState()) as PlainObject; + const state = observable(createState()); observe(state, callback); expect(state.boolean).toEqual(true); state.boolean = false; expect(callback).not.toBeCalled(); - jest.advanceTimersByTime(FRAME_TIME); + jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); expect(state.boolean).toEqual(false); done(); @@ -99,11 +106,11 @@ test('Deferred callback when modifying object key', done => { test('Deferred callback when deleting object key', done => { const callback = jest.fn(); - const state = observable(createState()) as PlainObject; + const state = observable(createState()); observe(state, callback); delete state.string; expect(callback).not.toBeCalled(); - jest.advanceTimersByTime(FRAME_TIME); + jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); expect(state.string).toEqual(undefined); done(); @@ -111,12 +118,12 @@ test('Deferred callback when deleting object key', done => { test('Deferred callback when modifying mutliple object keys', done => { const callback = jest.fn(); - const state = observable(createState()) as PlainObject; + const state = observable(createState()); observe(state, callback); state.boolean = false; state.number = 1; expect(callback).not.toBeCalled(); - jest.advanceTimersByTime(FRAME_TIME); + jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); expect(state.boolean).toEqual(false); expect(state.number).toEqual(1); @@ -125,14 +132,14 @@ test('Deferred callback when modifying mutliple object keys', done => { test('Deferred callback when modifying object using Object.assign()', done => { const callback = jest.fn(); - const state = observable(createState()) as PlainObject; + const state = observable(createState()); observe(state, callback); Object.assign(state, { boolean: false, number: 1 }); expect(callback).not.toBeCalled(); - jest.advanceTimersByTime(FRAME_TIME); + jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); expect(state.boolean).toEqual(false); expect(state.number).toEqual(1); @@ -141,12 +148,12 @@ test('Deferred callback when modifying object using Object.assign()', done => { test('Deferred callback when modifying array using pop', done => { const callback = jest.fn(); - const state = observable([1, 2, 3]) as PlainObject; + const state = observable([1, 2, 3]); observe(state, callback); expect(state).toEqual([1, 2, 3]); state.pop(); expect(callback).not.toBeCalled(); - jest.advanceTimersByTime(FRAME_TIME); + jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); expect(state.length).toEqual(2); expect(state).toEqual([1, 2]); @@ -155,12 +162,12 @@ test('Deferred callback when modifying array using pop', done => { test('Deferred callback when modifying array using push', done => { const callback = jest.fn(); - const state = observable([1, 2, 3]) as PlainObject; + const state = observable([1, 2, 3]); observe(state, callback); expect(state).toEqual([1, 2, 3]); state.push(4); expect(callback).not.toBeCalled(); - jest.advanceTimersByTime(FRAME_TIME); + jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); expect(state.length).toEqual(4); expect(state).toEqual([1, 2, 3, 4]); @@ -169,12 +176,12 @@ test('Deferred callback when modifying array using push', done => { test('Deferred callback when modifying array using index', done => { const callback = jest.fn(); - const state = observable([1, 2, 3]) as PlainObject; + const state = observable([1, 2, 3]); observe(state, callback); expect(state).toEqual([1, 2, 3]); state[0] = 0; expect(callback).not.toBeCalled(); - jest.advanceTimersByTime(FRAME_TIME); + jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); expect(state.length).toEqual(3); expect(state).toEqual([0, 2, 3]); @@ -183,12 +190,12 @@ test('Deferred callback when modifying array using index', done => { test('Deferred callback when modifying array using length', done => { const callback = jest.fn(); - const state = observable([1, 2, 3]) as PlainObject; + const state = observable([1, 2, 3]); observe(state, callback); expect(state).toEqual([1, 2, 3]); state.length = 1; expect(callback).not.toBeCalled(); - jest.advanceTimersByTime(FRAME_TIME); + jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); expect(state.length).toEqual(1); expect(state).toEqual([1]); @@ -197,12 +204,12 @@ test('Deferred callback when modifying array using length', done => { test('Deferred callback when modifying nested array', done => { const callback = jest.fn(); - const state = observable(createState()) as PlainObject; + const state = observable(createState()); observe(state, callback); expect(state.array).toEqual([1, 2, 3]); state.array.push(4); expect(callback).not.toBeCalled(); - jest.advanceTimersByTime(FRAME_TIME); + jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); expect(state.array.length).toEqual(4); expect(state.array).toEqual([1, 2, 3, 4]); @@ -211,12 +218,12 @@ test('Deferred callback when modifying nested array', done => { test('Deferred callback when modifying nested object', done => { const callback = jest.fn(); - const state = observable(createState()) as PlainObject; + const state = observable(createState()); observe(state, callback); expect(state.array).toEqual([1, 2, 3]); state.object.string2 = 'test2'; expect(callback).not.toBeCalled(); - jest.advanceTimersByTime(FRAME_TIME); + jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); expect(state.object.string2).toEqual('test2'); done(); @@ -225,11 +232,11 @@ test('Deferred callback when modifying nested object', done => { test('Multiple deferred callbacks when modifying object', done => { const callback1 = jest.fn(); const callback2 = jest.fn(); - const state = observable(createState()) as PlainObject; + const state = observable(createState()); observe(state, callback1); observe(state, callback2); state.string = 'test2'; - jest.advanceTimersByTime(FRAME_TIME); + jest.advanceTimersByTime(global.FRAME_TIME); expect(callback1).toHaveBeenCalledTimes(1); expect(callback2).toHaveBeenCalledTimes(1); expect(state.string).toEqual('test2'); @@ -238,15 +245,15 @@ test('Multiple deferred callbacks when modifying object', done => { test('No callback when object is unobserved', done => { const callback = jest.fn(); - const state = observable(createState()) as PlainObject; + const state = observable(createState()); observe(state, callback); state.string = 'test2'; - jest.advanceTimersByTime(FRAME_TIME); + jest.advanceTimersByTime(global.FRAME_TIME); expect(state.string).toEqual('test2'); expect(callback).toHaveBeenCalledTimes(1); unobserve(state, callback); state.string = 'test3'; - jest.advanceTimersByTime(FRAME_TIME); + jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); expect(state.string).toEqual('test3'); done(); @@ -254,20 +261,20 @@ test('No callback when object is unobserved', done => { test('Deferred callback when object is reobserved', done => { const callback = jest.fn(); - const state = observable(createState()) as PlainObject; + const state = observable(createState()); observe(state, callback); state.string = 'test2'; - jest.advanceTimersByTime(FRAME_TIME); + jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); expect(state.string).toEqual('test2'); unobserve(state, callback); state.string = 'test3'; - jest.advanceTimersByTime(FRAME_TIME); + jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); expect(state.string).toEqual('test3'); observe(state, callback); state.string = 'test4'; - jest.advanceTimersByTime(FRAME_TIME); + jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(2); expect(state.string).toEqual('test4'); done(); @@ -291,19 +298,19 @@ test('destroy returns true when destroying an observable', done => { test('after destroying a non-observable observe returns false', done => { const state1 = destroy(observable(createState())); - expect(observe(state1, ()=>{})).toEqual(false); + expect(observe(state1 as any, ()=>{})).toEqual(false); done(); }); test('after destroying a non-observable unobserve returns false', done => { const state1 = destroy(observable(createState())); - expect(unobserve(state1, ()=>{})).toEqual(false); + expect(unobserve(state1 as any, ()=>{})).toEqual(false); done(); }); test('destroying an non-observable multiple times returns false', done => { const state1 = destroy(observable(createState())); - expect(destroy(state1)).toEqual(false); + expect(destroy(state1 as any)).toEqual(false); done(); }); From 6889148a7e4f05b42c74d875fe02552af901cece Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Thu, 16 Mar 2023 22:16:25 -0400 Subject: [PATCH 05/53] Built latest version --- dist/index.d.ts | 13 ++++++------- dist/simple-observable-proxy.js | 26 +++++++++++++++----------- dist/simple-observable-proxy.min.js | 4 ++-- lib/index.d.ts | 13 ++++++------- lib/index.js | 11 +++++++---- lib/index.mjs | 11 +++++++---- 6 files changed, 43 insertions(+), 35 deletions(-) diff --git a/dist/index.d.ts b/dist/index.d.ts index 181ec6f..d743d74 100644 --- a/dist/index.d.ts +++ b/dist/index.d.ts @@ -1,9 +1,8 @@ -export type PlainObject = { +export type Observable = { [name: string]: any; }; -type ObservableCallback = () => void; -export declare const observable: (data: any) => PlainObject | boolean; -export declare const observe: (observableProxy: any, callback: ObservableCallback) => boolean; -export declare const unobserve: (observableProxy: any | PlainObject, callback: ObservableCallback) => boolean; -export declare const destroy: (observableProxy: any) => boolean; -export {}; +export type ObservableCallback = () => void; +export declare const observable: (data: Observable) => Observable; +export declare const observe: (observableProxy: Observable, callback: ObservableCallback) => boolean; +export declare const unobserve: (observableProxy: Observable, callback: ObservableCallback) => boolean; +export declare const destroy: (observableProxy: Observable) => boolean; diff --git a/dist/simple-observable-proxy.js b/dist/simple-observable-proxy.js index 28ebd61..3561c39 100644 --- a/dist/simple-observable-proxy.js +++ b/dist/simple-observable-proxy.js @@ -1,9 +1,9 @@ -/*! simple observable proxy v1.1.0 | MIT License | © 2022 Aleph1 Technologies Inc */ +/*! simple observable proxy v2.0.0 | MIT License | © 2022 Aleph1 Technologies Inc */ const observables = new Set(), observablesByProxy = new Map(), observersByProxy = new Map(), proxiesToNotify = new Set(), - objectConstructor = {}.constructor, + plainObjectConstructor = {}.constructor, tick = () => { proxiesToNotify.forEach((proxy) => { observersByProxy.get(proxy).forEach((callback) => callback()); @@ -15,7 +15,7 @@ const observables = new Set(), }, makeObservableProxy = (data, rootProxy) => { if (observables.has(data)) - throw new Error("Can’t observe Object or Array again"); + throw new Error("Only Arrays and plain Objects are observable"); if (observablesByProxy.has(data)) throw new Error("rootProxy isn’t an observable"); let observers; @@ -49,7 +49,7 @@ const observables = new Set(), ((data) => !!data && "object" == typeof data && - data.constructor === objectConstructor)(data))(value) && + data.constructor === plainObjectConstructor)(data))(value) && (proxy[key] = makeObservableProxy(value, rootProxy || proxy)); }), (observers = new Set()), @@ -59,14 +59,18 @@ const observables = new Set(), proxy ); }, - observable = (data) => - ((data) => - Array.isArray(data) || + observable = (data) => { + if ( ((data) => - !!data && - "object" == typeof data && - data.constructor === objectConstructor)(data))(data) && - makeObservableProxy(data), + Array.isArray(data) || + ((data) => + !!data && + "object" == typeof data && + data.constructor === plainObjectConstructor)(data))(data) + ) + return makeObservableProxy(data); + throw new Error("Only Arrays and plain Objects are observable"); + }, observe = (observableProxy, callback) => { const observers = observersByProxy.get(observableProxy); return ( diff --git a/dist/simple-observable-proxy.min.js b/dist/simple-observable-proxy.min.js index 5c7845f..a60b99f 100644 --- a/dist/simple-observable-proxy.min.js +++ b/dist/simple-observable-proxy.min.js @@ -1,2 +1,2 @@ -/*! simple observable proxy v1.1.0 | MIT License | © 2022 Aleph1 Technologies Inc */ -const e=new Set,r=new Map,t=new Map,o=new Set,n={}.constructor,a=()=>{o.forEach((e=>{t.get(e).forEach((e=>e()))})),o.clear(),"undefined"!=typeof window&&window.requestAnimationFrame?window.requestAnimationFrame(a):setTimeout(a,16)},s=(a,c)=>{if(e.has(a))throw new Error("Can’t observe Object or Array again");if(r.has(a))throw new Error("rootProxy isn’t an observable");let i;const d=new Proxy(a,{get:(e,r)=>e[r],set(e,t,n){if(e[t]!==n){if(i){if(r.has(n))throw new Error("Can’t nest observables");o.add(c||d)}e[t]=n}return!0},deleteProperty:(e,r)=>r in e&&(delete e[r],o.add(c||d),!0)});return(Array.isArray(a)?[...Array(a.length).keys()]:Object.keys(a)).forEach((e=>{const t=a[e];if(r.has(t))throw new Error("Can’t nest observables");(e=>Array.isArray(e)||(e=>!!e&&"object"==typeof e&&e.constructor===n)(e))(t)&&(d[e]=s(t,c||d))})),i=new Set,e.add(a),r.set(d,a),t.set(d,i),d},c=e=>(e=>Array.isArray(e)||(e=>!!e&&"object"==typeof e&&e.constructor===n)(e))(e)&&s(e),i=(e,r)=>{const o=t.get(e);return!(!o||"function"!=typeof r)&&o.add(r)},d=(e,r)=>{const o=t.get(e);return!(!o||"function"!=typeof r)&&o.delete(r)},w=n=>{const a=t.get(n);return!!a&&(a.clear(),e.delete(r.get(n)),r.delete(n),t.delete(n),o.delete(n),!0)};a();export{w as destroy,c as observable,i as observe,d as unobserve}; +/*! simple observable proxy v2.0.0 | MIT License | © 2022 Aleph1 Technologies Inc */ +const e=new Set,r=new Map,t=new Map,n=new Set,o={}.constructor,a=()=>{n.forEach((e=>{t.get(e).forEach((e=>e()))})),n.clear(),"undefined"!=typeof window&&window.requestAnimationFrame?window.requestAnimationFrame(a):setTimeout(a,16)},s=(a,i)=>{if(e.has(a))throw new Error("Only Arrays and plain Objects are observable");if(r.has(a))throw new Error("rootProxy isn’t an observable");let c;const d=new Proxy(a,{get:(e,r)=>e[r],set(e,t,o){if(e[t]!==o){if(c){if(r.has(o))throw new Error("Can’t nest observables");n.add(i||d)}e[t]=o}return!0},deleteProperty:(e,r)=>r in e&&(delete e[r],n.add(i||d),!0)});return(Array.isArray(a)?[...Array(a.length).keys()]:Object.keys(a)).forEach((e=>{const t=a[e];if(r.has(t))throw new Error("Can’t nest observables");(e=>Array.isArray(e)||(e=>!!e&&"object"==typeof e&&e.constructor===o)(e))(t)&&(d[e]=s(t,i||d))})),c=new Set,e.add(a),r.set(d,a),t.set(d,c),d},i=e=>{if((e=>Array.isArray(e)||(e=>!!e&&"object"==typeof e&&e.constructor===o)(e))(e))return s(e);throw new Error("Only Arrays and plain Objects are observable")},c=(e,r)=>{const n=t.get(e);return!(!n||"function"!=typeof r)&&n.add(r)},d=(e,r)=>{const n=t.get(e);return!(!n||"function"!=typeof r)&&n.delete(r)},w=o=>{const a=t.get(o);return!!a&&(a.clear(),e.delete(r.get(o)),r.delete(o),t.delete(o),n.delete(o),!0)};a();export{w as destroy,i as observable,c as observe,d as unobserve}; diff --git a/lib/index.d.ts b/lib/index.d.ts index 181ec6f..d743d74 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -1,9 +1,8 @@ -export type PlainObject = { +export type Observable = { [name: string]: any; }; -type ObservableCallback = () => void; -export declare const observable: (data: any) => PlainObject | boolean; -export declare const observe: (observableProxy: any, callback: ObservableCallback) => boolean; -export declare const unobserve: (observableProxy: any | PlainObject, callback: ObservableCallback) => boolean; -export declare const destroy: (observableProxy: any) => boolean; -export {}; +export type ObservableCallback = () => void; +export declare const observable: (data: Observable) => Observable; +export declare const observe: (observableProxy: Observable, callback: ObservableCallback) => boolean; +export declare const unobserve: (observableProxy: Observable, callback: ObservableCallback) => boolean; +export declare const destroy: (observableProxy: Observable) => boolean; diff --git a/lib/index.js b/lib/index.js index 1f9cc37..4293e5a 100644 --- a/lib/index.js +++ b/lib/index.js @@ -9,8 +9,8 @@ const observablesByProxy = new Map(); const observersByProxy = new Map(); // observers to call on tick const proxiesToNotify = new Set(); -const objectConstructor = {}.constructor; -const isPlainObject = (data) => !!data && typeof data === 'object' && data.constructor === objectConstructor; +const plainObjectConstructor = {}.constructor; +const isPlainObject = (data) => !!data && typeof data === 'object' && data.constructor === plainObjectConstructor; const canBeObservable = (data) => Array.isArray(data) || /*#__INLINE__*/ isPlainObject(data); const tick = () => { proxiesToNotify.forEach(proxy => { @@ -24,7 +24,7 @@ const tick = () => { }; const makeObservableProxy = (data, rootProxy) => { if (observables.has(data)) - throw new Error('Can’t observe Object or Array again'); + throw new Error('Only Arrays and plain Objects are observable'); if (observablesByProxy.has(data)) throw new Error('rootProxy isn’t an observable'); let observers; @@ -66,7 +66,10 @@ const makeObservableProxy = (data, rootProxy) => { return proxy; }; const observable = (data) => { - return /*#__INLINE__*/ canBeObservable(data) && makeObservableProxy(data); + if ( /*#__INLINE__*/canBeObservable(data)) + return makeObservableProxy(data); + else + throw new Error('Only Arrays and plain Objects are observable'); }; exports.observable = observable; const observe = (observableProxy, callback) => { diff --git a/lib/index.mjs b/lib/index.mjs index 69bf000..43df244 100644 --- a/lib/index.mjs +++ b/lib/index.mjs @@ -6,8 +6,8 @@ const observablesByProxy = new Map(); const observersByProxy = new Map(); // observers to call on tick const proxiesToNotify = new Set(); -const objectConstructor = {}.constructor; -const isPlainObject = (data) => !!data && typeof data === 'object' && data.constructor === objectConstructor; +const plainObjectConstructor = {}.constructor; +const isPlainObject = (data) => !!data && typeof data === 'object' && data.constructor === plainObjectConstructor; const canBeObservable = (data) => Array.isArray(data) || /*#__INLINE__*/ isPlainObject(data); const tick = () => { proxiesToNotify.forEach(proxy => { @@ -21,7 +21,7 @@ const tick = () => { }; const makeObservableProxy = (data, rootProxy) => { if (observables.has(data)) - throw new Error('Can’t observe Object or Array again'); + throw new Error('Only Arrays and plain Objects are observable'); if (observablesByProxy.has(data)) throw new Error('rootProxy isn’t an observable'); let observers; @@ -63,7 +63,10 @@ const makeObservableProxy = (data, rootProxy) => { return proxy; }; export const observable = (data) => { - return /*#__INLINE__*/ canBeObservable(data) && makeObservableProxy(data); + if ( /*#__INLINE__*/canBeObservable(data)) + return makeObservableProxy(data); + else + throw new Error('Only Arrays and plain Objects are observable'); }; export const observe = (observableProxy, callback) => { const observers = observersByProxy.get(observableProxy); From dcf2fb2db227b882126925446ad873227432ed82 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Thu, 16 Mar 2023 22:29:04 -0400 Subject: [PATCH 06/53] Updated readme with notes pertaining to TypeScript and errors --- README.md | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 6b878a1..8ecc88a 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # Simple Observable Proxy ### Simple Observable Proxy is a dependency-free library for JavaScript, that allows for observation of arrays and objects that are either flat or deep. -For objects, changing values, as well as adding, editing, or deleting keys results in a callback signal. For arrays changing values, direct modification using \[\], methods that change the array (pop, push, shift, unshift, etc.), or modifying length results in a callback signal. Multiple observers can be created per observable, and all signals are queued and sent on requestAnimationFrame. +For objects, changing values, as well as adding, editing, or deleting keys results in a callback signal. For arrays changing values, direct modification using \[\], methods that change the array (pop, push, shift, unshift, etc.), or modifying length results in a callback signal. Multiple observers can be created per observable, and all signals are queued and sent using requestAnimationFrame in the browser, and an interval of 16 milliseconds in a node environment. -Simple Observable Proxy is written in TypeScript and is intended to be a very small library (approximately 650 bytes when minified and gzipped), and, as such, it does not report on specific differences between the current and prior state of the observed object or array. +Simple Observable Proxy is written in TypeScript and compiles as CommonJS and ESM. It is intended to be a very small library (approximately 700 bytes when minified and gzipped), and, as such, it does not report on specific differences between the current and prior state of the observed object or array. ## Installation @@ -69,22 +69,24 @@ observe(sharedState, sharedStateCallback2); ## Methods -### observable(plainObjectOrArray) -Converts a plain object or array to an instance of `Proxy` and returns it. If any other value is passed to the function it returns `false`. +### observable(arrayOrPlainObject: Observable): Observable +Converts an `Array` or plain `Object` (not an instance of a class) to an instance of `Proxy` and returns it. There are numerous cases where this function will throw an Error: -### observe(proxy, callbackFn) +- If any value other than an `Array` or plain `Object` is passed. +- If the `Array` or plain `Object` contains an instance of a class. +- If the `Array` or plain `Object` contains an `Array` or plain `Object` that has already been passed to `observable()`. + +### observe(proxy: Observable, callbackFn: () => {}): boolean Subscribes to proxy changes using callbackFn, Returns `true` if successfully subscribed, or `false` in cases where the proxy or callback function is invalid, or the callback is already registered. -### unobserve(proxy, callbackFn) +### unobserve(proxy: Observable, callbackFn: () => {}): boolean Unsubscribes from proxy changes using callbackFn. Returns `true` if successfully unsubscribed, or `false` in cases where the proxy or callback function is invalid. -### destroy(proxy) +### destroy(proxy: Observable): boolean Cleans up the proxy. Returns `true` if successfully destroyed, or `false` in cases where the proxy has already been destroyed, or is not a valid proxy. ## Notes -Simple Observable Proxy maintains a list of sources to prevent observing the same object or array more than once. Attempting to do so will throw an error. - Attempting to nest one observable within another will throw an error. When multiple values are modified on an observable proxy only one notification is sent per callback on the next requestAnimationFrame. For example: @@ -109,10 +111,6 @@ delete state.test2; // delete key ## Roadmap -Version 2.0 will include the following changes: - -- observable will throw errors when trying to observe a value other than an array or plain object - Version 3.0 will consider the following changes: - Instances of classes are observable From f155ca5821fc5d53289f34068277a0a06e255906 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Thu, 16 Mar 2023 22:40:33 -0400 Subject: [PATCH 07/53] Added more explicit information regarding observable callbacks --- README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 8ecc88a..7d2425d 100644 --- a/README.md +++ b/README.md @@ -87,14 +87,12 @@ Cleans up the proxy. Returns `true` if successfully destroyed, or `false` in cas ## Notes -Attempting to nest one observable within another will throw an error. - -When multiple values are modified on an observable proxy only one notification is sent per callback on the next requestAnimationFrame. For example: +When a value is modified on an observable proxy, its updated values is available immediately. When multiple values are modified on the observable proxy each registered callback will be called only once using requestAnimationFrame in the browser, or after 16ms in a Node environment. For example: ```js import { observable, observe } from 'simple-observable-proxy'; const stateChange = () => { - console.log('state changed') + console.log('state changed callback') }; const state = observable({ test: 'test', @@ -106,7 +104,12 @@ state.nested = [1, 2, 3]; // added key delete state.test2; // delete key // despite multiple changes to state, stateChange will -// only be called once on next requestAnimationFrame +// only be called once on next requestAnimationFrame or after 16ms +console.log('before state changed callback'); + +// output in the console should be +// 'before state changed callback' +// 'state changed callback' ``` ## Roadmap From b15dda414bd89eca7078aaa6418231ff7b8e83f4 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Thu, 16 Mar 2023 22:40:59 -0400 Subject: [PATCH 08/53] Changed case of changes to be singular --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7d2425d..dbcada1 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,7 @@ console.log('before state changed callback'); ## Roadmap -Version 3.0 will consider the following changes: +Version 3.0 will consider the following change: - Instances of classes are observable From 5f43709893898289ae1bcbca9cae66e6f4c73b76 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Tue, 21 Mar 2023 18:52:59 -0400 Subject: [PATCH 09/53] Supports listening for different event types (change, destroy) --- src/index.ts | 65 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 17 deletions(-) diff --git a/src/index.ts b/src/index.ts index 9471586..35ea4e9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,24 +1,43 @@ export type Observable = {[name: string]: any;}; export type ObservableCallback = () => void; +export const ObservableEvents = { + change: 'change', + destroy: 'destroy', +} as const; +type ObservableEventKey = keyof typeof ObservableEvents; +export type ObservableEvent = typeof ObservableEvents[ObservableEventKey]; + +type ObservableCallbackObject = { + change: Set, + destroy: Set +}; +export type ObservableCallbackMap = Map; // data that is being observed const observables = new Set(); // original data for each proxy const observablesByProxy = new Map(); // observers for each proxy -const observersByProxy = new Map(); -// observers to call on tick -const proxiesToNotify = new Set(); +const observersByProxy: ObservableCallbackMap = new Map(); +// collections to call on tick +const changedProxies: Set = new Set(); +const destroyedProxies: Set = new Set(); const plainObjectConstructor = {}.constructor; const isPlainObject = (data: Observable): boolean => !!data && typeof data === 'object' && data.constructor === plainObjectConstructor; const canBeObservable = (data: Observable): boolean => Array.isArray(data) || /*#__INLINE__*/isPlainObject(data); const tick = (): void => { - proxiesToNotify.forEach(proxy => { - observersByProxy.get(proxy).forEach((callback: ObservableCallback) => callback()); + changedProxies.forEach(proxy => { + const observers = observersByProxy.get(proxy); + if(observers) observers.change.forEach((callback: ObservableCallback) => callback()); + }); + changedProxies.clear(); + destroyedProxies.forEach(proxy => { + const observers = observersByProxy.get(proxy); + if(observers) observers.destroy.forEach((callback: ObservableCallback) => callback()); }); - proxiesToNotify.clear(); + destroyedProxies.clear(); if(typeof window !== "undefined" && window.requestAnimationFrame) window.requestAnimationFrame(tick); else setTimeout(tick, 16); }; @@ -26,7 +45,7 @@ const tick = (): void => { const makeObservableProxy = (data: Observable, rootProxy?: Observable): Observable => { if(observables.has(data)) throw new Error('Only Arrays and plain Objects are observable'); if(observablesByProxy.has(data)) throw new Error('rootProxy isn’t an observable'); - let observers: Set; + let observers: ObservableCallbackObject; const proxy = new Proxy(data, { get(target, key): any { return target[key as string]; @@ -35,7 +54,7 @@ const makeObservableProxy = (data: Observable, rootProxy?: Observable): Observab if(target[key as string] !== value) { if(observers) { if(observablesByProxy.has(value)) throw new Error('Can’t nest observables'); - proxiesToNotify.add(rootProxy || proxy) + changedProxies.add(rootProxy || proxy) } target[key as string] = value; } @@ -44,7 +63,7 @@ const makeObservableProxy = (data: Observable, rootProxy?: Observable): Observab deleteProperty(target, key): boolean { if (key in target) { delete target[key as string]; - proxiesToNotify.add(rootProxy || proxy); + changedProxies.add(rootProxy || proxy); return true; } return false; @@ -55,10 +74,12 @@ const makeObservableProxy = (data: Observable, rootProxy?: Observable): Observab if(observablesByProxy.has(value)) throw new Error('Can’t nest observables'); if(/*#__INLINE__*/canBeObservable(value)) proxy[key] = makeObservableProxy(value, rootProxy || proxy); }); - observers = new Set(); observables.add(data); observablesByProxy.set(proxy, data); - observersByProxy.set(proxy, observers); + observersByProxy.set(proxy, observers = { + change: new Set(), + destroy: new Set() + }); return proxy; }; @@ -67,24 +88,34 @@ export const observable = (data: Observable): Observable => { else throw new Error('Only Arrays and plain Objects are observable'); } -export const observe = (observableProxy: Observable, callback: ObservableCallback): boolean => { +export const on = (observableProxy: Observable, eventType: ObservableEventKey, callback: ObservableCallback ): boolean => { const observers = observersByProxy.get(observableProxy); - return observers && typeof callback === 'function' ? observers.add(callback) : false; + if(observers && observers[eventType] && typeof callback === 'function' && !observers[eventType].has(callback)) { + observers[eventType].add(callback); + return true; + } + return false; } -export const unobserve = (observableProxy: Observable, callback: ObservableCallback): boolean => { +export const off = (observableProxy: Observable, eventType: ObservableEventKey, callback: ObservableCallback ): boolean => { const observers = observersByProxy.get(observableProxy); - return observers && typeof callback === 'function' ? observers.delete(callback) : false; + if(observers && observers[eventType] && typeof callback === 'function') return observers[eventType].delete(callback); + return false; } +// deprecated and to be removed in 3.0 +export const observe = (observableProxy: Observable, callback: ObservableCallback): boolean => on(observableProxy, ObservableEvents.change, callback); +export const unobserve = (observableProxy: Observable, callback: ObservableCallback): boolean => off(observableProxy, ObservableEvents.change, callback); + export const destroy = (observableProxy: Observable): boolean => { const observers = observersByProxy.get(observableProxy); if(observers) { - observers.clear(); + observers.change.clear(); + observers.destroy.clear(); observables.delete(observablesByProxy.get(observableProxy)); observablesByProxy.delete(observableProxy); observersByProxy.delete(observableProxy); - proxiesToNotify.delete(observableProxy); + changedProxies.delete(observableProxy); return true; } return false; From 9db316b42c291bdcbe286e6a47a6db0a852df750 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Tue, 21 Mar 2023 18:53:08 -0400 Subject: [PATCH 10/53] Build latest version --- dist/index.d.ts | 14 +++++++ dist/simple-observable-proxy.js | 54 +++++++++++++++++-------- dist/simple-observable-proxy.min.js | 2 +- lib/index.d.ts | 14 +++++++ lib/index.js | 61 +++++++++++++++++++++-------- lib/index.mjs | 55 +++++++++++++++++++------- 6 files changed, 150 insertions(+), 50 deletions(-) diff --git a/dist/index.d.ts b/dist/index.d.ts index d743d74..feac7e8 100644 --- a/dist/index.d.ts +++ b/dist/index.d.ts @@ -2,7 +2,21 @@ export type Observable = { [name: string]: any; }; export type ObservableCallback = () => void; +export declare const ObservableEvents: { + readonly change: "change"; + readonly destroy: "destroy"; +}; +type ObservableEventKey = keyof typeof ObservableEvents; +export type ObservableEvent = typeof ObservableEvents[ObservableEventKey]; +type ObservableCallbackObject = { + change: Set; + destroy: Set; +}; +export type ObservableCallbackMap = Map; export declare const observable: (data: Observable) => Observable; +export declare const on: (observableProxy: Observable, eventType: ObservableEventKey, callback: ObservableCallback) => boolean; +export declare const off: (observableProxy: Observable, eventType: ObservableEventKey, callback: ObservableCallback) => boolean; export declare const observe: (observableProxy: Observable, callback: ObservableCallback) => boolean; export declare const unobserve: (observableProxy: Observable, callback: ObservableCallback) => boolean; export declare const destroy: (observableProxy: Observable) => boolean; +export {}; diff --git a/dist/simple-observable-proxy.js b/dist/simple-observable-proxy.js index 3561c39..34abf1c 100644 --- a/dist/simple-observable-proxy.js +++ b/dist/simple-observable-proxy.js @@ -1,14 +1,22 @@ /*! simple observable proxy v2.0.0 | MIT License | © 2022 Aleph1 Technologies Inc */ -const observables = new Set(), +const ObservableEvents = { change: "change", destroy: "destroy" }, + observables = new Set(), observablesByProxy = new Map(), observersByProxy = new Map(), - proxiesToNotify = new Set(), + changedProxies = new Set(), + destroyedProxies = new Set(), plainObjectConstructor = {}.constructor, tick = () => { - proxiesToNotify.forEach((proxy) => { - observersByProxy.get(proxy).forEach((callback) => callback()); + changedProxies.forEach((proxy) => { + const observers = observersByProxy.get(proxy); + observers && observers.change.forEach((callback) => callback()); }), - proxiesToNotify.clear(), + changedProxies.clear(), + destroyedProxies.forEach((proxy) => { + const observers = observersByProxy.get(proxy); + observers && observers.destroy.forEach((callback) => callback()); + }), + destroyedProxies.clear(), "undefined" != typeof window && window.requestAnimationFrame ? window.requestAnimationFrame(tick) : setTimeout(tick, 16); @@ -26,7 +34,7 @@ const observables = new Set(), if (observers) { if (observablesByProxy.has(value)) throw new Error("Can’t nest observables"); - proxiesToNotify.add(rootProxy || proxy); + changedProxies.add(rootProxy || proxy); } target[key] = value; } @@ -34,7 +42,7 @@ const observables = new Set(), }, deleteProperty: (target, key) => key in target && - (delete target[key], proxiesToNotify.add(rootProxy || proxy), !0), + (delete target[key], changedProxies.add(rootProxy || proxy), !0), }); return ( (Array.isArray(data) @@ -52,10 +60,12 @@ const observables = new Set(), data.constructor === plainObjectConstructor)(data))(value) && (proxy[key] = makeObservableProxy(value, rootProxy || proxy)); }), - (observers = new Set()), observables.add(data), observablesByProxy.set(proxy, data), - observersByProxy.set(proxy, observers), + observersByProxy.set( + proxy, + (observers = { change: new Set(), destroy: new Set() }) + ), proxy ); }, @@ -71,30 +81,40 @@ const observables = new Set(), return makeObservableProxy(data); throw new Error("Only Arrays and plain Objects are observable"); }, - observe = (observableProxy, callback) => { + on = (observableProxy, eventType, callback) => { const observers = observersByProxy.get(observableProxy); return ( - !(!observers || "function" != typeof callback) && observers.add(callback) + !( + !observers || + !observers[eventType] || + "function" != typeof callback || + observers[eventType].has(callback) + ) && (observers[eventType].add(callback), !0) ); }, - unobserve = (observableProxy, callback) => { + off = (observableProxy, eventType, callback) => { const observers = observersByProxy.get(observableProxy); return ( - !(!observers || "function" != typeof callback) && - observers.delete(callback) + !(!observers || !observers[eventType] || "function" != typeof callback) && + observers[eventType].delete(callback) ); }, + observe = (observableProxy, callback) => + on(observableProxy, ObservableEvents.change, callback), + unobserve = (observableProxy, callback) => + off(observableProxy, ObservableEvents.change, callback), destroy = (observableProxy) => { const observers = observersByProxy.get(observableProxy); return ( !!observers && - (observers.clear(), + (observers.change.clear(), + observers.destroy.clear(), observables.delete(observablesByProxy.get(observableProxy)), observablesByProxy.delete(observableProxy), observersByProxy.delete(observableProxy), - proxiesToNotify.delete(observableProxy), + changedProxies.delete(observableProxy), !0) ); }; tick(); -export { destroy, observable, observe, unobserve }; +export { ObservableEvents, destroy, observable, observe, off, on, unobserve }; diff --git a/dist/simple-observable-proxy.min.js b/dist/simple-observable-proxy.min.js index a60b99f..4d23251 100644 --- a/dist/simple-observable-proxy.min.js +++ b/dist/simple-observable-proxy.min.js @@ -1,2 +1,2 @@ /*! simple observable proxy v2.0.0 | MIT License | © 2022 Aleph1 Technologies Inc */ -const e=new Set,r=new Map,t=new Map,n=new Set,o={}.constructor,a=()=>{n.forEach((e=>{t.get(e).forEach((e=>e()))})),n.clear(),"undefined"!=typeof window&&window.requestAnimationFrame?window.requestAnimationFrame(a):setTimeout(a,16)},s=(a,i)=>{if(e.has(a))throw new Error("Only Arrays and plain Objects are observable");if(r.has(a))throw new Error("rootProxy isn’t an observable");let c;const d=new Proxy(a,{get:(e,r)=>e[r],set(e,t,o){if(e[t]!==o){if(c){if(r.has(o))throw new Error("Can’t nest observables");n.add(i||d)}e[t]=o}return!0},deleteProperty:(e,r)=>r in e&&(delete e[r],n.add(i||d),!0)});return(Array.isArray(a)?[...Array(a.length).keys()]:Object.keys(a)).forEach((e=>{const t=a[e];if(r.has(t))throw new Error("Can’t nest observables");(e=>Array.isArray(e)||(e=>!!e&&"object"==typeof e&&e.constructor===o)(e))(t)&&(d[e]=s(t,i||d))})),c=new Set,e.add(a),r.set(d,a),t.set(d,c),d},i=e=>{if((e=>Array.isArray(e)||(e=>!!e&&"object"==typeof e&&e.constructor===o)(e))(e))return s(e);throw new Error("Only Arrays and plain Objects are observable")},c=(e,r)=>{const n=t.get(e);return!(!n||"function"!=typeof r)&&n.add(r)},d=(e,r)=>{const n=t.get(e);return!(!n||"function"!=typeof r)&&n.delete(r)},w=o=>{const a=t.get(o);return!!a&&(a.clear(),e.delete(r.get(o)),r.delete(o),t.delete(o),n.delete(o),!0)};a();export{w as destroy,i as observable,c as observe,d as unobserve}; +const e={change:"change",destroy:"destroy"},r=new Set,t=new Map,n=new Map,o=new Set,a=new Set,s={}.constructor,c=()=>{o.forEach((e=>{const r=n.get(e);r&&r.change.forEach((e=>e()))})),o.clear(),a.forEach((e=>{const r=n.get(e);r&&r.destroy.forEach((e=>e()))})),a.clear(),"undefined"!=typeof window&&window.requestAnimationFrame?window.requestAnimationFrame(c):setTimeout(c,16)},d=(e,a)=>{if(r.has(e))throw new Error("Only Arrays and plain Objects are observable");if(t.has(e))throw new Error("rootProxy isn’t an observable");let c;const y=new Proxy(e,{get:(e,r)=>e[r],set(e,r,n){if(e[r]!==n){if(c){if(t.has(n))throw new Error("Can’t nest observables");o.add(a||y)}e[r]=n}return!0},deleteProperty:(e,r)=>r in e&&(delete e[r],o.add(a||y),!0)});return(Array.isArray(e)?[...Array(e.length).keys()]:Object.keys(e)).forEach((r=>{const n=e[r];if(t.has(n))throw new Error("Can’t nest observables");(e=>Array.isArray(e)||(e=>!!e&&"object"==typeof e&&e.constructor===s)(e))(n)&&(y[r]=d(n,a||y))})),r.add(e),t.set(y,e),n.set(y,c={change:new Set,destroy:new Set}),y},y=e=>{if((e=>Array.isArray(e)||(e=>!!e&&"object"==typeof e&&e.constructor===s)(e))(e))return d(e);throw new Error("Only Arrays and plain Objects are observable")},i=(e,r,t)=>{const o=n.get(e);return!(!o||!o[r]||"function"!=typeof t||o[r].has(t))&&(o[r].add(t),!0)},w=(e,r,t)=>{const o=n.get(e);return!(!o||!o[r]||"function"!=typeof t)&&o[r].delete(t)},h=(r,t)=>i(r,e.change,t),l=(r,t)=>w(r,e.change,t),f=e=>{const a=n.get(e);return!!a&&(a.change.clear(),a.destroy.clear(),r.delete(t.get(e)),t.delete(e),n.delete(e),o.delete(e),!0)};c();export{e as ObservableEvents,f as destroy,y as observable,h as observe,w as off,i as on,l as unobserve}; diff --git a/lib/index.d.ts b/lib/index.d.ts index d743d74..feac7e8 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -2,7 +2,21 @@ export type Observable = { [name: string]: any; }; export type ObservableCallback = () => void; +export declare const ObservableEvents: { + readonly change: "change"; + readonly destroy: "destroy"; +}; +type ObservableEventKey = keyof typeof ObservableEvents; +export type ObservableEvent = typeof ObservableEvents[ObservableEventKey]; +type ObservableCallbackObject = { + change: Set; + destroy: Set; +}; +export type ObservableCallbackMap = Map; export declare const observable: (data: Observable) => Observable; +export declare const on: (observableProxy: Observable, eventType: ObservableEventKey, callback: ObservableCallback) => boolean; +export declare const off: (observableProxy: Observable, eventType: ObservableEventKey, callback: ObservableCallback) => boolean; export declare const observe: (observableProxy: Observable, callback: ObservableCallback) => boolean; export declare const unobserve: (observableProxy: Observable, callback: ObservableCallback) => boolean; export declare const destroy: (observableProxy: Observable) => boolean; +export {}; diff --git a/lib/index.js b/lib/index.js index 4293e5a..b6176ed 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,22 +1,35 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.destroy = exports.unobserve = exports.observe = exports.observable = void 0; +exports.destroy = exports.unobserve = exports.observe = exports.off = exports.on = exports.observable = exports.ObservableEvents = void 0; +exports.ObservableEvents = { + change: 'change', + destroy: 'destroy', +}; // data that is being observed const observables = new Set(); // original data for each proxy const observablesByProxy = new Map(); // observers for each proxy const observersByProxy = new Map(); -// observers to call on tick -const proxiesToNotify = new Set(); +// collections to call on tick +const changedProxies = new Set(); +const destroyedProxies = new Set(); const plainObjectConstructor = {}.constructor; const isPlainObject = (data) => !!data && typeof data === 'object' && data.constructor === plainObjectConstructor; const canBeObservable = (data) => Array.isArray(data) || /*#__INLINE__*/ isPlainObject(data); const tick = () => { - proxiesToNotify.forEach(proxy => { - observersByProxy.get(proxy).forEach((callback) => callback()); + changedProxies.forEach(proxy => { + const observers = observersByProxy.get(proxy); + if (observers) + observers.change.forEach((callback) => callback()); + }); + changedProxies.clear(); + destroyedProxies.forEach(proxy => { + const observers = observersByProxy.get(proxy); + if (observers) + observers.destroy.forEach((callback) => callback()); }); - proxiesToNotify.clear(); + destroyedProxies.clear(); if (typeof window !== "undefined" && window.requestAnimationFrame) window.requestAnimationFrame(tick); else @@ -37,7 +50,7 @@ const makeObservableProxy = (data, rootProxy) => { if (observers) { if (observablesByProxy.has(value)) throw new Error('Can’t nest observables'); - proxiesToNotify.add(rootProxy || proxy); + changedProxies.add(rootProxy || proxy); } target[key] = value; } @@ -46,7 +59,7 @@ const makeObservableProxy = (data, rootProxy) => { deleteProperty(target, key) { if (key in target) { delete target[key]; - proxiesToNotify.add(rootProxy || proxy); + changedProxies.add(rootProxy || proxy); return true; } return false; @@ -59,10 +72,12 @@ const makeObservableProxy = (data, rootProxy) => { if ( /*#__INLINE__*/canBeObservable(value)) proxy[key] = makeObservableProxy(value, rootProxy || proxy); }); - observers = new Set(); observables.add(data); observablesByProxy.set(proxy, data); - observersByProxy.set(proxy, observers); + observersByProxy.set(proxy, observers = { + change: new Set(), + destroy: new Set() + }); return proxy; }; const observable = (data) => { @@ -72,24 +87,36 @@ const observable = (data) => { throw new Error('Only Arrays and plain Objects are observable'); }; exports.observable = observable; -const observe = (observableProxy, callback) => { +const on = (observableProxy, eventType, callback) => { const observers = observersByProxy.get(observableProxy); - return observers && typeof callback === 'function' ? observers.add(callback) : false; + if (observers && observers[eventType] && typeof callback === 'function' && !observers[eventType].has(callback)) { + observers[eventType].add(callback); + return true; + } + return false; }; -exports.observe = observe; -const unobserve = (observableProxy, callback) => { +exports.on = on; +const off = (observableProxy, eventType, callback) => { const observers = observersByProxy.get(observableProxy); - return observers && typeof callback === 'function' ? observers.delete(callback) : false; + if (observers && observers[eventType] && typeof callback === 'function') + return observers[eventType].delete(callback); + return false; }; +exports.off = off; +// deprecated and to be removed in 3.0 +const observe = (observableProxy, callback) => (0, exports.on)(observableProxy, exports.ObservableEvents.change, callback); +exports.observe = observe; +const unobserve = (observableProxy, callback) => (0, exports.off)(observableProxy, exports.ObservableEvents.change, callback); exports.unobserve = unobserve; const destroy = (observableProxy) => { const observers = observersByProxy.get(observableProxy); if (observers) { - observers.clear(); + observers.change.clear(); + observers.destroy.clear(); observables.delete(observablesByProxy.get(observableProxy)); observablesByProxy.delete(observableProxy); observersByProxy.delete(observableProxy); - proxiesToNotify.delete(observableProxy); + changedProxies.delete(observableProxy); return true; } return false; diff --git a/lib/index.mjs b/lib/index.mjs index 43df244..9672a6d 100644 --- a/lib/index.mjs +++ b/lib/index.mjs @@ -1,19 +1,32 @@ +export const ObservableEvents = { + change: 'change', + destroy: 'destroy', +}; // data that is being observed const observables = new Set(); // original data for each proxy const observablesByProxy = new Map(); // observers for each proxy const observersByProxy = new Map(); -// observers to call on tick -const proxiesToNotify = new Set(); +// collections to call on tick +const changedProxies = new Set(); +const destroyedProxies = new Set(); const plainObjectConstructor = {}.constructor; const isPlainObject = (data) => !!data && typeof data === 'object' && data.constructor === plainObjectConstructor; const canBeObservable = (data) => Array.isArray(data) || /*#__INLINE__*/ isPlainObject(data); const tick = () => { - proxiesToNotify.forEach(proxy => { - observersByProxy.get(proxy).forEach((callback) => callback()); + changedProxies.forEach(proxy => { + const observers = observersByProxy.get(proxy); + if (observers) + observers.change.forEach((callback) => callback()); + }); + changedProxies.clear(); + destroyedProxies.forEach(proxy => { + const observers = observersByProxy.get(proxy); + if (observers) + observers.destroy.forEach((callback) => callback()); }); - proxiesToNotify.clear(); + destroyedProxies.clear(); if (typeof window !== "undefined" && window.requestAnimationFrame) window.requestAnimationFrame(tick); else @@ -34,7 +47,7 @@ const makeObservableProxy = (data, rootProxy) => { if (observers) { if (observablesByProxy.has(value)) throw new Error('Can’t nest observables'); - proxiesToNotify.add(rootProxy || proxy); + changedProxies.add(rootProxy || proxy); } target[key] = value; } @@ -43,7 +56,7 @@ const makeObservableProxy = (data, rootProxy) => { deleteProperty(target, key) { if (key in target) { delete target[key]; - proxiesToNotify.add(rootProxy || proxy); + changedProxies.add(rootProxy || proxy); return true; } return false; @@ -56,10 +69,12 @@ const makeObservableProxy = (data, rootProxy) => { if ( /*#__INLINE__*/canBeObservable(value)) proxy[key] = makeObservableProxy(value, rootProxy || proxy); }); - observers = new Set(); observables.add(data); observablesByProxy.set(proxy, data); - observersByProxy.set(proxy, observers); + observersByProxy.set(proxy, observers = { + change: new Set(), + destroy: new Set() + }); return proxy; }; export const observable = (data) => { @@ -68,22 +83,32 @@ export const observable = (data) => { else throw new Error('Only Arrays and plain Objects are observable'); }; -export const observe = (observableProxy, callback) => { +export const on = (observableProxy, eventType, callback) => { const observers = observersByProxy.get(observableProxy); - return observers && typeof callback === 'function' ? observers.add(callback) : false; + if (observers && observers[eventType] && typeof callback === 'function' && !observers[eventType].has(callback)) { + observers[eventType].add(callback); + return true; + } + return false; }; -export const unobserve = (observableProxy, callback) => { +export const off = (observableProxy, eventType, callback) => { const observers = observersByProxy.get(observableProxy); - return observers && typeof callback === 'function' ? observers.delete(callback) : false; + if (observers && observers[eventType] && typeof callback === 'function') + return observers[eventType].delete(callback); + return false; }; +// deprecated and to be removed in 3.0 +export const observe = (observableProxy, callback) => on(observableProxy, ObservableEvents.change, callback); +export const unobserve = (observableProxy, callback) => off(observableProxy, ObservableEvents.change, callback); export const destroy = (observableProxy) => { const observers = observersByProxy.get(observableProxy); if (observers) { - observers.clear(); + observers.change.clear(); + observers.destroy.clear(); observables.delete(observablesByProxy.get(observableProxy)); observablesByProxy.delete(observableProxy); observersByProxy.delete(observableProxy); - proxiesToNotify.delete(observableProxy); + changedProxies.delete(observableProxy); return true; } return false; From aeb6f154d582b37edf45fd232bdae68a5a2fa785 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Tue, 21 Mar 2023 19:10:54 -0400 Subject: [PATCH 11/53] Grouped tests --- scripts/test.ts | 562 ++++++++++++++++++++++++------------------------ 1 file changed, 279 insertions(+), 283 deletions(-) diff --git a/scripts/test.ts b/scripts/test.ts index 713814a..1741951 100644 --- a/scripts/test.ts +++ b/scripts/test.ts @@ -1,4 +1,4 @@ -import { observable, observe, unobserve, destroy, Observable } from '../src/index'; +import { observable, on, off, observe, unobserve, destroy, Observable, ObservableEvents } from '../src/index'; function createState(): Observable { return { @@ -12,322 +12,318 @@ function createState(): Observable { }; } -test('Creates observable from plain object', () => { - const state = observable(createState()); - expect(state.array).toEqual([1, 2, 3]); - expect(state.boolean).toEqual(true); - expect(state.number).toEqual(0); - expect(state.object).toEqual({ - string: 'test' +describe('observable()', () => { + + test('Observable from plain object', () => { + const state = observable(createState()); + expect(state.array).toEqual([1, 2, 3]); + expect(state.boolean).toEqual(true); + expect(state.number).toEqual(0); + expect(state.object).toEqual({ + string: 'test' + }); + expect(state.string).toEqual('test'); }); - expect(state.string).toEqual('test'); -}); -test('Creates observable from array', () => { - const state = observable([1, 2, 3]); - expect(state).toEqual([1, 2, 3]); -}); + test('Observable from array', () => { + const state = observable([1, 2, 3]); + expect(state).toEqual([1, 2, 3]); + }); -test('Creates observable from sparse array', () => { - const state = observable([1, , 3]); - expect(state.length).toEqual(3); - expect(state[0]).toEqual(1); - expect(state[1]).toEqual(undefined); - expect(state[2]).toEqual(3); -}); + test('Observable from sparse array', () => { + const state = observable([1, , 3]); + expect(state.length).toEqual(3); + expect(state[0]).toEqual(1); + expect(state[1]).toEqual(undefined); + expect(state[2]).toEqual(3); + }); -test('observable() throws error when passed boolean', () => { - expect(() => { - const state = observable(false as any); - }).toThrow(Error); -}); + test('Throws error when passed boolean', () => { + expect(() => { + const state = observable(false as any); + }).toThrow(Error); + }); -test('observable() throws error when passed string', () => { - expect(() => { - const state = observable('test' as any); - }).toThrow(Error); -}); + test('Throws error when passed string', () => { + expect(() => { + const state = observable('test' as any); + }).toThrow(Error); + }); -test('observable() throws error when passed number', () => { - expect(() => { - const state = observable(1 as any); - }).toThrow(Error); -}); + test('Throws error when passed number', () => { + expect(() => { + const state = observable(1 as any); + }).toThrow(Error); + }); -test('observable() throws error when passed null', () => { - expect(() => { - const state = observable(null as any); - }).toThrow(Error); -}); + test('Throws error when passed null', () => { + expect(() => { + const state = observable(null as any); + }).toThrow(Error); + }); -test('observable() throws error when passed undefined', () => { - expect(() => { - const state = observable(undefined as any); - }).toThrow(Error); -}); + test('Throws error when passed undefined', () => { + expect(() => { + const state = observable(undefined as any); + }).toThrow(Error); + }); -test('observable() throws error when passed instance of built-in class', () => { - expect(() => { - const state = observable(new Date() as any); - }).toThrow(Error); -}); + test('Throws error when passed instance of built-in class', () => { + expect(() => { + const state = observable(new Date() as any); + }).toThrow(Error); + }); -test('observable() throws error when passed instance of custom class', () => { - class CustomClass {constructor(){}}; - expect(() => { - const state = observable(new CustomClass() as any); - }).toThrow(Error); -}); + test('Throws error when passed instance of custom class', () => { + class CustomClass {constructor(){}}; + expect(() => { + const state = observable(new CustomClass() as any); + }).toThrow(Error); + }); -test('Deferred callback when adding object key', done => { - const callback = jest.fn(); - const state = observable(createState()); - observe(state, callback); - state.string2 = 'test2'; - expect(callback).not.toBeCalled(); - jest.advanceTimersByTime(global.FRAME_TIME); - expect(callback).toHaveBeenCalledTimes(1); - expect(state.string2).toEqual('test2'); - done(); -}); + test('Throws error when observables are nested', done => { + const state1 = observable(createState()); + expect(() => { + const state2 = observable({ + state: state1 + }); + }).toThrow(Error); + done(); + }); -test('Deferred callback when modifying object key', done => { - const callback = jest.fn(); - const state = observable(createState()); - observe(state, callback); - expect(state.boolean).toEqual(true); - state.boolean = false; - expect(callback).not.toBeCalled(); - jest.advanceTimersByTime(global.FRAME_TIME); - expect(callback).toHaveBeenCalledTimes(1); - expect(state.boolean).toEqual(false); - done(); }); -test('Deferred callback when deleting object key', done => { - const callback = jest.fn(); - const state = observable(createState()); - observe(state, callback); - delete state.string; - expect(callback).not.toBeCalled(); - jest.advanceTimersByTime(global.FRAME_TIME); - expect(callback).toHaveBeenCalledTimes(1); - expect(state.string).toEqual(undefined); - done(); -}); +describe('observe()', () => { + + test('triggers deferred callback when adding object key', done => { + const callback = jest.fn(); + const state = observable(createState()); + observe(state, callback); + state.string2 = 'test2'; + expect(callback).not.toBeCalled(); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.string2).toEqual('test2'); + done(); + }); -test('Deferred callback when modifying mutliple object keys', done => { - const callback = jest.fn(); - const state = observable(createState()); - observe(state, callback); - state.boolean = false; - state.number = 1; - expect(callback).not.toBeCalled(); - jest.advanceTimersByTime(global.FRAME_TIME); - expect(callback).toHaveBeenCalledTimes(1); - expect(state.boolean).toEqual(false); - expect(state.number).toEqual(1); - done(); -}); + test('triggers deferred callback when modifying object key', done => { + const callback = jest.fn(); + const state = observable(createState()); + observe(state, callback); + expect(state.boolean).toEqual(true); + state.boolean = false; + expect(callback).not.toBeCalled(); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.boolean).toEqual(false); + done(); + }); -test('Deferred callback when modifying object using Object.assign()', done => { - const callback = jest.fn(); - const state = observable(createState()); - observe(state, callback); - Object.assign(state, { - boolean: false, - number: 1 + test('triggers deferred callback when deleting object key', done => { + const callback = jest.fn(); + const state = observable(createState()); + observe(state, callback); + delete state.string; + expect(callback).not.toBeCalled(); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.string).toEqual(undefined); + done(); }); - expect(callback).not.toBeCalled(); - jest.advanceTimersByTime(global.FRAME_TIME); - expect(callback).toHaveBeenCalledTimes(1); - expect(state.boolean).toEqual(false); - expect(state.number).toEqual(1); - done(); -}); -test('Deferred callback when modifying array using pop', done => { - const callback = jest.fn(); - const state = observable([1, 2, 3]); - observe(state, callback); - expect(state).toEqual([1, 2, 3]); - state.pop(); - expect(callback).not.toBeCalled(); - jest.advanceTimersByTime(global.FRAME_TIME); - expect(callback).toHaveBeenCalledTimes(1); - expect(state.length).toEqual(2); - expect(state).toEqual([1, 2]); - done(); -}); + test('triggers deferred callback when modifying mutliple object keys', done => { + const callback = jest.fn(); + const state = observable(createState()); + observe(state, callback); + state.boolean = false; + state.number = 1; + expect(callback).not.toBeCalled(); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.boolean).toEqual(false); + expect(state.number).toEqual(1); + done(); + }); -test('Deferred callback when modifying array using push', done => { - const callback = jest.fn(); - const state = observable([1, 2, 3]); - observe(state, callback); - expect(state).toEqual([1, 2, 3]); - state.push(4); - expect(callback).not.toBeCalled(); - jest.advanceTimersByTime(global.FRAME_TIME); - expect(callback).toHaveBeenCalledTimes(1); - expect(state.length).toEqual(4); - expect(state).toEqual([1, 2, 3, 4]); - done(); -}); + test('triggers deferred callback when modifying object using Object.assign()', done => { + const callback = jest.fn(); + const state = observable(createState()); + observe(state, callback); + Object.assign(state, { + boolean: false, + number: 1 + }); + expect(callback).not.toBeCalled(); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.boolean).toEqual(false); + expect(state.number).toEqual(1); + done(); + }); -test('Deferred callback when modifying array using index', done => { - const callback = jest.fn(); - const state = observable([1, 2, 3]); - observe(state, callback); - expect(state).toEqual([1, 2, 3]); - state[0] = 0; - expect(callback).not.toBeCalled(); - jest.advanceTimersByTime(global.FRAME_TIME); - expect(callback).toHaveBeenCalledTimes(1); - expect(state.length).toEqual(3); - expect(state).toEqual([0, 2, 3]); - done(); -}); + test('triggers deferred callback when modifying array using pop', done => { + const callback = jest.fn(); + const state = observable([1, 2, 3]); + observe(state, callback); + expect(state).toEqual([1, 2, 3]); + state.pop(); + expect(callback).not.toBeCalled(); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.length).toEqual(2); + expect(state).toEqual([1, 2]); + done(); + }); -test('Deferred callback when modifying array using length', done => { - const callback = jest.fn(); - const state = observable([1, 2, 3]); - observe(state, callback); - expect(state).toEqual([1, 2, 3]); - state.length = 1; - expect(callback).not.toBeCalled(); - jest.advanceTimersByTime(global.FRAME_TIME); - expect(callback).toHaveBeenCalledTimes(1); - expect(state.length).toEqual(1); - expect(state).toEqual([1]); - done(); -}); + test('triggers deferred callback when modifying array using push', done => { + const callback = jest.fn(); + const state = observable([1, 2, 3]); + observe(state, callback); + expect(state).toEqual([1, 2, 3]); + state.push(4); + expect(callback).not.toBeCalled(); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.length).toEqual(4); + expect(state).toEqual([1, 2, 3, 4]); + done(); + }); -test('Deferred callback when modifying nested array', done => { - const callback = jest.fn(); - const state = observable(createState()); - observe(state, callback); - expect(state.array).toEqual([1, 2, 3]); - state.array.push(4); - expect(callback).not.toBeCalled(); - jest.advanceTimersByTime(global.FRAME_TIME); - expect(callback).toHaveBeenCalledTimes(1); - expect(state.array.length).toEqual(4); - expect(state.array).toEqual([1, 2, 3, 4]); - done(); -}); + test('triggers deferred callback when modifying array using index', done => { + const callback = jest.fn(); + const state = observable([1, 2, 3]); + observe(state, callback); + expect(state).toEqual([1, 2, 3]); + state[0] = 0; + expect(callback).not.toBeCalled(); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.length).toEqual(3); + expect(state).toEqual([0, 2, 3]); + done(); + }); -test('Deferred callback when modifying nested object', done => { - const callback = jest.fn(); - const state = observable(createState()); - observe(state, callback); - expect(state.array).toEqual([1, 2, 3]); - state.object.string2 = 'test2'; - expect(callback).not.toBeCalled(); - jest.advanceTimersByTime(global.FRAME_TIME); - expect(callback).toHaveBeenCalledTimes(1); - expect(state.object.string2).toEqual('test2'); - done(); -}); + test('triggers deferred callback when modifying array using length', done => { + const callback = jest.fn(); + const state = observable([1, 2, 3]); + observe(state, callback); + expect(state).toEqual([1, 2, 3]); + state.length = 1; + expect(callback).not.toBeCalled(); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.length).toEqual(1); + expect(state).toEqual([1]); + done(); + }); -test('Multiple deferred callbacks when modifying object', done => { - const callback1 = jest.fn(); - const callback2 = jest.fn(); - const state = observable(createState()); - observe(state, callback1); - observe(state, callback2); - state.string = 'test2'; - jest.advanceTimersByTime(global.FRAME_TIME); - expect(callback1).toHaveBeenCalledTimes(1); - expect(callback2).toHaveBeenCalledTimes(1); - expect(state.string).toEqual('test2'); - done(); -}); + test('triggers deferred callback when modifying nested array', done => { + const callback = jest.fn(); + const state = observable(createState()); + observe(state, callback); + expect(state.array).toEqual([1, 2, 3]); + state.array.push(4); + expect(callback).not.toBeCalled(); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.array.length).toEqual(4); + expect(state.array).toEqual([1, 2, 3, 4]); + done(); + }); -test('No callback when object is unobserved', done => { - const callback = jest.fn(); - const state = observable(createState()); - observe(state, callback); - state.string = 'test2'; - jest.advanceTimersByTime(global.FRAME_TIME); - expect(state.string).toEqual('test2'); - expect(callback).toHaveBeenCalledTimes(1); - unobserve(state, callback); - state.string = 'test3'; - jest.advanceTimersByTime(global.FRAME_TIME); - expect(callback).toHaveBeenCalledTimes(1); - expect(state.string).toEqual('test3'); - done(); -}); + test('triggers deferred callback when modifying nested object', done => { + const callback = jest.fn(); + const state = observable(createState()); + observe(state, callback); + expect(state.array).toEqual([1, 2, 3]); + state.object.string2 = 'test2'; + expect(callback).not.toBeCalled(); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.object.string2).toEqual('test2'); + done(); + }); -test('Deferred callback when object is reobserved', done => { - const callback = jest.fn(); - const state = observable(createState()); - observe(state, callback); - state.string = 'test2'; - jest.advanceTimersByTime(global.FRAME_TIME); - expect(callback).toHaveBeenCalledTimes(1); - expect(state.string).toEqual('test2'); - unobserve(state, callback); - state.string = 'test3'; - jest.advanceTimersByTime(global.FRAME_TIME); - expect(callback).toHaveBeenCalledTimes(1); - expect(state.string).toEqual('test3'); - observe(state, callback); - state.string = 'test4'; - jest.advanceTimersByTime(global.FRAME_TIME); - expect(callback).toHaveBeenCalledTimes(2); - expect(state.string).toEqual('test4'); - done(); -}); + test('triggers deferred callback for multiple observers', done => { + const callback1 = jest.fn(); + const callback2 = jest.fn(); + const state = observable(createState()); + observe(state, callback1); + observe(state, callback2); + state.string = 'test2'; + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback1).toHaveBeenCalledTimes(1); + expect(callback2).toHaveBeenCalledTimes(1); + expect(state.string).toEqual('test2'); + done(); + }); -test('Error when observables are nested', done => { - const state1 = observable(createState()); - expect(() => { - const state2 = observable({ - state: state1 - }); - }).toThrow(Error); - done(); -}); + test('When trying to observe a non-observable returns false', done => { + const obj1 = createState(); + expect(observe(obj1, ()=>{})).toEqual(false); + done(); + }); -test('destroy returns true when destroying an observable', done => { - const state1 = observable(createState()); - expect(destroy(state1)).toEqual(true); - done(); }); -test('after destroying a non-observable observe returns false', done => { - const state1 = destroy(observable(createState())); - expect(observe(state1 as any, ()=>{})).toEqual(false); - done(); -}); +describe('unobserve()', () => { + + test('No callback when object is unobserved', done => { + const callback = jest.fn(); + const state = observable(createState()); + observe(state, callback); + state.string = 'test2'; + jest.advanceTimersByTime(global.FRAME_TIME); + expect(state.string).toEqual('test2'); + expect(callback).toHaveBeenCalledTimes(1); + unobserve(state, callback); + state.string = 'test3'; + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.string).toEqual('test3'); + done(); + }); -test('after destroying a non-observable unobserve returns false', done => { - const state1 = destroy(observable(createState())); - expect(unobserve(state1 as any, ()=>{})).toEqual(false); - done(); -}); + test('After destroying a non-observable returns false', done => { + const state1 = destroy(observable(createState())); + expect(unobserve(state1 as any, ()=>{})).toEqual(false); + done(); + }); -test('destroying an non-observable multiple times returns false', done => { - const state1 = destroy(observable(createState())); - expect(destroy(state1 as any)).toEqual(false); - done(); -}); + test('When trying to unobserve a non-observable returns false w', done => { + const obj1 = createState(); + expect(unobserve(obj1, ()=>{})).toEqual(false); + done(); + }); -test('observe returns false when trying to observe a non-observable', done => { - const obj1 = createState(); - expect(observe(obj1, ()=>{})).toEqual(false); - done(); -}); -test('unobserve returns false when trying to unobserve a non-observable', done => { - const obj1 = createState(); - expect(unobserve(obj1, ()=>{})).toEqual(false); - done(); }); -test('destroy returns false when trying to destroy a non-observable', done => { - const obj1 = createState(); - expect(destroy(obj1)).toEqual(false); - done(); +describe('destroy()', () => { + + test('When destroying an observable retuns true', done => { + const state1 = observable(createState()); + expect(destroy(state1)).toEqual(true); + done(); + }); + + test('When destroying a non-observable returns false', done => { + const state1 = destroy(observable(createState())); + expect(observe(state1 as any, ()=>{})).toEqual(false); + done(); + }); + + test('Destroying an non-observable multiple times returns false', done => { + const state1 = destroy(observable(createState())); + expect(destroy(state1 as any)).toEqual(false); + done(); + }); + + test('When trying to destroy a non-observable returns false', done => { + const obj1 = createState(); + expect(destroy(obj1)).toEqual(false); + done(); + }); + }); \ No newline at end of file From 942a3e21fd2f144750cfd5a3e91ef4eeb9842838 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Tue, 21 Mar 2023 19:11:02 -0400 Subject: [PATCH 12/53] Added tests for on() --- scripts/test.ts | 175 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) diff --git a/scripts/test.ts b/scripts/test.ts index 1741951..c69d7e1 100644 --- a/scripts/test.ts +++ b/scripts/test.ts @@ -267,6 +267,181 @@ describe('observe()', () => { }); +describe('on()', () => { + + test('triggers deferred callback when adding object key', done => { + const callback = jest.fn(); + const state = observable(createState()); + on(state, ObservableEvents.change, callback); + state.string2 = 'test2'; + expect(callback).not.toBeCalled(); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.string2).toEqual('test2'); + done(); + }); + + test('triggers deferred callback when modifying object key', done => { + const callback = jest.fn(); + const state = observable(createState()); + on(state, ObservableEvents.change, callback); + expect(state.boolean).toEqual(true); + state.boolean = false; + expect(callback).not.toBeCalled(); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.boolean).toEqual(false); + done(); + }); + + test('triggers deferred callback when deleting object key', done => { + const callback = jest.fn(); + const state = observable(createState()); + on(state, ObservableEvents.change, callback); + delete state.string; + expect(callback).not.toBeCalled(); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.string).toEqual(undefined); + done(); + }); + + test('triggers deferred callback when modifying mutliple object keys', done => { + const callback = jest.fn(); + const state = observable(createState()); + on(state, ObservableEvents.change, callback); + state.boolean = false; + state.number = 1; + expect(callback).not.toBeCalled(); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.boolean).toEqual(false); + expect(state.number).toEqual(1); + done(); + }); + + test('triggers deferred callback when modifying object using Object.assign()', done => { + const callback = jest.fn(); + const state = observable(createState()); + on(state, ObservableEvents.change, callback); + Object.assign(state, { + boolean: false, + number: 1 + }); + expect(callback).not.toBeCalled(); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.boolean).toEqual(false); + expect(state.number).toEqual(1); + done(); + }); + + test('triggers deferred callback when modifying array using pop', done => { + const callback = jest.fn(); + const state = observable([1, 2, 3]); + on(state, ObservableEvents.change, callback); + expect(state).toEqual([1, 2, 3]); + state.pop(); + expect(callback).not.toBeCalled(); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.length).toEqual(2); + expect(state).toEqual([1, 2]); + done(); + }); + + test('triggers deferred callback when modifying array using push', done => { + const callback = jest.fn(); + const state = observable([1, 2, 3]); + on(state, ObservableEvents.change, callback); + expect(state).toEqual([1, 2, 3]); + state.push(4); + expect(callback).not.toBeCalled(); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.length).toEqual(4); + expect(state).toEqual([1, 2, 3, 4]); + done(); + }); + + test('triggers deferred callback when modifying array using index', done => { + const callback = jest.fn(); + const state = observable([1, 2, 3]); + on(state, ObservableEvents.change, callback); + expect(state).toEqual([1, 2, 3]); + state[0] = 0; + expect(callback).not.toBeCalled(); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.length).toEqual(3); + expect(state).toEqual([0, 2, 3]); + done(); + }); + + test('triggers deferred callback when modifying array using length', done => { + const callback = jest.fn(); + const state = observable([1, 2, 3]); + on(state, ObservableEvents.change, callback); + expect(state).toEqual([1, 2, 3]); + state.length = 1; + expect(callback).not.toBeCalled(); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.length).toEqual(1); + expect(state).toEqual([1]); + done(); + }); + + test('triggers deferred callback when modifying nested array', done => { + const callback = jest.fn(); + const state = observable(createState()); + on(state, ObservableEvents.change, callback); + expect(state.array).toEqual([1, 2, 3]); + state.array.push(4); + expect(callback).not.toBeCalled(); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.array.length).toEqual(4); + expect(state.array).toEqual([1, 2, 3, 4]); + done(); + }); + + test('triggers deferred callback when modifying nested object', done => { + const callback = jest.fn(); + const state = observable(createState()); + on(state, ObservableEvents.change, callback); + expect(state.array).toEqual([1, 2, 3]); + state.object.string2 = 'test2'; + expect(callback).not.toBeCalled(); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.object.string2).toEqual('test2'); + done(); + }); + + test('triggers deferred callback when reobserved', done => { + const callback = jest.fn(); + const state = observable(createState()); + observe(state, callback); + state.string = 'test2'; + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.string).toEqual('test2'); + unobserve(state, callback); + state.string = 'test3'; + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.string).toEqual('test3'); + observe(state, callback); + state.string = 'test4'; + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(2); + expect(state.string).toEqual('test4'); + done(); + }); + +}); + describe('unobserve()', () => { test('No callback when object is unobserved', done => { From 862be04f1716811f9264b95639cfd317a1cc2257 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Tue, 21 Mar 2023 19:12:24 -0400 Subject: [PATCH 13/53] Fixed word cases --- scripts/test.ts | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/scripts/test.ts b/scripts/test.ts index c69d7e1..5db1f74 100644 --- a/scripts/test.ts +++ b/scripts/test.ts @@ -95,7 +95,7 @@ describe('observable()', () => { describe('observe()', () => { - test('triggers deferred callback when adding object key', done => { + test('Triggers deferred callback when adding object key', done => { const callback = jest.fn(); const state = observable(createState()); observe(state, callback); @@ -107,7 +107,7 @@ describe('observe()', () => { done(); }); - test('triggers deferred callback when modifying object key', done => { + test('Triggers deferred callback when modifying object key', done => { const callback = jest.fn(); const state = observable(createState()); observe(state, callback); @@ -120,7 +120,7 @@ describe('observe()', () => { done(); }); - test('triggers deferred callback when deleting object key', done => { + test('Triggers deferred callback when deleting object key', done => { const callback = jest.fn(); const state = observable(createState()); observe(state, callback); @@ -132,7 +132,7 @@ describe('observe()', () => { done(); }); - test('triggers deferred callback when modifying mutliple object keys', done => { + test('Triggers deferred callback when modifying mutliple object keys', done => { const callback = jest.fn(); const state = observable(createState()); observe(state, callback); @@ -146,7 +146,7 @@ describe('observe()', () => { done(); }); - test('triggers deferred callback when modifying object using Object.assign()', done => { + test('Triggers deferred callback when modifying object using Object.assign()', done => { const callback = jest.fn(); const state = observable(createState()); observe(state, callback); @@ -162,7 +162,7 @@ describe('observe()', () => { done(); }); - test('triggers deferred callback when modifying array using pop', done => { + test('Triggers deferred callback when modifying array using pop', done => { const callback = jest.fn(); const state = observable([1, 2, 3]); observe(state, callback); @@ -176,7 +176,7 @@ describe('observe()', () => { done(); }); - test('triggers deferred callback when modifying array using push', done => { + test('Triggers deferred callback when modifying array using push', done => { const callback = jest.fn(); const state = observable([1, 2, 3]); observe(state, callback); @@ -190,7 +190,7 @@ describe('observe()', () => { done(); }); - test('triggers deferred callback when modifying array using index', done => { + test('Triggers deferred callback when modifying array using index', done => { const callback = jest.fn(); const state = observable([1, 2, 3]); observe(state, callback); @@ -204,7 +204,7 @@ describe('observe()', () => { done(); }); - test('triggers deferred callback when modifying array using length', done => { + test('Triggers deferred callback when modifying array using length', done => { const callback = jest.fn(); const state = observable([1, 2, 3]); observe(state, callback); @@ -218,7 +218,7 @@ describe('observe()', () => { done(); }); - test('triggers deferred callback when modifying nested array', done => { + test('Triggers deferred callback when modifying nested array', done => { const callback = jest.fn(); const state = observable(createState()); observe(state, callback); @@ -232,7 +232,7 @@ describe('observe()', () => { done(); }); - test('triggers deferred callback when modifying nested object', done => { + test('Triggers deferred callback when modifying nested object', done => { const callback = jest.fn(); const state = observable(createState()); observe(state, callback); @@ -245,7 +245,7 @@ describe('observe()', () => { done(); }); - test('triggers deferred callback for multiple observers', done => { + test('Triggers deferred callback for multiple observers', done => { const callback1 = jest.fn(); const callback2 = jest.fn(); const state = observable(createState()); @@ -269,7 +269,7 @@ describe('observe()', () => { describe('on()', () => { - test('triggers deferred callback when adding object key', done => { + test('Triggers deferred callback when adding object key', done => { const callback = jest.fn(); const state = observable(createState()); on(state, ObservableEvents.change, callback); @@ -281,7 +281,7 @@ describe('on()', () => { done(); }); - test('triggers deferred callback when modifying object key', done => { + test('Triggers deferred callback when modifying object key', done => { const callback = jest.fn(); const state = observable(createState()); on(state, ObservableEvents.change, callback); @@ -294,7 +294,7 @@ describe('on()', () => { done(); }); - test('triggers deferred callback when deleting object key', done => { + test('Triggers deferred callback when deleting object key', done => { const callback = jest.fn(); const state = observable(createState()); on(state, ObservableEvents.change, callback); @@ -306,7 +306,7 @@ describe('on()', () => { done(); }); - test('triggers deferred callback when modifying mutliple object keys', done => { + test('Triggers deferred callback when modifying mutliple object keys', done => { const callback = jest.fn(); const state = observable(createState()); on(state, ObservableEvents.change, callback); @@ -320,7 +320,7 @@ describe('on()', () => { done(); }); - test('triggers deferred callback when modifying object using Object.assign()', done => { + test('Triggers deferred callback when modifying object using Object.assign()', done => { const callback = jest.fn(); const state = observable(createState()); on(state, ObservableEvents.change, callback); @@ -336,7 +336,7 @@ describe('on()', () => { done(); }); - test('triggers deferred callback when modifying array using pop', done => { + test('Triggers deferred callback when modifying array using pop', done => { const callback = jest.fn(); const state = observable([1, 2, 3]); on(state, ObservableEvents.change, callback); @@ -350,7 +350,7 @@ describe('on()', () => { done(); }); - test('triggers deferred callback when modifying array using push', done => { + test('Triggers deferred callback when modifying array using push', done => { const callback = jest.fn(); const state = observable([1, 2, 3]); on(state, ObservableEvents.change, callback); @@ -364,7 +364,7 @@ describe('on()', () => { done(); }); - test('triggers deferred callback when modifying array using index', done => { + test('Triggers deferred callback when modifying array using index', done => { const callback = jest.fn(); const state = observable([1, 2, 3]); on(state, ObservableEvents.change, callback); @@ -378,7 +378,7 @@ describe('on()', () => { done(); }); - test('triggers deferred callback when modifying array using length', done => { + test('Triggers deferred callback when modifying array using length', done => { const callback = jest.fn(); const state = observable([1, 2, 3]); on(state, ObservableEvents.change, callback); @@ -392,7 +392,7 @@ describe('on()', () => { done(); }); - test('triggers deferred callback when modifying nested array', done => { + test('Triggers deferred callback when modifying nested array', done => { const callback = jest.fn(); const state = observable(createState()); on(state, ObservableEvents.change, callback); @@ -406,7 +406,7 @@ describe('on()', () => { done(); }); - test('triggers deferred callback when modifying nested object', done => { + test('Triggers deferred callback when modifying nested object', done => { const callback = jest.fn(); const state = observable(createState()); on(state, ObservableEvents.change, callback); @@ -419,7 +419,7 @@ describe('on()', () => { done(); }); - test('triggers deferred callback when reobserved', done => { + test('Triggers deferred callback when reobserved', done => { const callback = jest.fn(); const state = observable(createState()); observe(state, callback); From b02d795451ac43a6527f54dcf6b7c685325bd933 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Tue, 21 Mar 2023 19:23:20 -0400 Subject: [PATCH 14/53] Added information about on(), off() and deprecated notices for observe() and unobserve() --- README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index dbcada1..32160cf 100644 --- a/README.md +++ b/README.md @@ -76,11 +76,17 @@ Converts an `Array` or plain `Object` (not an instance of a class) to an instanc - If the `Array` or plain `Object` contains an instance of a class. - If the `Array` or plain `Object` contains an `Array` or plain `Object` that has already been passed to `observable()`. -### observe(proxy: Observable, callbackFn: () => {}): boolean -Subscribes to proxy changes using callbackFn, Returns `true` if successfully subscribed, or `false` in cases where the proxy or callback function is invalid, or the callback is already registered. +### on(proxy: Observable, ObservableEventType: "change" | "destroy", callbackFn: () => {}): boolean +Subscribes to either the change or destroy event using callbackFn, Returns `true` if successfully subscribed, or `false` in cases where the proxy or callback function is invalid, or the callback is already registered. -### unobserve(proxy: Observable, callbackFn: () => {}): boolean -Unsubscribes from proxy changes using callbackFn. Returns `true` if successfully unsubscribed, or `false` in cases where the proxy or callback function is invalid. +### off(proxy: Observable, ObservableEventType: "change" | "destroy", callbackFn: () => {}): boolean +Unsubscribes from either the change or destroy event using callbackFn. Returns `true` if successfully unsubscribed, or `false` in cases where the proxy or callback function is invalid. + +### DEPRECATED observe(proxy: Observable, callbackFn: () => {}): boolean +Shorthand method that calls observe(proxy, "change", callbackFn). Maintained for backwards compatibility with v1, but will be dropped in a future release. + +### DEPRECATED unobserve(proxy: Observable, callbackFn: () => {}): boolean +Shorthand method that calls unobserve(proxy, "change", callbackFn). Maintained for backwards compatibility with v1, but will be dropped in a future release. ### destroy(proxy: Observable): boolean Cleans up the proxy. Returns `true` if successfully destroyed, or `false` in cases where the proxy has already been destroyed, or is not a valid proxy. From ff2ba8e45999634c5ce91e43735211361a42a6bc Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Tue, 21 Mar 2023 23:23:25 -0400 Subject: [PATCH 15/53] Changed double quotes to single quotes --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 35ea4e9..eb2f8d9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -38,7 +38,7 @@ const tick = (): void => { if(observers) observers.destroy.forEach((callback: ObservableCallback) => callback()); }); destroyedProxies.clear(); - if(typeof window !== "undefined" && window.requestAnimationFrame) window.requestAnimationFrame(tick); + if(typeof window !== 'undefined' && window.requestAnimationFrame) window.requestAnimationFrame(tick); else setTimeout(tick, 16); }; From fb7726b377e8a288f24d775d99dfa1bc7aa48e4c Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Tue, 21 Mar 2023 23:25:15 -0400 Subject: [PATCH 16/53] Fixed error logic and messages --- src/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index eb2f8d9..bb5ee06 100644 --- a/src/index.ts +++ b/src/index.ts @@ -43,8 +43,8 @@ const tick = (): void => { }; const makeObservableProxy = (data: Observable, rootProxy?: Observable): Observable => { - if(observables.has(data)) throw new Error('Only Arrays and plain Objects are observable'); - if(observablesByProxy.has(data)) throw new Error('rootProxy isn’t an observable'); + if(observables.has(data)) throw new Error('data is alreaby an observable'); + if(rootProxy && !observablesByProxy.has(rootProxy)) throw new Error('rootProxy isn’t an observable'); let observers: ObservableCallbackObject; const proxy = new Proxy(data, { get(target, key): any { From 68785261502937c8ca5572fa046beffb8f8b7d55 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Tue, 21 Mar 2023 23:25:55 -0400 Subject: [PATCH 17/53] Add data to observables before iterating keys --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index bb5ee06..5460e42 100644 --- a/src/index.ts +++ b/src/index.ts @@ -69,12 +69,12 @@ const makeObservableProxy = (data: Observable, rootProxy?: Observable): Observab return false; } }); + observables.add(data); (Array.isArray(data) ? [...Array(data.length).keys()] : Object.keys(data)).forEach(key => { const value = data[key as string]; if(observablesByProxy.has(value)) throw new Error('Can’t nest observables'); if(/*#__INLINE__*/canBeObservable(value)) proxy[key] = makeObservableProxy(value, rootProxy || proxy); }); - observables.add(data); observablesByProxy.set(proxy, data); observersByProxy.set(proxy, observers = { change: new Set(), From d998b9cc6d3fcac396120de112c4b4c5d3890d9e Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Tue, 21 Mar 2023 23:26:28 -0400 Subject: [PATCH 18/53] Store reference to proxy and data before iterating data keys --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 5460e42..fd41bd5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -70,12 +70,12 @@ const makeObservableProxy = (data: Observable, rootProxy?: Observable): Observab } }); observables.add(data); + observablesByProxy.set(proxy, data); (Array.isArray(data) ? [...Array(data.length).keys()] : Object.keys(data)).forEach(key => { const value = data[key as string]; if(observablesByProxy.has(value)) throw new Error('Can’t nest observables'); if(/*#__INLINE__*/canBeObservable(value)) proxy[key] = makeObservableProxy(value, rootProxy || proxy); }); - observablesByProxy.set(proxy, data); observersByProxy.set(proxy, observers = { change: new Set(), destroy: new Set() From 7c2058a7bc61396c8f2648a6b3fcd7da63ae47cb Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Tue, 21 Mar 2023 23:27:29 -0400 Subject: [PATCH 19/53] Built latest version --- dist/simple-observable-proxy.js | 9 ++++----- dist/simple-observable-proxy.min.js | 2 +- lib/index.js | 10 +++++----- lib/index.mjs | 10 +++++----- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/dist/simple-observable-proxy.js b/dist/simple-observable-proxy.js index 34abf1c..2aa5eaa 100644 --- a/dist/simple-observable-proxy.js +++ b/dist/simple-observable-proxy.js @@ -22,9 +22,8 @@ const ObservableEvents = { change: "change", destroy: "destroy" }, : setTimeout(tick, 16); }, makeObservableProxy = (data, rootProxy) => { - if (observables.has(data)) - throw new Error("Only Arrays and plain Objects are observable"); - if (observablesByProxy.has(data)) + if (observables.has(data)) throw new Error("data is alreaby an observable"); + if (rootProxy && !observablesByProxy.has(rootProxy)) throw new Error("rootProxy isn’t an observable"); let observers; const proxy = new Proxy(data, { @@ -45,6 +44,8 @@ const ObservableEvents = { change: "change", destroy: "destroy" }, (delete target[key], changedProxies.add(rootProxy || proxy), !0), }); return ( + observables.add(data), + observablesByProxy.set(proxy, data), (Array.isArray(data) ? [...Array(data.length).keys()] : Object.keys(data) @@ -60,8 +61,6 @@ const ObservableEvents = { change: "change", destroy: "destroy" }, data.constructor === plainObjectConstructor)(data))(value) && (proxy[key] = makeObservableProxy(value, rootProxy || proxy)); }), - observables.add(data), - observablesByProxy.set(proxy, data), observersByProxy.set( proxy, (observers = { change: new Set(), destroy: new Set() }) diff --git a/dist/simple-observable-proxy.min.js b/dist/simple-observable-proxy.min.js index 4d23251..2bb25a4 100644 --- a/dist/simple-observable-proxy.min.js +++ b/dist/simple-observable-proxy.min.js @@ -1,2 +1,2 @@ /*! simple observable proxy v2.0.0 | MIT License | © 2022 Aleph1 Technologies Inc */ -const e={change:"change",destroy:"destroy"},r=new Set,t=new Map,n=new Map,o=new Set,a=new Set,s={}.constructor,c=()=>{o.forEach((e=>{const r=n.get(e);r&&r.change.forEach((e=>e()))})),o.clear(),a.forEach((e=>{const r=n.get(e);r&&r.destroy.forEach((e=>e()))})),a.clear(),"undefined"!=typeof window&&window.requestAnimationFrame?window.requestAnimationFrame(c):setTimeout(c,16)},d=(e,a)=>{if(r.has(e))throw new Error("Only Arrays and plain Objects are observable");if(t.has(e))throw new Error("rootProxy isn’t an observable");let c;const y=new Proxy(e,{get:(e,r)=>e[r],set(e,r,n){if(e[r]!==n){if(c){if(t.has(n))throw new Error("Can’t nest observables");o.add(a||y)}e[r]=n}return!0},deleteProperty:(e,r)=>r in e&&(delete e[r],o.add(a||y),!0)});return(Array.isArray(e)?[...Array(e.length).keys()]:Object.keys(e)).forEach((r=>{const n=e[r];if(t.has(n))throw new Error("Can’t nest observables");(e=>Array.isArray(e)||(e=>!!e&&"object"==typeof e&&e.constructor===s)(e))(n)&&(y[r]=d(n,a||y))})),r.add(e),t.set(y,e),n.set(y,c={change:new Set,destroy:new Set}),y},y=e=>{if((e=>Array.isArray(e)||(e=>!!e&&"object"==typeof e&&e.constructor===s)(e))(e))return d(e);throw new Error("Only Arrays and plain Objects are observable")},i=(e,r,t)=>{const o=n.get(e);return!(!o||!o[r]||"function"!=typeof t||o[r].has(t))&&(o[r].add(t),!0)},w=(e,r,t)=>{const o=n.get(e);return!(!o||!o[r]||"function"!=typeof t)&&o[r].delete(t)},h=(r,t)=>i(r,e.change,t),l=(r,t)=>w(r,e.change,t),f=e=>{const a=n.get(e);return!!a&&(a.change.clear(),a.destroy.clear(),r.delete(t.get(e)),t.delete(e),n.delete(e),o.delete(e),!0)};c();export{e as ObservableEvents,f as destroy,y as observable,h as observe,w as off,i as on,l as unobserve}; +const e={change:"change",destroy:"destroy"},r=new Set,t=new Map,n=new Map,o=new Set,a=new Set,s={}.constructor,c=()=>{o.forEach((e=>{const r=n.get(e);r&&r.change.forEach((e=>e()))})),o.clear(),a.forEach((e=>{const r=n.get(e);r&&r.destroy.forEach((e=>e()))})),a.clear(),"undefined"!=typeof window&&window.requestAnimationFrame?window.requestAnimationFrame(c):setTimeout(c,16)},d=(e,a)=>{if(r.has(e))throw new Error("data is alreaby an observable");if(a&&!t.has(a))throw new Error("rootProxy isn’t an observable");let c;const i=new Proxy(e,{get:(e,r)=>e[r],set(e,r,n){if(e[r]!==n){if(c){if(t.has(n))throw new Error("Can’t nest observables");o.add(a||i)}e[r]=n}return!0},deleteProperty:(e,r)=>r in e&&(delete e[r],o.add(a||i),!0)});return r.add(e),t.set(i,e),(Array.isArray(e)?[...Array(e.length).keys()]:Object.keys(e)).forEach((r=>{const n=e[r];if(t.has(n))throw new Error("Can’t nest observables");(e=>Array.isArray(e)||(e=>!!e&&"object"==typeof e&&e.constructor===s)(e))(n)&&(i[r]=d(n,a||i))})),n.set(i,c={change:new Set,destroy:new Set}),i},i=e=>{if((e=>Array.isArray(e)||(e=>!!e&&"object"==typeof e&&e.constructor===s)(e))(e))return d(e);throw new Error("Only Arrays and plain Objects are observable")},y=(e,r,t)=>{const o=n.get(e);return!(!o||!o[r]||"function"!=typeof t||o[r].has(t))&&(o[r].add(t),!0)},w=(e,r,t)=>{const o=n.get(e);return!(!o||!o[r]||"function"!=typeof t)&&o[r].delete(t)},h=(r,t)=>y(r,e.change,t),l=(r,t)=>w(r,e.change,t),f=e=>{const a=n.get(e);return!!a&&(a.change.clear(),a.destroy.clear(),r.delete(t.get(e)),t.delete(e),n.delete(e),o.delete(e),!0)};c();export{e as ObservableEvents,f as destroy,i as observable,h as observe,w as off,y as on,l as unobserve}; diff --git a/lib/index.js b/lib/index.js index b6176ed..ed667ab 100644 --- a/lib/index.js +++ b/lib/index.js @@ -30,15 +30,15 @@ const tick = () => { observers.destroy.forEach((callback) => callback()); }); destroyedProxies.clear(); - if (typeof window !== "undefined" && window.requestAnimationFrame) + if (typeof window !== 'undefined' && window.requestAnimationFrame) window.requestAnimationFrame(tick); else setTimeout(tick, 16); }; const makeObservableProxy = (data, rootProxy) => { if (observables.has(data)) - throw new Error('Only Arrays and plain Objects are observable'); - if (observablesByProxy.has(data)) + throw new Error('data is alreaby an observable'); + if (rootProxy && !observablesByProxy.has(rootProxy)) throw new Error('rootProxy isn’t an observable'); let observers; const proxy = new Proxy(data, { @@ -65,6 +65,8 @@ const makeObservableProxy = (data, rootProxy) => { return false; } }); + observables.add(data); + observablesByProxy.set(proxy, data); (Array.isArray(data) ? [...Array(data.length).keys()] : Object.keys(data)).forEach(key => { const value = data[key]; if (observablesByProxy.has(value)) @@ -72,8 +74,6 @@ const makeObservableProxy = (data, rootProxy) => { if ( /*#__INLINE__*/canBeObservable(value)) proxy[key] = makeObservableProxy(value, rootProxy || proxy); }); - observables.add(data); - observablesByProxy.set(proxy, data); observersByProxy.set(proxy, observers = { change: new Set(), destroy: new Set() diff --git a/lib/index.mjs b/lib/index.mjs index 9672a6d..c93d59e 100644 --- a/lib/index.mjs +++ b/lib/index.mjs @@ -27,15 +27,15 @@ const tick = () => { observers.destroy.forEach((callback) => callback()); }); destroyedProxies.clear(); - if (typeof window !== "undefined" && window.requestAnimationFrame) + if (typeof window !== 'undefined' && window.requestAnimationFrame) window.requestAnimationFrame(tick); else setTimeout(tick, 16); }; const makeObservableProxy = (data, rootProxy) => { if (observables.has(data)) - throw new Error('Only Arrays and plain Objects are observable'); - if (observablesByProxy.has(data)) + throw new Error('data is alreaby an observable'); + if (rootProxy && !observablesByProxy.has(rootProxy)) throw new Error('rootProxy isn’t an observable'); let observers; const proxy = new Proxy(data, { @@ -62,6 +62,8 @@ const makeObservableProxy = (data, rootProxy) => { return false; } }); + observables.add(data); + observablesByProxy.set(proxy, data); (Array.isArray(data) ? [...Array(data.length).keys()] : Object.keys(data)).forEach(key => { const value = data[key]; if (observablesByProxy.has(value)) @@ -69,8 +71,6 @@ const makeObservableProxy = (data, rootProxy) => { if ( /*#__INLINE__*/canBeObservable(value)) proxy[key] = makeObservableProxy(value, rootProxy || proxy); }); - observables.add(data); - observablesByProxy.set(proxy, data); observersByProxy.set(proxy, observers = { change: new Set(), destroy: new Set() From c8f44d434bfb5373b07aee0a5b249b7c93aa1876 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 22 Mar 2023 18:38:33 -0400 Subject: [PATCH 20/53] Added BROWSER global variable --- global.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/global.d.ts b/global.d.ts index 73436f5..3998ad5 100644 --- a/global.d.ts +++ b/global.d.ts @@ -1,4 +1,5 @@ declare global { + var BROWSER: boolean; var FRAME_TIME: number; } From 99c741a8a262b172994086fa5d8b9692d327723c Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 22 Mar 2023 18:38:54 -0400 Subject: [PATCH 21/53] BROWSER is set to false for testing purposes --- jest.setup.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/jest.setup.ts b/jest.setup.ts index b245498..cc250ed 100644 --- a/jest.setup.ts +++ b/jest.setup.ts @@ -1,3 +1,4 @@ +global.BROWSER = false; global.FRAME_TIME = 16; Object.defineProperty(window, 'navigator', {value: 'node'}); From 91ce06bedc80f3ac1d4b854cb8d478d7529d85d7 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 22 Mar 2023 18:39:36 -0400 Subject: [PATCH 22/53] Use raf or timeout based on BROWSER global --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index fd41bd5..2b273a7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -38,7 +38,7 @@ const tick = (): void => { if(observers) observers.destroy.forEach((callback: ObservableCallback) => callback()); }); destroyedProxies.clear(); - if(typeof window !== 'undefined' && window.requestAnimationFrame) window.requestAnimationFrame(tick); + if(BROWSER) window.requestAnimationFrame(tick); else setTimeout(tick, 16); }; From 4957501ea395e758679f95b36d35cf2eff0cc8cc Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 22 Mar 2023 18:41:04 -0400 Subject: [PATCH 23/53] Added rollup plugin replace --- package-lock.json | 4854 +-------------------------------------------- package.json | 1 + 2 files changed, 35 insertions(+), 4820 deletions(-) diff --git a/package-lock.json b/package-lock.json index ca60373..1f276e1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "@babel/parser": "^7.21.3", "@babel/preset-env": "^7.20.2", "@babel/preset-typescript": "^7.21.0", + "@rollup/plugin-replace": "^5.0.2", "@rollup/plugin-terser": "^0.4.0", "@rollup/plugin-typescript": "^11.0.0", "@types/jest": "^27.5.2", @@ -2269,6 +2270,39 @@ "dev": true, "optional": true }, + "node_modules/@rollup/plugin-replace": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-5.0.2.tgz", + "integrity": "sha512-M9YXNekv/C/iHHK+cvORzfRYfPbq0RDD8r0G+bMiTXjNGKulPnCT9O3Ss46WfhI6ZOCgApOP7xAdmCQJ+U2LAA==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "magic-string": "^0.27.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-replace/node_modules/magic-string": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", + "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.13" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@rollup/plugin-terser": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.0.tgz", @@ -6537,4825 +6571,5 @@ "url": "https://github.com/sponsors/sindresorhus" } } - }, - "dependencies": { - "@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@babel/cli": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.21.0.tgz", - "integrity": "sha512-xi7CxyS8XjSyiwUGCfwf+brtJxjW1/ZTcBUkP10xawIEXLX5HzLn+3aXkgxozcP2UhRhtKTmQurw9Uaes7jZrA==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.17", - "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.3", - "chokidar": "^3.4.0", - "commander": "^4.0.1", - "convert-source-map": "^1.1.0", - "fs-readdir-recursive": "^1.1.0", - "glob": "^7.2.0", - "make-dir": "^2.1.0", - "slash": "^2.0.0" - }, - "dependencies": { - "commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true - }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true - } - } - }, - "@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, - "requires": { - "@babel/highlight": "^7.18.6" - } - }, - "@babel/compat-data": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz", - "integrity": "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==", - "dev": true - }, - "@babel/core": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.3.tgz", - "integrity": "sha512-qIJONzoa/qiHghnm0l1n4i/6IIziDpzqc36FBs4pzMhDUraHqponwJLiAKm1hGLP3OSB/TVNz6rMwVGpwxxySw==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.3", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.3", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.3", - "@babel/types": "^7.21.3", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" - } - }, - "@babel/generator": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz", - "integrity": "sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==", - "dev": true, - "requires": { - "@babel/types": "^7.21.3", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", - "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", - "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", - "dev": true, - "requires": { - "@babel/helper-explode-assignable-expression": "^7.18.6", - "@babel/types": "^7.18.9" - } - }, - "@babel/helper-compilation-targets": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", - "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", - "lru-cache": "^5.1.1", - "semver": "^6.3.0" - } - }, - "@babel/helper-create-class-features-plugin": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.0.tgz", - "integrity": "sha512-Q8wNiMIdwsv5la5SPxNYzzkPnjgC0Sy0i7jLkVOCdllu/xcVNkr3TeZzbHBJrj+XXRqzX5uCyCoV9eu6xUG7KQ==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-member-expression-to-functions": "^7.21.0", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-replace-supers": "^7.20.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/helper-split-export-declaration": "^7.18.6" - } - }, - "@babel/helper-create-regexp-features-plugin": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.21.0.tgz", - "integrity": "sha512-N+LaFW/auRSWdx7SHD/HiARwXQju1vXTW4fKr4u5SgBUTm51OKEjKgj+cs00ggW3kEvNqwErnlwuq7Y3xBe4eg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "regexpu-core": "^5.3.1" - } - }, - "@babel/helper-define-polyfill-provider": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz", - "integrity": "sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==", - "dev": true, - "requires": { - "@babel/helper-compilation-targets": "^7.17.7", - "@babel/helper-plugin-utils": "^7.16.7", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - } - }, - "@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", - "dev": true - }, - "@babel/helper-explode-assignable-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", - "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-function-name": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", - "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", - "dev": true, - "requires": { - "@babel/template": "^7.20.7", - "@babel/types": "^7.21.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.21.0.tgz", - "integrity": "sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q==", - "dev": true, - "requires": { - "@babel/types": "^7.21.0" - } - }, - "@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-module-transforms": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", - "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.2", - "@babel/types": "^7.21.2" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", - "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", - "dev": true - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz", - "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-wrap-function": "^7.18.9", - "@babel/types": "^7.18.9" - } - }, - "@babel/helper-replace-supers": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz", - "integrity": "sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-member-expression-to-functions": "^7.20.7", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.7", - "@babel/types": "^7.20.7" - } - }, - "@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", - "dev": true, - "requires": { - "@babel/types": "^7.20.2" - } - }, - "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz", - "integrity": "sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==", - "dev": true, - "requires": { - "@babel/types": "^7.20.0" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", - "dev": true - }, - "@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", - "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", - "dev": true - }, - "@babel/helper-wrap-function": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz", - "integrity": "sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.19.0", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.5", - "@babel/types": "^7.20.5" - } - }, - "@babel/helpers": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", - "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", - "dev": true, - "requires": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0" - } - }, - "@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@babel/parser": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", - "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==", - "dev": true - }, - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz", - "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.20.7.tgz", - "integrity": "sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-proposal-optional-chaining": "^7.20.7" - } - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", - "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-remap-async-to-generator": "^7.18.9", - "@babel/plugin-syntax-async-generators": "^7.8.4" - } - }, - "@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-proposal-class-static-block": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.21.0.tgz", - "integrity": "sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.21.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-class-static-block": "^7.14.5" - } - }, - "@babel/plugin-proposal-dynamic-import": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", - "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - } - }, - "@babel/plugin-proposal-export-namespace-from": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", - "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - } - }, - "@babel/plugin-proposal-json-strings": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", - "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-json-strings": "^7.8.3" - } - }, - "@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz", - "integrity": "sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - } - }, - "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", - "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - } - }, - "@babel/plugin-proposal-numeric-separator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", - "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - } - }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", - "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.20.7" - } - }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", - "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - } - }, - "@babel/plugin-proposal-optional-chaining": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", - "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - } - }, - "@babel/plugin-proposal-private-methods": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", - "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0.tgz", - "integrity": "sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-create-class-features-plugin": "^7.21.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - } - }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", - "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-syntax-import-assertions": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.20.0.tgz", - "integrity": "sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.19.0" - } - }, - "@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-typescript": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz", - "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.19.0" - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.20.7.tgz", - "integrity": "sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.20.7.tgz", - "integrity": "sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-remap-async-to-generator": "^7.18.9" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", - "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.21.0.tgz", - "integrity": "sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-transform-classes": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.21.0.tgz", - "integrity": "sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-replace-supers": "^7.20.7", - "@babel/helper-split-export-declaration": "^7.18.6", - "globals": "^11.1.0" - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.20.7.tgz", - "integrity": "sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/template": "^7.20.7" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.21.3.tgz", - "integrity": "sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", - "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz", - "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", - "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.21.0.tgz", - "integrity": "sha512-LlUYlydgDkKpIY7mcBWvyPPmMcOphEyYA27Ef4xpbh1IiDNLr0kZsos2nf92vz3IccvJI25QUwp86Eo5s6HmBQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz", - "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==", - "dev": true, - "requires": { - "@babel/helper-compilation-targets": "^7.18.9", - "@babel/helper-function-name": "^7.18.9", - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-literals": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz", - "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-member-expression-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", - "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.20.11.tgz", - "integrity": "sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.2.tgz", - "integrity": "sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-simple-access": "^7.20.2" - } - }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.20.11.tgz", - "integrity": "sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-validator-identifier": "^7.19.1" - } - }, - "@babel/plugin-transform-modules-umd": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", - "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.20.5.tgz", - "integrity": "sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.20.5", - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-transform-new-target": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", - "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", - "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.6" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.21.3.tgz", - "integrity": "sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-transform-property-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", - "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz", - "integrity": "sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2", - "regenerator-transform": "^0.15.1" - } - }, - "@babel/plugin-transform-reserved-words": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", - "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", - "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.20.7.tgz", - "integrity": "sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", - "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz", - "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz", - "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-typescript": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.21.3.tgz", - "integrity": "sha512-RQxPz6Iqt8T0uw/WsJNReuBpWpBqs/n7mNo18sKLoTbMp+UrEekhH+pKSVC7gWz+DNjo9gryfV8YzCiT45RgMw==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-create-class-features-plugin": "^7.21.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-typescript": "^7.20.0" - } - }, - "@babel/plugin-transform-unicode-escapes": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", - "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", - "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/preset-env": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.20.2.tgz", - "integrity": "sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.20.1", - "@babel/helper-compilation-targets": "^7.20.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-validator-option": "^7.18.6", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", - "@babel/plugin-proposal-async-generator-functions": "^7.20.1", - "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-proposal-class-static-block": "^7.18.6", - "@babel/plugin-proposal-dynamic-import": "^7.18.6", - "@babel/plugin-proposal-export-namespace-from": "^7.18.9", - "@babel/plugin-proposal-json-strings": "^7.18.6", - "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", - "@babel/plugin-proposal-numeric-separator": "^7.18.6", - "@babel/plugin-proposal-object-rest-spread": "^7.20.2", - "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", - "@babel/plugin-proposal-optional-chaining": "^7.18.9", - "@babel/plugin-proposal-private-methods": "^7.18.6", - "@babel/plugin-proposal-private-property-in-object": "^7.18.6", - "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.20.0", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.18.6", - "@babel/plugin-transform-async-to-generator": "^7.18.6", - "@babel/plugin-transform-block-scoped-functions": "^7.18.6", - "@babel/plugin-transform-block-scoping": "^7.20.2", - "@babel/plugin-transform-classes": "^7.20.2", - "@babel/plugin-transform-computed-properties": "^7.18.9", - "@babel/plugin-transform-destructuring": "^7.20.2", - "@babel/plugin-transform-dotall-regex": "^7.18.6", - "@babel/plugin-transform-duplicate-keys": "^7.18.9", - "@babel/plugin-transform-exponentiation-operator": "^7.18.6", - "@babel/plugin-transform-for-of": "^7.18.8", - "@babel/plugin-transform-function-name": "^7.18.9", - "@babel/plugin-transform-literals": "^7.18.9", - "@babel/plugin-transform-member-expression-literals": "^7.18.6", - "@babel/plugin-transform-modules-amd": "^7.19.6", - "@babel/plugin-transform-modules-commonjs": "^7.19.6", - "@babel/plugin-transform-modules-systemjs": "^7.19.6", - "@babel/plugin-transform-modules-umd": "^7.18.6", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.19.1", - "@babel/plugin-transform-new-target": "^7.18.6", - "@babel/plugin-transform-object-super": "^7.18.6", - "@babel/plugin-transform-parameters": "^7.20.1", - "@babel/plugin-transform-property-literals": "^7.18.6", - "@babel/plugin-transform-regenerator": "^7.18.6", - "@babel/plugin-transform-reserved-words": "^7.18.6", - "@babel/plugin-transform-shorthand-properties": "^7.18.6", - "@babel/plugin-transform-spread": "^7.19.0", - "@babel/plugin-transform-sticky-regex": "^7.18.6", - "@babel/plugin-transform-template-literals": "^7.18.9", - "@babel/plugin-transform-typeof-symbol": "^7.18.9", - "@babel/plugin-transform-unicode-escapes": "^7.18.10", - "@babel/plugin-transform-unicode-regex": "^7.18.6", - "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.20.2", - "babel-plugin-polyfill-corejs2": "^0.3.3", - "babel-plugin-polyfill-corejs3": "^0.6.0", - "babel-plugin-polyfill-regenerator": "^0.4.1", - "core-js-compat": "^3.25.1", - "semver": "^6.3.0" - } - }, - "@babel/preset-modules": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", - "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - } - }, - "@babel/preset-typescript": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.21.0.tgz", - "integrity": "sha512-myc9mpoVA5m1rF8K8DgLEatOYFDpwC+RkMkjZ0Du6uI62YvDe8uxIEYVs/VCdSJ097nlALiU/yBC7//3nI+hNg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-validator-option": "^7.21.0", - "@babel/plugin-transform-typescript": "^7.21.0" - } - }, - "@babel/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", - "dev": true - }, - "@babel/runtime": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", - "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.11" - } - }, - "@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" - } - }, - "@babel/traverse": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz", - "integrity": "sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.3", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.3", - "@babel/types": "^7.21.3", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz", - "integrity": "sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", - "to-fast-properties": "^2.0.0" - } - }, - "@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - } - }, - "@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true - }, - "@jest/console": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", - "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", - "dev": true, - "requires": { - "@jest/types": "^28.1.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^28.1.3", - "jest-util": "^28.1.3", - "slash": "^3.0.0" - } - }, - "@jest/core": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-28.1.3.tgz", - "integrity": "sha512-CIKBrlaKOzA7YG19BEqCw3SLIsEwjZkeJzf5bdooVnW4bH5cktqe3JX+G2YV1aK5vP8N9na1IGWFzYaTp6k6NA==", - "dev": true, - "requires": { - "@jest/console": "^28.1.3", - "@jest/reporters": "^28.1.3", - "@jest/test-result": "^28.1.3", - "@jest/transform": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^28.1.3", - "jest-config": "^28.1.3", - "jest-haste-map": "^28.1.3", - "jest-message-util": "^28.1.3", - "jest-regex-util": "^28.0.2", - "jest-resolve": "^28.1.3", - "jest-resolve-dependencies": "^28.1.3", - "jest-runner": "^28.1.3", - "jest-runtime": "^28.1.3", - "jest-snapshot": "^28.1.3", - "jest-util": "^28.1.3", - "jest-validate": "^28.1.3", - "jest-watcher": "^28.1.3", - "micromatch": "^4.0.4", - "pretty-format": "^28.1.3", - "rimraf": "^3.0.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", - "dev": true, - "requires": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - } - } - }, - "@jest/environment": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-28.1.3.tgz", - "integrity": "sha512-1bf40cMFTEkKyEf585R9Iz1WayDjHoHqvts0XFYEqyKM3cFWDpeMoqKKTAF9LSYQModPUlh8FKptoM2YcMWAXA==", - "dev": true, - "requires": { - "@jest/fake-timers": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/node": "*", - "jest-mock": "^28.1.3" - } - }, - "@jest/expect": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-28.1.3.tgz", - "integrity": "sha512-lzc8CpUbSoE4dqT0U+g1qODQjBRHPpCPXissXD4mS9+sWQdmmpeJ9zSH1rS1HEkrsMN0fb7nKrJ9giAR1d3wBw==", - "dev": true, - "requires": { - "expect": "^28.1.3", - "jest-snapshot": "^28.1.3" - } - }, - "@jest/expect-utils": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-28.1.3.tgz", - "integrity": "sha512-wvbi9LUrHJLn3NlDW6wF2hvIMtd4JUl2QNVrjq+IBSHirgfrR3o9RnVtxzdEGO2n9JyIWwHnLfby5KzqBGg2YA==", - "dev": true, - "requires": { - "jest-get-type": "^28.0.2" - } - }, - "@jest/fake-timers": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-28.1.3.tgz", - "integrity": "sha512-D/wOkL2POHv52h+ok5Oj/1gOG9HSywdoPtFsRCUmlCILXNn5eIWmcnd3DIiWlJnpGvQtmajqBP95Ei0EimxfLw==", - "dev": true, - "requires": { - "@jest/types": "^28.1.3", - "@sinonjs/fake-timers": "^9.1.2", - "@types/node": "*", - "jest-message-util": "^28.1.3", - "jest-mock": "^28.1.3", - "jest-util": "^28.1.3" - } - }, - "@jest/globals": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-28.1.3.tgz", - "integrity": "sha512-XFU4P4phyryCXu1pbcqMO0GSQcYe1IsalYCDzRNyhetyeyxMcIxa11qPNDpVNLeretItNqEmYYQn1UYz/5x1NA==", - "dev": true, - "requires": { - "@jest/environment": "^28.1.3", - "@jest/expect": "^28.1.3", - "@jest/types": "^28.1.3" - } - }, - "@jest/reporters": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-28.1.3.tgz", - "integrity": "sha512-JuAy7wkxQZVNU/V6g9xKzCGC5LVXx9FDcABKsSXp5MiKPEE2144a/vXTEDoyzjUpZKfVwp08Wqg5A4WfTMAzjg==", - "dev": true, - "requires": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^28.1.3", - "@jest/test-result": "^28.1.3", - "@jest/transform": "^28.1.3", - "@jest/types": "^28.1.3", - "@jridgewell/trace-mapping": "^0.3.13", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^28.1.3", - "jest-util": "^28.1.3", - "jest-worker": "^28.1.3", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "terminal-link": "^2.0.0", - "v8-to-istanbul": "^9.0.1" - } - }, - "@jest/schemas": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", - "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.24.1" - } - }, - "@jest/source-map": { - "version": "28.1.2", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-28.1.2.tgz", - "integrity": "sha512-cV8Lx3BeStJb8ipPHnqVw/IM2VCMWO3crWZzYodSIkxXnRcXJipCdx1JCK0K5MsJJouZQTH73mzf4vgxRaH9ww==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.13", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - } - }, - "@jest/test-result": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.3.tgz", - "integrity": "sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==", - "dev": true, - "requires": { - "@jest/console": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - } - }, - "@jest/test-sequencer": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-28.1.3.tgz", - "integrity": "sha512-NIMPEqqa59MWnDi1kvXXpYbqsfQmSJsIbnd85mdVGkiDfQ9WQQTXOLsvISUfonmnBT+w85WEgneCigEEdHDFxw==", - "dev": true, - "requires": { - "@jest/test-result": "^28.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.1.3", - "slash": "^3.0.0" - } - }, - "@jest/transform": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-28.1.3.tgz", - "integrity": "sha512-u5dT5di+oFI6hfcLOHGTAfmUxFRrjK+vnaP0kkVow9Md/M7V/MxqQMOz/VV25UZO8pzeA9PjfTpOu6BDuwSPQA==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/types": "^28.1.3", - "@jridgewell/trace-mapping": "^0.3.13", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.1.3", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.1.3", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.1" - } - }, - "@jest/types": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", - "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", - "dev": true, - "requires": { - "@jest/schemas": "^28.1.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true - }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true - }, - "@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } - } - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "@nicolo-ribaudo/chokidar-2": { - "version": "2.1.8-no-fsevents.3", - "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz", - "integrity": "sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==", - "dev": true, - "optional": true - }, - "@rollup/plugin-terser": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.0.tgz", - "integrity": "sha512-Ipcf3LPNerey1q9ZMjiaWHlNPEHNU/B5/uh9zXLltfEQ1lVSLLeZSgAtTPWGyw8Ip1guOeq+mDtdOlEj/wNxQw==", - "dev": true, - "requires": { - "serialize-javascript": "^6.0.0", - "smob": "^0.0.6", - "terser": "^5.15.1" - } - }, - "@rollup/plugin-typescript": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-11.0.0.tgz", - "integrity": "sha512-goPyCWBiimk1iJgSTgsehFD5OOFHiAknrRJjqFCudcW8JtWiBlK284Xnn4flqMqg6YAjVG/EE+3aVzrL5qNSzQ==", - "dev": true, - "requires": { - "@rollup/pluginutils": "^5.0.1", - "resolve": "^1.22.1" - } - }, - "@rollup/pluginutils": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", - "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", - "dev": true, - "requires": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^2.3.1" - } - }, - "@sinclair/typebox": { - "version": "0.24.51", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", - "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", - "dev": true - }, - "@sinonjs/commons": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", - "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz", - "integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" - } - }, - "@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true - }, - "@types/babel__core": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz", - "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==", - "dev": true, - "requires": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dev": true, - "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@types/babel__traverse": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", - "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", - "dev": true, - "requires": { - "@babel/types": "^7.3.0" - } - }, - "@types/estree": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", - "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", - "dev": true - }, - "@types/graceful-fs": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", - "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "*" - } - }, - "@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, - "requires": { - "@types/istanbul-lib-report": "*" - } - }, - "@types/jest": { - "version": "27.5.2", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.5.2.tgz", - "integrity": "sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA==", - "dev": true, - "requires": { - "jest-matcher-utils": "^27.0.0", - "pretty-format": "^27.0.0" - } - }, - "@types/jsdom": { - "version": "16.2.15", - "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-16.2.15.tgz", - "integrity": "sha512-nwF87yjBKuX/roqGYerZZM0Nv1pZDMAT5YhOHYeM/72Fic+VEqJh4nyoqoapzJnW3pUlfxPY5FhgsJtM+dRnQQ==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/parse5": "^6.0.3", - "@types/tough-cookie": "*" - } - }, - "@types/node": { - "version": "18.15.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz", - "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==", - "dev": true - }, - "@types/parse5": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-6.0.3.tgz", - "integrity": "sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==", - "dev": true - }, - "@types/prettier": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", - "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", - "dev": true - }, - "@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true - }, - "@types/tough-cookie": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz", - "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==", - "dev": true - }, - "@types/yargs": { - "version": "17.0.22", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.22.tgz", - "integrity": "sha512-pet5WJ9U8yPVRhkwuEIp5ktAeAqRZOq4UdAyWLWzxbtpyXnzbtLdKiXAjJzi/KLmPGS9wk86lUFWZFN6sISo4g==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, - "@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, - "abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "dev": true - }, - "acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true - }, - "acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", - "dev": true, - "requires": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - } - } - }, - "acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "requires": { - "debug": "4" - } - }, - "ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "requires": { - "type-fest": "^0.21.3" - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "babel-jest": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-28.1.3.tgz", - "integrity": "sha512-epUaPOEWMk3cWX0M/sPvCHHCe9fMFAa/9hXEgKP8nFfNl/jlGkE9ucq9NqkZGXLDduCJYS0UvSlPUwC0S+rH6Q==", - "dev": true, - "requires": { - "@jest/transform": "^28.1.3", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^28.1.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - } - }, - "babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - } - }, - "babel-plugin-jest-hoist": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-28.1.3.tgz", - "integrity": "sha512-Ys3tUKAmfnkRUpPdpa98eYrAR0nV+sSFUZZEGuQ2EbFd1y4SOLtD5QDNHAq+bb9a+bbXvYQC4b+ID/THIMcU6Q==", - "dev": true, - "requires": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - } - }, - "babel-plugin-polyfill-corejs2": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz", - "integrity": "sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.17.7", - "@babel/helper-define-polyfill-provider": "^0.3.3", - "semver": "^6.1.1" - } - }, - "babel-plugin-polyfill-corejs3": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz", - "integrity": "sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==", - "dev": true, - "requires": { - "@babel/helper-define-polyfill-provider": "^0.3.3", - "core-js-compat": "^3.25.1" - } - }, - "babel-plugin-polyfill-regenerator": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz", - "integrity": "sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==", - "dev": true, - "requires": { - "@babel/helper-define-polyfill-provider": "^0.3.3" - } - }, - "babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, - "requires": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - } - }, - "babel-preset-jest": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-28.1.3.tgz", - "integrity": "sha512-L+fupJvlWAHbQfn74coNX3zf60LXMJsezNvvx8eIh7iOR1luJ1poxYgQk1F8PYtNq/6QODDHCqsSnTFSWC491A==", - "dev": true, - "requires": { - "babel-plugin-jest-hoist": "^28.1.3", - "babel-preset-current-node-syntax": "^1.0.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "browser-process-hrtime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", - "dev": true - }, - "browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" - } - }, - "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, - "requires": { - "fast-json-stable-stringify": "2.x" - } - }, - "bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "requires": { - "node-int64": "^0.4.0" - } - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001466", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001466.tgz", - "integrity": "sha512-ewtFBSfWjEmxUgNBSZItFSmVtvk9zkwkl1OfRZlKA8slltRN+/C/tuGVrF9styXkN36Yu3+SeJ1qkXxDEyNZ5w==", - "dev": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "optional": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", - "dev": true - }, - "cjs-module-lexer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", - "dev": true - }, - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true - }, - "collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", - "dev": true - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true - }, - "core-js-compat": { - "version": "3.29.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.29.1.tgz", - "integrity": "sha512-QmchCua884D8wWskMX8tW5ydINzd8oSJVx38lx/pVkFGqztxt73GYre3pm/hyYq8bPf+MW5In4I/uRShFDsbrA==", - "dev": true, - "requires": { - "browserslist": "^4.21.5" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "cssom": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", - "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", - "dev": true - }, - "cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, - "requires": { - "cssom": "~0.3.6" - }, - "dependencies": { - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - } - } - }, - "data-urls": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", - "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", - "dev": true, - "requires": { - "abab": "^2.0.6", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^11.0.0" - }, - "dependencies": { - "whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", - "dev": true, - "requires": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" - } - } - } - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "decimal.js": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", - "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", - "dev": true - }, - "dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "deepmerge": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.0.tgz", - "integrity": "sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og==", - "dev": true - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true - }, - "detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true - }, - "diff": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", - "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", - "dev": true - }, - "diff-sequences": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", - "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", - "dev": true - }, - "domexception": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", - "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", - "dev": true, - "requires": { - "webidl-conversions": "^7.0.0" - } - }, - "electron-to-chromium": { - "version": "1.4.332", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.332.tgz", - "integrity": "sha512-c1Vbv5tuUlBFp0mb3mCIjw+REEsgthRgNE8BlbEDKmvzb8rxjcVki6OkQP83vLN34s0XCxpSkq7AZNep1a6xhw==", - "dev": true - }, - "emittery": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", - "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true - }, - "escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "dev": true, - "requires": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true - }, - "expect": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/expect/-/expect-28.1.3.tgz", - "integrity": "sha512-eEh0xn8HlsuOBxFgIss+2mX85VAS4Qy3OSkjV7rlBWljtA4oWH37glVGyOZSZvErDT/yBywZdPGwCXuTvSG85g==", - "dev": true, - "requires": { - "@jest/expect-utils": "^28.1.3", - "jest-get-type": "^28.0.2", - "jest-matcher-utils": "^28.1.3", - "jest-message-util": "^28.1.3", - "jest-util": "^28.1.3" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "diff-sequences": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.1.1.tgz", - "integrity": "sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==", - "dev": true - }, - "jest-diff": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.1.3.tgz", - "integrity": "sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^28.1.1", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.1.3" - } - }, - "jest-matcher-utils": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz", - "integrity": "sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^28.1.3", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.1.3" - } - }, - "pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", - "dev": true, - "requires": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - } - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, - "requires": { - "bser": "2.1.1" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "fs-readdir-recursive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", - "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "optional": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "html-encoding-sniffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", - "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", - "dev": true, - "requires": { - "whatwg-encoding": "^2.0.0" - } - }, - "html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - }, - "import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "optional": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "optional": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "requires": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - } - }, - "istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - } - }, - "istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - } - }, - "istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, - "jest": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest/-/jest-28.1.3.tgz", - "integrity": "sha512-N4GT5on8UkZgH0O5LUavMRV1EDEhNTL0KEfRmDIeZHSV7p2XgLoY9t9VDUgL6o+yfdgYHVxuz81G8oB9VG5uyA==", - "dev": true, - "requires": { - "@jest/core": "^28.1.3", - "@jest/types": "^28.1.3", - "import-local": "^3.0.2", - "jest-cli": "^28.1.3" - } - }, - "jest-changed-files": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-28.1.3.tgz", - "integrity": "sha512-esaOfUWJXk2nfZt9SPyC8gA1kNfdKLkQWyzsMlqq8msYSlNKfmZxfRgZn4Cd4MGVUF+7v6dBs0d5TOAKa7iIiA==", - "dev": true, - "requires": { - "execa": "^5.0.0", - "p-limit": "^3.1.0" - } - }, - "jest-circus": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-28.1.3.tgz", - "integrity": "sha512-cZ+eS5zc79MBwt+IhQhiEp0OeBddpc1n8MBo1nMB8A7oPMKEO+Sre+wHaLJexQUj9Ya/8NOBY0RESUgYjB6fow==", - "dev": true, - "requires": { - "@jest/environment": "^28.1.3", - "@jest/expect": "^28.1.3", - "@jest/test-result": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^0.7.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^28.1.3", - "jest-matcher-utils": "^28.1.3", - "jest-message-util": "^28.1.3", - "jest-runtime": "^28.1.3", - "jest-snapshot": "^28.1.3", - "jest-util": "^28.1.3", - "p-limit": "^3.1.0", - "pretty-format": "^28.1.3", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "diff-sequences": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.1.1.tgz", - "integrity": "sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==", - "dev": true - }, - "jest-diff": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.1.3.tgz", - "integrity": "sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^28.1.1", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.1.3" - } - }, - "jest-matcher-utils": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz", - "integrity": "sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^28.1.3", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.1.3" - } - }, - "pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", - "dev": true, - "requires": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - } - } - }, - "jest-cli": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-28.1.3.tgz", - "integrity": "sha512-roY3kvrv57Azn1yPgdTebPAXvdR2xfezaKKYzVxZ6It/5NCxzJym6tUI5P1zkdWhfUYkxEI9uZWcQdaFLo8mJQ==", - "dev": true, - "requires": { - "@jest/core": "^28.1.3", - "@jest/test-result": "^28.1.3", - "@jest/types": "^28.1.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "import-local": "^3.0.2", - "jest-config": "^28.1.3", - "jest-util": "^28.1.3", - "jest-validate": "^28.1.3", - "prompts": "^2.0.1", - "yargs": "^17.3.1" - } - }, - "jest-config": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-28.1.3.tgz", - "integrity": "sha512-MG3INjByJ0J4AsNBm7T3hsuxKQqFIiRo/AUqb1q9LRKI5UU6Aar9JHbr9Ivn1TVwfUD9KirRoM/T6u8XlcQPHQ==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^28.1.3", - "@jest/types": "^28.1.3", - "babel-jest": "^28.1.3", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^28.1.3", - "jest-environment-node": "^28.1.3", - "jest-get-type": "^28.0.2", - "jest-regex-util": "^28.0.2", - "jest-resolve": "^28.1.3", - "jest-runner": "^28.1.3", - "jest-util": "^28.1.3", - "jest-validate": "^28.1.3", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^28.1.3", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", - "dev": true, - "requires": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - } - } - }, - "jest-diff": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", - "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - }, - "dependencies": { - "jest-get-type": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", - "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", - "dev": true - } - } - }, - "jest-docblock": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-28.1.1.tgz", - "integrity": "sha512-3wayBVNiOYx0cwAbl9rwm5kKFP8yHH3d/fkEaL02NPTkDojPtheGB7HZSFY4wzX+DxyrvhXz0KSCVksmCknCuA==", - "dev": true, - "requires": { - "detect-newline": "^3.0.0" - } - }, - "jest-each": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-28.1.3.tgz", - "integrity": "sha512-arT1z4sg2yABU5uogObVPvSlSMQlDA48owx07BDPAiasW0yYpYHYOo4HHLz9q0BVzDVU4hILFjzJw0So9aCL/g==", - "dev": true, - "requires": { - "@jest/types": "^28.1.3", - "chalk": "^4.0.0", - "jest-get-type": "^28.0.2", - "jest-util": "^28.1.3", - "pretty-format": "^28.1.3" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", - "dev": true, - "requires": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - } - } - }, - "jest-environment-jsdom": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-28.1.3.tgz", - "integrity": "sha512-HnlGUmZRdxfCByd3GM2F100DgQOajUBzEitjGqIREcb45kGjZvRrKUdlaF6escXBdcXNl0OBh+1ZrfeZT3GnAg==", - "dev": true, - "requires": { - "@jest/environment": "^28.1.3", - "@jest/fake-timers": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/jsdom": "^16.2.4", - "@types/node": "*", - "jest-mock": "^28.1.3", - "jest-util": "^28.1.3", - "jsdom": "^19.0.0" - } - }, - "jest-environment-node": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-28.1.3.tgz", - "integrity": "sha512-ugP6XOhEpjAEhGYvp5Xj989ns5cB1K6ZdjBYuS30umT4CQEETaxSiPcZ/E1kFktX4GkrcM4qu07IIlDYX1gp+A==", - "dev": true, - "requires": { - "@jest/environment": "^28.1.3", - "@jest/fake-timers": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/node": "*", - "jest-mock": "^28.1.3", - "jest-util": "^28.1.3" - } - }, - "jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", - "dev": true - }, - "jest-haste-map": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.1.3.tgz", - "integrity": "sha512-3S+RQWDXccXDKSWnkHa/dPwt+2qwA8CJzR61w3FoYCvoo3Pn8tvGcysmMF0Bj0EX5RYvAI2EIvC57OmotfdtKA==", - "dev": true, - "requires": { - "@jest/types": "^28.1.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.1.3", - "jest-worker": "^28.1.3", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - } - }, - "jest-leak-detector": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-28.1.3.tgz", - "integrity": "sha512-WFVJhnQsiKtDEo5lG2mM0v40QWnBM+zMdHHyJs8AWZ7J0QZJS59MsyKeJHWhpBZBH32S48FOVvGyOFT1h0DlqA==", - "dev": true, - "requires": { - "jest-get-type": "^28.0.2", - "pretty-format": "^28.1.3" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", - "dev": true, - "requires": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - } - } - }, - "jest-matcher-utils": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", - "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - }, - "dependencies": { - "jest-get-type": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", - "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", - "dev": true - } - } - }, - "jest-message-util": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", - "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^28.1.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^28.1.3", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", - "dev": true, - "requires": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - } - } - }, - "jest-mock": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-28.1.3.tgz", - "integrity": "sha512-o3J2jr6dMMWYVH4Lh/NKmDXdosrsJgi4AviS8oXLujcjpCMBb1FMsblDnOXKZKfSiHLxYub1eS0IHuRXsio9eA==", - "dev": true, - "requires": { - "@jest/types": "^28.1.3", - "@types/node": "*" - } - }, - "jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true, - "requires": {} - }, - "jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", - "dev": true - }, - "jest-resolve": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-28.1.3.tgz", - "integrity": "sha512-Z1W3tTjE6QaNI90qo/BJpfnvpxtaFTFw5CDgwpyE/Kz8U/06N1Hjf4ia9quUhCh39qIGWF1ZuxFiBiJQwSEYKQ==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.1.3", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^28.1.3", - "jest-validate": "^28.1.3", - "resolve": "^1.20.0", - "resolve.exports": "^1.1.0", - "slash": "^3.0.0" - } - }, - "jest-resolve-dependencies": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.3.tgz", - "integrity": "sha512-qa0QO2Q0XzQoNPouMbCc7Bvtsem8eQgVPNkwn9LnS+R2n8DaVDPL/U1gngC0LTl1RYXJU0uJa2BMC2DbTfFrHA==", - "dev": true, - "requires": { - "jest-regex-util": "^28.0.2", - "jest-snapshot": "^28.1.3" - } - }, - "jest-runner": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-28.1.3.tgz", - "integrity": "sha512-GkMw4D/0USd62OVO0oEgjn23TM+YJa2U2Wu5zz9xsQB1MxWKDOlrnykPxnMsN0tnJllfLPinHTka61u0QhaxBA==", - "dev": true, - "requires": { - "@jest/console": "^28.1.3", - "@jest/environment": "^28.1.3", - "@jest/test-result": "^28.1.3", - "@jest/transform": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.10.2", - "graceful-fs": "^4.2.9", - "jest-docblock": "^28.1.1", - "jest-environment-node": "^28.1.3", - "jest-haste-map": "^28.1.3", - "jest-leak-detector": "^28.1.3", - "jest-message-util": "^28.1.3", - "jest-resolve": "^28.1.3", - "jest-runtime": "^28.1.3", - "jest-util": "^28.1.3", - "jest-watcher": "^28.1.3", - "jest-worker": "^28.1.3", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - } - }, - "jest-runtime": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-28.1.3.tgz", - "integrity": "sha512-NU+881ScBQQLc1JHG5eJGU7Ui3kLKrmwCPPtYsJtBykixrM2OhVQlpMmFWJjMyDfdkGgBMNjXCGB/ebzsgNGQw==", - "dev": true, - "requires": { - "@jest/environment": "^28.1.3", - "@jest/fake-timers": "^28.1.3", - "@jest/globals": "^28.1.3", - "@jest/source-map": "^28.1.2", - "@jest/test-result": "^28.1.3", - "@jest/transform": "^28.1.3", - "@jest/types": "^28.1.3", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.1.3", - "jest-message-util": "^28.1.3", - "jest-mock": "^28.1.3", - "jest-regex-util": "^28.0.2", - "jest-resolve": "^28.1.3", - "jest-snapshot": "^28.1.3", - "jest-util": "^28.1.3", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - } - }, - "jest-snapshot": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-28.1.3.tgz", - "integrity": "sha512-4lzMgtiNlc3DU/8lZfmqxN3AYD6GGLbl+72rdBpXvcV+whX7mDrREzkPdp2RnmfIiWBg1YbuFSkXduF2JcafJg==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^28.1.3", - "@jest/transform": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/babel__traverse": "^7.0.6", - "@types/prettier": "^2.1.5", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^28.1.3", - "graceful-fs": "^4.2.9", - "jest-diff": "^28.1.3", - "jest-get-type": "^28.0.2", - "jest-haste-map": "^28.1.3", - "jest-matcher-utils": "^28.1.3", - "jest-message-util": "^28.1.3", - "jest-util": "^28.1.3", - "natural-compare": "^1.4.0", - "pretty-format": "^28.1.3", - "semver": "^7.3.5" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "diff-sequences": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.1.1.tgz", - "integrity": "sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==", - "dev": true - }, - "jest-diff": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.1.3.tgz", - "integrity": "sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^28.1.1", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.1.3" - } - }, - "jest-matcher-utils": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz", - "integrity": "sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^28.1.3", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.1.3" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", - "dev": true, - "requires": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "jest-util": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", - "dev": true, - "requires": { - "@jest/types": "^28.1.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "jest-validate": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-28.1.3.tgz", - "integrity": "sha512-SZbOGBWEsaTxBGCOpsRWlXlvNkvTkY0XxRfh7zYmvd8uL5Qzyg0CHAXiXKROflh801quA6+/DsT4ODDthOC/OA==", - "dev": true, - "requires": { - "@jest/types": "^28.1.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^28.0.2", - "leven": "^3.1.0", - "pretty-format": "^28.1.3" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", - "dev": true, - "requires": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - } - } - }, - "jest-watcher": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.3.tgz", - "integrity": "sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==", - "dev": true, - "requires": { - "@jest/test-result": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.10.2", - "jest-util": "^28.1.3", - "string-length": "^4.0.1" - } - }, - "jest-worker": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.3.tgz", - "integrity": "sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jsdom": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-19.0.0.tgz", - "integrity": "sha512-RYAyjCbxy/vri/CfnjUWJQQtZ3LKlLnDqj+9XLNnJPgEGeirZs3hllKR20re8LUZ6o1b1X4Jat+Qd26zmP41+A==", - "dev": true, - "requires": { - "abab": "^2.0.5", - "acorn": "^8.5.0", - "acorn-globals": "^6.0.0", - "cssom": "^0.5.0", - "cssstyle": "^2.3.0", - "data-urls": "^3.0.1", - "decimal.js": "^10.3.1", - "domexception": "^4.0.0", - "escodegen": "^2.0.0", - "form-data": "^4.0.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^3.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^2.0.0", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^10.0.0", - "ws": "^8.2.3", - "xml-name-validator": "^4.0.0" - } - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true - }, - "kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true - }, - "lodash.hasin": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/lodash.hasin/-/lodash.hasin-4.5.2.tgz", - "integrity": "sha512-AFAitwTSq1Ka/1J9uBaVxpLBP5OI3INQvkl4wKcgIYxoA0S3aqO1QWXHR9aCcOrWtPFqP7GzlFncZfe0Jz0kNw==", - "dev": true - }, - "lodash.isempty": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", - "integrity": "sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg==", - "dev": true - }, - "lodash.isnil": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz", - "integrity": "sha512-up2Mzq3545mwVnMhTDMdfoG1OurpA/s5t88JmQX809eH3C8491iu2sfKhTfhQtKY78oPNhiaHJUpT/dUDAAtng==", - "dev": true - }, - "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 - }, - "lodash.omitby": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.omitby/-/lodash.omitby-4.6.0.tgz", - "integrity": "sha512-5OrRcIVR75M288p4nbI2WLAf3ndw2GD9fyNv3Bc15+WCxJDdZ4lYndSxGd7hnG6PVjiJTeJE2dHEGhIuKGicIQ==", - "dev": true - }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "magic-string": { - "version": "0.26.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.7.tgz", - "integrity": "sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==", - "dev": true, - "requires": { - "sourcemap-codec": "^1.4.8" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "requires": { - "tmpl": "1.0.5" - } - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "requires": { - "mime-db": "1.52.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true - }, - "node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", - "dev": true - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "nwsapi": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.2.tgz", - "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - }, - "dependencies": { - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - } - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "dev": true - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - } - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true - }, - "prettier": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.4.tgz", - "integrity": "sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw==", - "dev": true - }, - "pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "requires": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - } - }, - "psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true - }, - "punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true - }, - "querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "optional": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true - }, - "regenerate-unicode-properties": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", - "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", - "dev": true, - "requires": { - "regenerate": "^1.4.2" - } - }, - "regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "dev": true - }, - "regenerator-transform": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz", - "integrity": "sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.8.4" - } - }, - "regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", - "dev": true, - "requires": { - "@babel/regjsgen": "^0.8.0", - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" - } - }, - "regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "dev": true - } - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, - "resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, - "requires": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "requires": { - "resolve-from": "^5.0.0" - } - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - }, - "resolve.exports": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.1.tgz", - "integrity": "sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "rollup": { - "version": "3.19.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.19.1.tgz", - "integrity": "sha512-lAbrdN7neYCg/8WaoWn/ckzCtz+jr70GFfYdlf50OF7387HTg+wiuiqJRFYawwSPpqfqDNYqK7smY/ks2iAudg==", - "dev": true, - "requires": { - "fsevents": "~2.3.2" - } - }, - "rollup-plugin-prettier": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-prettier/-/rollup-plugin-prettier-3.0.0.tgz", - "integrity": "sha512-E0UqeVX1F+ATrHsXKXIywddjK+iFKOeOGI/drZY/wVq/xfHPjghviIhsFz7I0Wfuzp8jeN+4L7kVwQ/X84mOBw==", - "dev": true, - "requires": { - "@types/prettier": "^1.0.0 || ^2.0.0", - "diff": "5.1.0", - "lodash.hasin": "4.5.2", - "lodash.isempty": "4.4.0", - "lodash.isnil": "4.0.0", - "lodash.omitby": "4.6.0", - "magic-string": "0.26.7" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", - "dev": true, - "requires": { - "xmlchars": "^2.2.0" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "smob": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/smob/-/smob-0.0.6.tgz", - "integrity": "sha512-V21+XeNni+tTyiST1MHsa84AQhT1aFZipzPpOFAVB8DkHzwJyjjAmt9bgwnuZiZWnIbMo2duE29wybxv/7HWUw==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, - "requires": { - "escape-string-regexp": "^2.0.0" - } - }, - "string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "requires": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "supports-hyperlinks": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", - "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", - "dev": true, - "requires": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, - "terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" - } - }, - "terser": { - "version": "5.16.6", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.6.tgz", - "integrity": "sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg==", - "dev": true, - "requires": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "dependencies": { - "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, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - } - } - }, - "test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - } - }, - "tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "tough-cookie": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz", - "integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==", - "dev": true, - "requires": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - } - }, - "tr46": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", - "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", - "dev": true, - "requires": { - "punycode": "^2.1.1" - } - }, - "ts-jest": { - "version": "28.0.8", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-28.0.8.tgz", - "integrity": "sha512-5FaG0lXmRPzApix8oFG8RKjAz4ehtm8yMKOTy5HX3fY6W8kmvOrmcY0hKDElW52FJov+clhUbrKAqofnj4mXTg==", - "dev": true, - "requires": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^28.0.0", - "json5": "^2.2.1", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "7.x", - "yargs-parser": "^21.0.1" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", - "dev": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true - }, - "typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "dev": true - }, - "unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "dev": true - }, - "unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, - "requires": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - } - }, - "unicode-match-property-value-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", - "dev": true - }, - "unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "dev": true - }, - "universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true - }, - "update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", - "dev": true, - "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - } - }, - "url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "requires": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "v8-to-istanbul": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", - "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" - } - }, - "w3c-hr-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", - "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", - "dev": true, - "requires": { - "browser-process-hrtime": "^1.0.0" - } - }, - "w3c-xmlserializer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-3.0.0.tgz", - "integrity": "sha512-3WFqGEgSXIyGhOmAFtlicJNMjEps8b1MG31NCA0/vOF9+nKMUW1ckhi9cnNHmf88Rzw5V+dwIwsm2C7X8k9aQg==", - "dev": true, - "requires": { - "xml-name-validator": "^4.0.0" - } - }, - "walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "requires": { - "makeerror": "1.0.12" - } - }, - "webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true - }, - "whatwg-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", - "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", - "dev": true, - "requires": { - "iconv-lite": "0.6.3" - } - }, - "whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", - "dev": true - }, - "whatwg-url": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-10.0.0.tgz", - "integrity": "sha512-CLxxCmdUby142H5FZzn4D8ikO1cmypvXVQktsgosNy4a4BHrDHeciBBGZhb0bNoR5/MltoCatso+vFjjGx8t0w==", - "dev": true, - "requires": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - } - }, - "ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "dev": true, - "requires": {} - }, - "xml-name-validator": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", - "dev": true - }, - "xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", - "dev": true, - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } } } diff --git a/package.json b/package.json index 00a4ebf..a77c037 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "@babel/parser": "^7.21.3", "@babel/preset-env": "^7.20.2", "@babel/preset-typescript": "^7.21.0", + "@rollup/plugin-replace": "^5.0.2", "@rollup/plugin-terser": "^0.4.0", "@rollup/plugin-typescript": "^11.0.0", "@types/jest": "^27.5.2", From 9faf5325be006d653ba8a99c3839b2d6a909f2c5 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 22 Mar 2023 18:41:18 -0400 Subject: [PATCH 24/53] Modified build script --- package.json | 4 +-- rollup.config.mjs | 67 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index a77c037..4420a99 100644 --- a/package.json +++ b/package.json @@ -10,9 +10,7 @@ "test": "test" }, "scripts": { - "mjs": "tsc -d && mv lib/index.js lib/index.mjs", - "cjs": "tsc -m commonjs", - "build": "npm run mjs && npm run cjs && rollup --config", + "build": "rollup --config", "test": "jest --coverage" }, "repository": { diff --git a/rollup.config.mjs b/rollup.config.mjs index 3b26dd2..b3afe1c 100644 --- a/rollup.config.mjs +++ b/rollup.config.mjs @@ -1,3 +1,4 @@ +import replace from '@rollup/plugin-replace'; import typescript from '@rollup/plugin-typescript'; import terser from '@rollup/plugin-terser'; import prettier from 'rollup-plugin-prettier'; @@ -5,7 +6,7 @@ import prettier from 'rollup-plugin-prettier'; const banner = '/*! simple observable proxy v' + process.env.npm_package_version + ' | MIT License | © 2022 Aleph1 Technologies Inc */'; export default [ - // production build + // browser build { input: 'src/index.ts', output: { @@ -15,6 +16,10 @@ export default [ banner }, plugins: [ + replace({ + preventAssignment: true, + BROWSER: true + }), typescript({ compilerOptions: { target: 'es6' @@ -28,7 +33,7 @@ export default [ prettier() ] }, - // minified production build + // browser build minified { input: 'src/index.ts', output: { @@ -38,6 +43,10 @@ export default [ banner }, plugins: [ + replace({ + preventAssignment: true, + BROWSER: true + }), typescript({ compilerOptions: { target: 'es6' @@ -47,5 +56,59 @@ export default [ toplevel: true }) ] + }, + // typescript commonJS + { + input: 'src/index.ts', + output: { + file: 'lib/index.js', + exports: 'named', + format: 'cjs', + banner + }, + plugins: [ + replace({ + preventAssignment: true, + BROWSER: false + }), + typescript({ + compilerOptions: { + target: 'es6' + } + }), + terser({ + mangle: false, + toplevel: true, + module: true + }), + prettier() + ] + }, + // typescript commonJS + { + input: 'src/index.ts', + output: { + file: 'lib/index.mjs', + exports: 'named', + format: 'esm', + banner + }, + plugins: [ + replace({ + preventAssignment: true, + BROWSER: false + }), + typescript({ + compilerOptions: { + target: 'es6' + } + }), + terser({ + mangle: false, + toplevel: true, + module: true + }), + prettier() + ] } ]; \ No newline at end of file From ad2bc5e85b5e580d81e353811f040aa117ee5659 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 22 Mar 2023 18:41:30 -0400 Subject: [PATCH 25/53] Updated note regarding file size --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 32160cf..a3c818a 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ For objects, changing values, as well as adding, editing, or deleting keys results in a callback signal. For arrays changing values, direct modification using \[\], methods that change the array (pop, push, shift, unshift, etc.), or modifying length results in a callback signal. Multiple observers can be created per observable, and all signals are queued and sent using requestAnimationFrame in the browser, and an interval of 16 milliseconds in a node environment. -Simple Observable Proxy is written in TypeScript and compiles as CommonJS and ESM. It is intended to be a very small library (approximately 700 bytes when minified and gzipped), and, as such, it does not report on specific differences between the current and prior state of the observed object or array. +Simple Observable Proxy is written in TypeScript and compiles as CommonJS and ESM. It is intended to be a very small library (less than 800 bytes when minified and gzipped), and, as such, it does not report on specific differences between the current and prior state of the observed object or array. ## Installation From b21aef71494bab1e91ab6ce701fbef346aa6dbdf Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 22 Mar 2023 18:41:36 -0400 Subject: [PATCH 26/53] Built latest version --- dist/simple-observable-proxy.js | 4 +- dist/simple-observable-proxy.min.js | 2 +- lib/index.js | 222 ++++++++++++++-------------- lib/index.mjs | 209 +++++++++++++------------- 4 files changed, 215 insertions(+), 222 deletions(-) diff --git a/dist/simple-observable-proxy.js b/dist/simple-observable-proxy.js index 2aa5eaa..a5ea18f 100644 --- a/dist/simple-observable-proxy.js +++ b/dist/simple-observable-proxy.js @@ -17,9 +17,7 @@ const ObservableEvents = { change: "change", destroy: "destroy" }, observers && observers.destroy.forEach((callback) => callback()); }), destroyedProxies.clear(), - "undefined" != typeof window && window.requestAnimationFrame - ? window.requestAnimationFrame(tick) - : setTimeout(tick, 16); + window.requestAnimationFrame(tick); }, makeObservableProxy = (data, rootProxy) => { if (observables.has(data)) throw new Error("data is alreaby an observable"); diff --git a/dist/simple-observable-proxy.min.js b/dist/simple-observable-proxy.min.js index 2bb25a4..2e342a0 100644 --- a/dist/simple-observable-proxy.min.js +++ b/dist/simple-observable-proxy.min.js @@ -1,2 +1,2 @@ /*! simple observable proxy v2.0.0 | MIT License | © 2022 Aleph1 Technologies Inc */ -const e={change:"change",destroy:"destroy"},r=new Set,t=new Map,n=new Map,o=new Set,a=new Set,s={}.constructor,c=()=>{o.forEach((e=>{const r=n.get(e);r&&r.change.forEach((e=>e()))})),o.clear(),a.forEach((e=>{const r=n.get(e);r&&r.destroy.forEach((e=>e()))})),a.clear(),"undefined"!=typeof window&&window.requestAnimationFrame?window.requestAnimationFrame(c):setTimeout(c,16)},d=(e,a)=>{if(r.has(e))throw new Error("data is alreaby an observable");if(a&&!t.has(a))throw new Error("rootProxy isn’t an observable");let c;const i=new Proxy(e,{get:(e,r)=>e[r],set(e,r,n){if(e[r]!==n){if(c){if(t.has(n))throw new Error("Can’t nest observables");o.add(a||i)}e[r]=n}return!0},deleteProperty:(e,r)=>r in e&&(delete e[r],o.add(a||i),!0)});return r.add(e),t.set(i,e),(Array.isArray(e)?[...Array(e.length).keys()]:Object.keys(e)).forEach((r=>{const n=e[r];if(t.has(n))throw new Error("Can’t nest observables");(e=>Array.isArray(e)||(e=>!!e&&"object"==typeof e&&e.constructor===s)(e))(n)&&(i[r]=d(n,a||i))})),n.set(i,c={change:new Set,destroy:new Set}),i},i=e=>{if((e=>Array.isArray(e)||(e=>!!e&&"object"==typeof e&&e.constructor===s)(e))(e))return d(e);throw new Error("Only Arrays and plain Objects are observable")},y=(e,r,t)=>{const o=n.get(e);return!(!o||!o[r]||"function"!=typeof t||o[r].has(t))&&(o[r].add(t),!0)},w=(e,r,t)=>{const o=n.get(e);return!(!o||!o[r]||"function"!=typeof t)&&o[r].delete(t)},h=(r,t)=>y(r,e.change,t),l=(r,t)=>w(r,e.change,t),f=e=>{const a=n.get(e);return!!a&&(a.change.clear(),a.destroy.clear(),r.delete(t.get(e)),t.delete(e),n.delete(e),o.delete(e),!0)};c();export{e as ObservableEvents,f as destroy,i as observable,h as observe,w as off,y as on,l as unobserve}; +const e={change:"change",destroy:"destroy"},r=new Set,t=new Map,n=new Map,o=new Set,a=new Set,s={}.constructor,c=()=>{o.forEach((e=>{const r=n.get(e);r&&r.change.forEach((e=>e()))})),o.clear(),a.forEach((e=>{const r=n.get(e);r&&r.destroy.forEach((e=>e()))})),a.clear(),window.requestAnimationFrame(c)},y=(e,a)=>{if(r.has(e))throw new Error("data is alreaby an observable");if(a&&!t.has(a))throw new Error("rootProxy isn’t an observable");let c;const d=new Proxy(e,{get:(e,r)=>e[r],set(e,r,n){if(e[r]!==n){if(c){if(t.has(n))throw new Error("Can’t nest observables");o.add(a||d)}e[r]=n}return!0},deleteProperty:(e,r)=>r in e&&(delete e[r],o.add(a||d),!0)});return r.add(e),t.set(d,e),(Array.isArray(e)?[...Array(e.length).keys()]:Object.keys(e)).forEach((r=>{const n=e[r];if(t.has(n))throw new Error("Can’t nest observables");(e=>Array.isArray(e)||(e=>!!e&&"object"==typeof e&&e.constructor===s)(e))(n)&&(d[r]=y(n,a||d))})),n.set(d,c={change:new Set,destroy:new Set}),d},d=e=>{if((e=>Array.isArray(e)||(e=>!!e&&"object"==typeof e&&e.constructor===s)(e))(e))return y(e);throw new Error("Only Arrays and plain Objects are observable")},h=(e,r,t)=>{const o=n.get(e);return!(!o||!o[r]||"function"!=typeof t||o[r].has(t))&&(o[r].add(t),!0)},l=(e,r,t)=>{const o=n.get(e);return!(!o||!o[r]||"function"!=typeof t)&&o[r].delete(t)},w=(r,t)=>h(r,e.change,t),i=(r,t)=>l(r,e.change,t),f=e=>{const a=n.get(e);return!!a&&(a.change.clear(),a.destroy.clear(),r.delete(t.get(e)),t.delete(e),n.delete(e),o.delete(e),!0)};c();export{e as ObservableEvents,f as destroy,d as observable,w as observe,l as off,h as on,i as unobserve}; diff --git a/lib/index.js b/lib/index.js index ed667ab..ec439ba 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,125 +1,119 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.destroy = exports.unobserve = exports.observe = exports.off = exports.on = exports.observable = exports.ObservableEvents = void 0; -exports.ObservableEvents = { - change: 'change', - destroy: 'destroy', -}; -// data that is being observed -const observables = new Set(); -// original data for each proxy -const observablesByProxy = new Map(); -// observers for each proxy -const observersByProxy = new Map(); -// collections to call on tick -const changedProxies = new Set(); -const destroyedProxies = new Set(); -const plainObjectConstructor = {}.constructor; -const isPlainObject = (data) => !!data && typeof data === 'object' && data.constructor === plainObjectConstructor; -const canBeObservable = (data) => Array.isArray(data) || /*#__INLINE__*/ isPlainObject(data); -const tick = () => { - changedProxies.forEach(proxy => { +/*! simple observable proxy v2.0.0 | MIT License | © 2022 Aleph1 Technologies Inc */ +const ObservableEvents = { change: "change", destroy: "destroy" }, + observables = new Set(), + observablesByProxy = new Map(), + observersByProxy = new Map(), + changedProxies = new Set(), + destroyedProxies = new Set(), + plainObjectConstructor = {}.constructor, + tick = () => { + changedProxies.forEach((proxy) => { + const observers = observersByProxy.get(proxy); + observers && observers.change.forEach((callback) => callback()); + }), + changedProxies.clear(), + destroyedProxies.forEach((proxy) => { const observers = observersByProxy.get(proxy); - if (observers) - observers.change.forEach((callback) => callback()); - }); - changedProxies.clear(); - destroyedProxies.forEach(proxy => { - const observers = observersByProxy.get(proxy); - if (observers) - observers.destroy.forEach((callback) => callback()); - }); - destroyedProxies.clear(); - if (typeof window !== 'undefined' && window.requestAnimationFrame) - window.requestAnimationFrame(tick); - else - setTimeout(tick, 16); -}; -const makeObservableProxy = (data, rootProxy) => { - if (observables.has(data)) - throw new Error('data is alreaby an observable'); + observers && observers.destroy.forEach((callback) => callback()); + }), + destroyedProxies.clear(), + setTimeout(tick, 16); + }, + makeObservableProxy = (data, rootProxy) => { + if (observables.has(data)) throw new Error("data is alreaby an observable"); if (rootProxy && !observablesByProxy.has(rootProxy)) - throw new Error('rootProxy isn’t an observable'); + throw new Error("rootProxy isn’t an observable"); let observers; const proxy = new Proxy(data, { - get(target, key) { - return target[key]; - }, - set(target, key, value) { - if (target[key] !== value) { - if (observers) { - if (observablesByProxy.has(value)) - throw new Error('Can’t nest observables'); - changedProxies.add(rootProxy || proxy); - } - target[key] = value; - } - return true; - }, - deleteProperty(target, key) { - if (key in target) { - delete target[key]; - changedProxies.add(rootProxy || proxy); - return true; - } - return false; + get: (target, key) => target[key], + set(target, key, value) { + if (target[key] !== value) { + if (observers) { + if (observablesByProxy.has(value)) + throw new Error("Can’t nest observables"); + changedProxies.add(rootProxy || proxy); + } + target[key] = value; } + return !0; + }, + deleteProperty: (target, key) => + key in target && + (delete target[key], changedProxies.add(rootProxy || proxy), !0), }); - observables.add(data); - observablesByProxy.set(proxy, data); - (Array.isArray(data) ? [...Array(data.length).keys()] : Object.keys(data)).forEach(key => { + return ( + observables.add(data), + observablesByProxy.set(proxy, data), + (Array.isArray(data) + ? [...Array(data.length).keys()] + : Object.keys(data) + ).forEach((key) => { const value = data[key]; if (observablesByProxy.has(value)) - throw new Error('Can’t nest observables'); - if ( /*#__INLINE__*/canBeObservable(value)) - proxy[key] = makeObservableProxy(value, rootProxy || proxy); - }); - observersByProxy.set(proxy, observers = { - change: new Set(), - destroy: new Set() - }); - return proxy; -}; -const observable = (data) => { - if ( /*#__INLINE__*/canBeObservable(data)) - return makeObservableProxy(data); - else - throw new Error('Only Arrays and plain Objects are observable'); -}; -exports.observable = observable; -const on = (observableProxy, eventType, callback) => { + throw new Error("Can’t nest observables"); + ((data) => + Array.isArray(data) || + ((data) => + !!data && + "object" == typeof data && + data.constructor === plainObjectConstructor)(data))(value) && + (proxy[key] = makeObservableProxy(value, rootProxy || proxy)); + }), + observersByProxy.set( + proxy, + (observers = { change: new Set(), destroy: new Set() }) + ), + proxy + ); + }, + on = (observableProxy, eventType, callback) => { const observers = observersByProxy.get(observableProxy); - if (observers && observers[eventType] && typeof callback === 'function' && !observers[eventType].has(callback)) { - observers[eventType].add(callback); - return true; - } - return false; -}; -exports.on = on; -const off = (observableProxy, eventType, callback) => { + return ( + !( + !observers || + !observers[eventType] || + "function" != typeof callback || + observers[eventType].has(callback) + ) && (observers[eventType].add(callback), !0) + ); + }, + off = (observableProxy, eventType, callback) => { const observers = observersByProxy.get(observableProxy); - if (observers && observers[eventType] && typeof callback === 'function') - return observers[eventType].delete(callback); - return false; -}; -exports.off = off; -// deprecated and to be removed in 3.0 -const observe = (observableProxy, callback) => (0, exports.on)(observableProxy, exports.ObservableEvents.change, callback); -exports.observe = observe; -const unobserve = (observableProxy, callback) => (0, exports.off)(observableProxy, exports.ObservableEvents.change, callback); -exports.unobserve = unobserve; -const destroy = (observableProxy) => { + return ( + !(!observers || !observers[eventType] || "function" != typeof callback) && + observers[eventType].delete(callback) + ); + }; +tick(), + (exports.ObservableEvents = ObservableEvents), + (exports.destroy = (observableProxy) => { const observers = observersByProxy.get(observableProxy); - if (observers) { - observers.change.clear(); - observers.destroy.clear(); - observables.delete(observablesByProxy.get(observableProxy)); - observablesByProxy.delete(observableProxy); - observersByProxy.delete(observableProxy); - changedProxies.delete(observableProxy); - return true; - } - return false; -}; -exports.destroy = destroy; -tick(); + return ( + !!observers && + (observers.change.clear(), + observers.destroy.clear(), + observables.delete(observablesByProxy.get(observableProxy)), + observablesByProxy.delete(observableProxy), + observersByProxy.delete(observableProxy), + changedProxies.delete(observableProxy), + !0) + ); + }), + (exports.observable = (data) => { + if ( + ((data) => + Array.isArray(data) || + ((data) => + !!data && + "object" == typeof data && + data.constructor === plainObjectConstructor)(data))(data) + ) + return makeObservableProxy(data); + throw new Error("Only Arrays and plain Objects are observable"); + }), + (exports.observe = (observableProxy, callback) => + on(observableProxy, ObservableEvents.change, callback)), + (exports.off = off), + (exports.on = on), + (exports.unobserve = (observableProxy, callback) => + off(observableProxy, ObservableEvents.change, callback)); diff --git a/lib/index.mjs b/lib/index.mjs index c93d59e..86aa210 100644 --- a/lib/index.mjs +++ b/lib/index.mjs @@ -1,116 +1,117 @@ -export const ObservableEvents = { - change: 'change', - destroy: 'destroy', -}; -// data that is being observed -const observables = new Set(); -// original data for each proxy -const observablesByProxy = new Map(); -// observers for each proxy -const observersByProxy = new Map(); -// collections to call on tick -const changedProxies = new Set(); -const destroyedProxies = new Set(); -const plainObjectConstructor = {}.constructor; -const isPlainObject = (data) => !!data && typeof data === 'object' && data.constructor === plainObjectConstructor; -const canBeObservable = (data) => Array.isArray(data) || /*#__INLINE__*/ isPlainObject(data); -const tick = () => { - changedProxies.forEach(proxy => { +/*! simple observable proxy v2.0.0 | MIT License | © 2022 Aleph1 Technologies Inc */ +const ObservableEvents = { change: "change", destroy: "destroy" }, + observables = new Set(), + observablesByProxy = new Map(), + observersByProxy = new Map(), + changedProxies = new Set(), + destroyedProxies = new Set(), + plainObjectConstructor = {}.constructor, + tick = () => { + changedProxies.forEach((proxy) => { + const observers = observersByProxy.get(proxy); + observers && observers.change.forEach((callback) => callback()); + }), + changedProxies.clear(), + destroyedProxies.forEach((proxy) => { const observers = observersByProxy.get(proxy); - if (observers) - observers.change.forEach((callback) => callback()); - }); - changedProxies.clear(); - destroyedProxies.forEach(proxy => { - const observers = observersByProxy.get(proxy); - if (observers) - observers.destroy.forEach((callback) => callback()); - }); - destroyedProxies.clear(); - if (typeof window !== 'undefined' && window.requestAnimationFrame) - window.requestAnimationFrame(tick); - else - setTimeout(tick, 16); -}; -const makeObservableProxy = (data, rootProxy) => { - if (observables.has(data)) - throw new Error('data is alreaby an observable'); + observers && observers.destroy.forEach((callback) => callback()); + }), + destroyedProxies.clear(), + setTimeout(tick, 16); + }, + makeObservableProxy = (data, rootProxy) => { + if (observables.has(data)) throw new Error("data is alreaby an observable"); if (rootProxy && !observablesByProxy.has(rootProxy)) - throw new Error('rootProxy isn’t an observable'); + throw new Error("rootProxy isn’t an observable"); let observers; const proxy = new Proxy(data, { - get(target, key) { - return target[key]; - }, - set(target, key, value) { - if (target[key] !== value) { - if (observers) { - if (observablesByProxy.has(value)) - throw new Error('Can’t nest observables'); - changedProxies.add(rootProxy || proxy); - } - target[key] = value; - } - return true; - }, - deleteProperty(target, key) { - if (key in target) { - delete target[key]; - changedProxies.add(rootProxy || proxy); - return true; - } - return false; + get: (target, key) => target[key], + set(target, key, value) { + if (target[key] !== value) { + if (observers) { + if (observablesByProxy.has(value)) + throw new Error("Can’t nest observables"); + changedProxies.add(rootProxy || proxy); + } + target[key] = value; } + return !0; + }, + deleteProperty: (target, key) => + key in target && + (delete target[key], changedProxies.add(rootProxy || proxy), !0), }); - observables.add(data); - observablesByProxy.set(proxy, data); - (Array.isArray(data) ? [...Array(data.length).keys()] : Object.keys(data)).forEach(key => { + return ( + observables.add(data), + observablesByProxy.set(proxy, data), + (Array.isArray(data) + ? [...Array(data.length).keys()] + : Object.keys(data) + ).forEach((key) => { const value = data[key]; if (observablesByProxy.has(value)) - throw new Error('Can’t nest observables'); - if ( /*#__INLINE__*/canBeObservable(value)) - proxy[key] = makeObservableProxy(value, rootProxy || proxy); - }); - observersByProxy.set(proxy, observers = { - change: new Set(), - destroy: new Set() - }); - return proxy; -}; -export const observable = (data) => { - if ( /*#__INLINE__*/canBeObservable(data)) - return makeObservableProxy(data); - else - throw new Error('Only Arrays and plain Objects are observable'); -}; -export const on = (observableProxy, eventType, callback) => { + throw new Error("Can’t nest observables"); + ((data) => + Array.isArray(data) || + ((data) => + !!data && + "object" == typeof data && + data.constructor === plainObjectConstructor)(data))(value) && + (proxy[key] = makeObservableProxy(value, rootProxy || proxy)); + }), + observersByProxy.set( + proxy, + (observers = { change: new Set(), destroy: new Set() }) + ), + proxy + ); + }, + observable = (data) => { + if ( + ((data) => + Array.isArray(data) || + ((data) => + !!data && + "object" == typeof data && + data.constructor === plainObjectConstructor)(data))(data) + ) + return makeObservableProxy(data); + throw new Error("Only Arrays and plain Objects are observable"); + }, + on = (observableProxy, eventType, callback) => { const observers = observersByProxy.get(observableProxy); - if (observers && observers[eventType] && typeof callback === 'function' && !observers[eventType].has(callback)) { - observers[eventType].add(callback); - return true; - } - return false; -}; -export const off = (observableProxy, eventType, callback) => { + return ( + !( + !observers || + !observers[eventType] || + "function" != typeof callback || + observers[eventType].has(callback) + ) && (observers[eventType].add(callback), !0) + ); + }, + off = (observableProxy, eventType, callback) => { const observers = observersByProxy.get(observableProxy); - if (observers && observers[eventType] && typeof callback === 'function') - return observers[eventType].delete(callback); - return false; -}; -// deprecated and to be removed in 3.0 -export const observe = (observableProxy, callback) => on(observableProxy, ObservableEvents.change, callback); -export const unobserve = (observableProxy, callback) => off(observableProxy, ObservableEvents.change, callback); -export const destroy = (observableProxy) => { + return ( + !(!observers || !observers[eventType] || "function" != typeof callback) && + observers[eventType].delete(callback) + ); + }, + observe = (observableProxy, callback) => + on(observableProxy, ObservableEvents.change, callback), + unobserve = (observableProxy, callback) => + off(observableProxy, ObservableEvents.change, callback), + destroy = (observableProxy) => { const observers = observersByProxy.get(observableProxy); - if (observers) { - observers.change.clear(); - observers.destroy.clear(); - observables.delete(observablesByProxy.get(observableProxy)); - observablesByProxy.delete(observableProxy); - observersByProxy.delete(observableProxy); - changedProxies.delete(observableProxy); - return true; - } - return false; -}; + return ( + !!observers && + (observers.change.clear(), + observers.destroy.clear(), + observables.delete(observablesByProxy.get(observableProxy)), + observablesByProxy.delete(observableProxy), + observersByProxy.delete(observableProxy), + changedProxies.delete(observableProxy), + !0) + ); + }; tick(); +export { ObservableEvents, destroy, observable, observe, off, on, unobserve }; From 912ed1c94ecaca83d622dabfa0a49f19ac3f3615 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 29 Mar 2023 19:53:45 -0400 Subject: [PATCH 27/53] Observable callbacks are now passed the proxy they are listening to as the first argument --- src/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/index.ts b/src/index.ts index 2b273a7..0f6e108 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,5 @@ export type Observable = {[name: string]: any;}; -export type ObservableCallback = () => void; +export type ObservableCallback = (proxy: Observable) => void; export const ObservableEvents = { change: 'change', destroy: 'destroy', @@ -30,12 +30,12 @@ const canBeObservable = (data: Observable): boolean => Array.isArray(data) || /* const tick = (): void => { changedProxies.forEach(proxy => { const observers = observersByProxy.get(proxy); - if(observers) observers.change.forEach((callback: ObservableCallback) => callback()); + if(observers) observers.change.forEach((callback: ObservableCallback) => callback(proxy)); }); changedProxies.clear(); destroyedProxies.forEach(proxy => { const observers = observersByProxy.get(proxy); - if(observers) observers.destroy.forEach((callback: ObservableCallback) => callback()); + if(observers) observers.destroy.forEach((callback: ObservableCallback) => callback(proxy)); }); destroyedProxies.clear(); if(BROWSER) window.requestAnimationFrame(tick); From bae961a7e374c4feed425cf15a3e81a8e5410648 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 29 Mar 2023 19:54:26 -0400 Subject: [PATCH 28/53] Updated examples with listeners having a state argument --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a3c818a..535645c 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Objects and arrays can also be observed and unobserved. ```js import { observable, observe, unobserve } from 'simple-observable-proxy'; -const stateChange = () => { +const stateChange = state => { console.log('stateChange()'); } const state = observable({ @@ -55,11 +55,11 @@ const sharedState = observable([ } ]); -const sharedStateCallback1 = () => { +const sharedStateCallback1 = state => { console.log('sharedStateCallback1()'); }; -const sharedStateCallback2 = () => { +const sharedStateCallback2 = state => { console.log('sharedStateCallback2()'); }; From 85356962a058d3d3baa32c5d2a375f215efc468e Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 29 Mar 2023 19:54:43 -0400 Subject: [PATCH 29/53] Updated method footprints for callback functions --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 535645c..132fa5a 100644 --- a/README.md +++ b/README.md @@ -76,16 +76,16 @@ Converts an `Array` or plain `Object` (not an instance of a class) to an instanc - If the `Array` or plain `Object` contains an instance of a class. - If the `Array` or plain `Object` contains an `Array` or plain `Object` that has already been passed to `observable()`. -### on(proxy: Observable, ObservableEventType: "change" | "destroy", callbackFn: () => {}): boolean +### on(proxy: Observable, ObservableEventType: "change" | "destroy", callbackFn: (proxy: Observable) => void): boolean Subscribes to either the change or destroy event using callbackFn, Returns `true` if successfully subscribed, or `false` in cases where the proxy or callback function is invalid, or the callback is already registered. -### off(proxy: Observable, ObservableEventType: "change" | "destroy", callbackFn: () => {}): boolean +### off(proxy: Observable, ObservableEventType: "change" | "destroy", callbackFn: (proxy: Observable) => void): boolean Unsubscribes from either the change or destroy event using callbackFn. Returns `true` if successfully unsubscribed, or `false` in cases where the proxy or callback function is invalid. -### DEPRECATED observe(proxy: Observable, callbackFn: () => {}): boolean +### DEPRECATED observe(proxy: Observable, callbackFn: (proxy: Observable) => void): boolean Shorthand method that calls observe(proxy, "change", callbackFn). Maintained for backwards compatibility with v1, but will be dropped in a future release. -### DEPRECATED unobserve(proxy: Observable, callbackFn: () => {}): boolean +### DEPRECATED unobserve(proxy: Observable, callbackFn: (proxy: Observable) => void): boolean Shorthand method that calls unobserve(proxy, "change", callbackFn). Maintained for backwards compatibility with v1, but will be dropped in a future release. ### destroy(proxy: Observable): boolean From aa36d5c057872d16643c53749c5c57a2c22ac0e2 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 29 Mar 2023 19:54:58 -0400 Subject: [PATCH 30/53] Built latest version --- dist/index.d.ts | 2 +- dist/simple-observable-proxy.js | 4 ++-- dist/simple-observable-proxy.min.js | 2 +- lib/index.d.ts | 2 +- lib/index.js | 4 ++-- lib/index.mjs | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/dist/index.d.ts b/dist/index.d.ts index feac7e8..ef558b9 100644 --- a/dist/index.d.ts +++ b/dist/index.d.ts @@ -1,7 +1,7 @@ export type Observable = { [name: string]: any; }; -export type ObservableCallback = () => void; +export type ObservableCallback = (proxy: Observable) => void; export declare const ObservableEvents: { readonly change: "change"; readonly destroy: "destroy"; diff --git a/dist/simple-observable-proxy.js b/dist/simple-observable-proxy.js index a5ea18f..3695625 100644 --- a/dist/simple-observable-proxy.js +++ b/dist/simple-observable-proxy.js @@ -9,12 +9,12 @@ const ObservableEvents = { change: "change", destroy: "destroy" }, tick = () => { changedProxies.forEach((proxy) => { const observers = observersByProxy.get(proxy); - observers && observers.change.forEach((callback) => callback()); + observers && observers.change.forEach((callback) => callback(proxy)); }), changedProxies.clear(), destroyedProxies.forEach((proxy) => { const observers = observersByProxy.get(proxy); - observers && observers.destroy.forEach((callback) => callback()); + observers && observers.destroy.forEach((callback) => callback(proxy)); }), destroyedProxies.clear(), window.requestAnimationFrame(tick); diff --git a/dist/simple-observable-proxy.min.js b/dist/simple-observable-proxy.min.js index 2e342a0..1b68d62 100644 --- a/dist/simple-observable-proxy.min.js +++ b/dist/simple-observable-proxy.min.js @@ -1,2 +1,2 @@ /*! simple observable proxy v2.0.0 | MIT License | © 2022 Aleph1 Technologies Inc */ -const e={change:"change",destroy:"destroy"},r=new Set,t=new Map,n=new Map,o=new Set,a=new Set,s={}.constructor,c=()=>{o.forEach((e=>{const r=n.get(e);r&&r.change.forEach((e=>e()))})),o.clear(),a.forEach((e=>{const r=n.get(e);r&&r.destroy.forEach((e=>e()))})),a.clear(),window.requestAnimationFrame(c)},y=(e,a)=>{if(r.has(e))throw new Error("data is alreaby an observable");if(a&&!t.has(a))throw new Error("rootProxy isn’t an observable");let c;const d=new Proxy(e,{get:(e,r)=>e[r],set(e,r,n){if(e[r]!==n){if(c){if(t.has(n))throw new Error("Can’t nest observables");o.add(a||d)}e[r]=n}return!0},deleteProperty:(e,r)=>r in e&&(delete e[r],o.add(a||d),!0)});return r.add(e),t.set(d,e),(Array.isArray(e)?[...Array(e.length).keys()]:Object.keys(e)).forEach((r=>{const n=e[r];if(t.has(n))throw new Error("Can’t nest observables");(e=>Array.isArray(e)||(e=>!!e&&"object"==typeof e&&e.constructor===s)(e))(n)&&(d[r]=y(n,a||d))})),n.set(d,c={change:new Set,destroy:new Set}),d},d=e=>{if((e=>Array.isArray(e)||(e=>!!e&&"object"==typeof e&&e.constructor===s)(e))(e))return y(e);throw new Error("Only Arrays and plain Objects are observable")},h=(e,r,t)=>{const o=n.get(e);return!(!o||!o[r]||"function"!=typeof t||o[r].has(t))&&(o[r].add(t),!0)},l=(e,r,t)=>{const o=n.get(e);return!(!o||!o[r]||"function"!=typeof t)&&o[r].delete(t)},w=(r,t)=>h(r,e.change,t),i=(r,t)=>l(r,e.change,t),f=e=>{const a=n.get(e);return!!a&&(a.change.clear(),a.destroy.clear(),r.delete(t.get(e)),t.delete(e),n.delete(e),o.delete(e),!0)};c();export{e as ObservableEvents,f as destroy,d as observable,w as observe,l as off,h as on,i as unobserve}; +const e={change:"change",destroy:"destroy"},r=new Set,t=new Map,n=new Map,o=new Set,a=new Set,s={}.constructor,c=()=>{o.forEach((e=>{const r=n.get(e);r&&r.change.forEach((r=>r(e)))})),o.clear(),a.forEach((e=>{const r=n.get(e);r&&r.destroy.forEach((r=>r(e)))})),a.clear(),window.requestAnimationFrame(c)},y=(e,a)=>{if(r.has(e))throw new Error("data is alreaby an observable");if(a&&!t.has(a))throw new Error("rootProxy isn’t an observable");let c;const d=new Proxy(e,{get:(e,r)=>e[r],set(e,r,n){if(e[r]!==n){if(c){if(t.has(n))throw new Error("Can’t nest observables");o.add(a||d)}e[r]=n}return!0},deleteProperty:(e,r)=>r in e&&(delete e[r],o.add(a||d),!0)});return r.add(e),t.set(d,e),(Array.isArray(e)?[...Array(e.length).keys()]:Object.keys(e)).forEach((r=>{const n=e[r];if(t.has(n))throw new Error("Can’t nest observables");(e=>Array.isArray(e)||(e=>!!e&&"object"==typeof e&&e.constructor===s)(e))(n)&&(d[r]=y(n,a||d))})),n.set(d,c={change:new Set,destroy:new Set}),d},d=e=>{if((e=>Array.isArray(e)||(e=>!!e&&"object"==typeof e&&e.constructor===s)(e))(e))return y(e);throw new Error("Only Arrays and plain Objects are observable")},h=(e,r,t)=>{const o=n.get(e);return!(!o||!o[r]||"function"!=typeof t||o[r].has(t))&&(o[r].add(t),!0)},l=(e,r,t)=>{const o=n.get(e);return!(!o||!o[r]||"function"!=typeof t)&&o[r].delete(t)},w=(r,t)=>h(r,e.change,t),i=(r,t)=>l(r,e.change,t),f=e=>{const a=n.get(e);return!!a&&(a.change.clear(),a.destroy.clear(),r.delete(t.get(e)),t.delete(e),n.delete(e),o.delete(e),!0)};c();export{e as ObservableEvents,f as destroy,d as observable,w as observe,l as off,h as on,i as unobserve}; diff --git a/lib/index.d.ts b/lib/index.d.ts index feac7e8..ef558b9 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -1,7 +1,7 @@ export type Observable = { [name: string]: any; }; -export type ObservableCallback = () => void; +export type ObservableCallback = (proxy: Observable) => void; export declare const ObservableEvents: { readonly change: "change"; readonly destroy: "destroy"; diff --git a/lib/index.js b/lib/index.js index ec439ba..6b4cce4 100644 --- a/lib/index.js +++ b/lib/index.js @@ -9,12 +9,12 @@ const ObservableEvents = { change: "change", destroy: "destroy" }, tick = () => { changedProxies.forEach((proxy) => { const observers = observersByProxy.get(proxy); - observers && observers.change.forEach((callback) => callback()); + observers && observers.change.forEach((callback) => callback(proxy)); }), changedProxies.clear(), destroyedProxies.forEach((proxy) => { const observers = observersByProxy.get(proxy); - observers && observers.destroy.forEach((callback) => callback()); + observers && observers.destroy.forEach((callback) => callback(proxy)); }), destroyedProxies.clear(), setTimeout(tick, 16); diff --git a/lib/index.mjs b/lib/index.mjs index 86aa210..7593ed0 100644 --- a/lib/index.mjs +++ b/lib/index.mjs @@ -9,12 +9,12 @@ const ObservableEvents = { change: "change", destroy: "destroy" }, tick = () => { changedProxies.forEach((proxy) => { const observers = observersByProxy.get(proxy); - observers && observers.change.forEach((callback) => callback()); + observers && observers.change.forEach((callback) => callback(proxy)); }), changedProxies.clear(), destroyedProxies.forEach((proxy) => { const observers = observersByProxy.get(proxy); - observers && observers.destroy.forEach((callback) => callback()); + observers && observers.destroy.forEach((callback) => callback(proxy)); }), destroyedProxies.clear(), setTimeout(tick, 16); From 39bf293922fe4efb607ccd149f8cc4aaf2c3ca2c Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 29 Mar 2023 20:18:57 -0400 Subject: [PATCH 31/53] Added information regarding migrating from 1.x to 2.x --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.md b/README.md index 132fa5a..6c99394 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,26 @@ Shorthand method that calls unobserve(proxy, "change", callbackFn). Maintained f ### destroy(proxy: Observable): boolean Cleans up the proxy. Returns `true` if successfully destroyed, or `false` in cases where the proxy has already been destroyed, or is not a valid proxy. +## Migration from 1.x to 2.x +In order to ensure that 1.x code does not break, the `observe` and `unobserve` methods have been retained as part of the 2.x codeset, but are marked as deprecated. If you wish to convert these to the 2.x syntax, you shoud modify your code as follows: + +1. Where you import the `observe` and `unobserve` methods, instead import the `on` and `off` methods, and the `ObservableEvents` object. +2. Replace any calls to `observe(yourState, yourChangeCallback)` to `on(yourState, ObservableEvents.change, yourChangeCallback)`, and any calls to `unobserve(yourState, yourChangeCallback)` to `off(yourState, ObservableEvents.change, yourChangeCallback)`. + +If you wish to recreate the deprecated `observe` and `unobserve` methods, you can add the following to your codeset. + +### TypeScript +```ts +export const observe = (observableProxy: Observable, callback: ObservableCallback): boolean => on(observableProxy, ObservableEvents.change, callback); +export const unobserve = (observableProxy: Observable, callback: ObservableCallback): boolean => off(observableProxy, ObservableEvents.change, callback); +``` + +### JavaScript +```js +export const observe = (observableProxy, callback) => on(observableProxy, ObservableEvents.change, callback); +export const unobserve = (observableProxy, callback) => off(observableProxy, ObservableEvents.change, callback); +``` + ## Notes When a value is modified on an observable proxy, its updated values is available immediately. When multiple values are modified on the observable proxy each registered callback will be called only once using requestAnimationFrame in the browser, or after 16ms in a Node environment. For example: From ac492539f98fd850ff8bae5d96da85475cfc7a4b Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 29 Mar 2023 20:19:09 -0400 Subject: [PATCH 32/53] Added links to readme sections --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 6c99394..b17806b 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,14 @@ For objects, changing values, as well as adding, editing, or deleting keys resul Simple Observable Proxy is written in TypeScript and compiles as CommonJS and ESM. It is intended to be a very small library (less than 800 bytes when minified and gzipped), and, as such, it does not report on specific differences between the current and prior state of the observed object or array. +- [Installation](#real-cool-heading) +- [Basic Usage](#basic-usage) +- [Methods](#methods) +- [Migration from 1.x to 2.x](#migrating-from-1x-to-2x) +- [Notes](#notes) +- [Roadmap](#roadmap) +- [Browser Support](#browser-support) + ## Installation Node From 588360bfcb2c458811d98c2bc5b4e21e48aa222f Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 29 Mar 2023 20:20:45 -0400 Subject: [PATCH 33/53] Fixed link to Migrating from 1.x to 2.x --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b17806b..b0a6a58 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Simple Observable Proxy is written in TypeScript and compiles as CommonJS and ES - [Installation](#real-cool-heading) - [Basic Usage](#basic-usage) - [Methods](#methods) -- [Migration from 1.x to 2.x](#migrating-from-1x-to-2x) +- [Migrating from 1.x to 2.x](#migrating-from-1x-to-2x) - [Notes](#notes) - [Roadmap](#roadmap) - [Browser Support](#browser-support) @@ -99,7 +99,7 @@ Shorthand method that calls unobserve(proxy, "change", callbackFn). Maintained f ### destroy(proxy: Observable): boolean Cleans up the proxy. Returns `true` if successfully destroyed, or `false` in cases where the proxy has already been destroyed, or is not a valid proxy. -## Migration from 1.x to 2.x +## Migrating from 1.x to 2.x In order to ensure that 1.x code does not break, the `observe` and `unobserve` methods have been retained as part of the 2.x codeset, but are marked as deprecated. If you wish to convert these to the 2.x syntax, you shoud modify your code as follows: 1. Where you import the `observe` and `unobserve` methods, instead import the `on` and `off` methods, and the `ObservableEvents` object. From 67ebd700ffb4e3df7f3c3fe60d79fc5a3a547645 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 29 Mar 2023 20:22:26 -0400 Subject: [PATCH 34/53] Updated ```ts to ```typescript --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b0a6a58..5232975 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,7 @@ In order to ensure that 1.x code does not break, the `observe` and `unobserve` m If you wish to recreate the deprecated `observe` and `unobserve` methods, you can add the following to your codeset. ### TypeScript -```ts +```typescript export const observe = (observableProxy: Observable, callback: ObservableCallback): boolean => on(observableProxy, ObservableEvents.change, callback); export const unobserve = (observableProxy: Observable, callback: ObservableCallback): boolean => off(observableProxy, ObservableEvents.change, callback); ``` From 978d9089e09c1b43aabb0ec2f4c9ad4a61f0c9ce Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 29 Mar 2023 20:23:39 -0400 Subject: [PATCH 35/53] Removed export directive from readme --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5232975..2e1e5d9 100644 --- a/README.md +++ b/README.md @@ -109,14 +109,14 @@ If you wish to recreate the deprecated `observe` and `unobserve` methods, you ca ### TypeScript ```typescript -export const observe = (observableProxy: Observable, callback: ObservableCallback): boolean => on(observableProxy, ObservableEvents.change, callback); -export const unobserve = (observableProxy: Observable, callback: ObservableCallback): boolean => off(observableProxy, ObservableEvents.change, callback); +const observe = (observableProxy: Observable, callback: ObservableCallback): boolean => on(observableProxy, ObservableEvents.change, callback); +const unobserve = (observableProxy: Observable, callback: ObservableCallback): boolean => off(observableProxy, ObservableEvents.change, callback); ``` ### JavaScript ```js -export const observe = (observableProxy, callback) => on(observableProxy, ObservableEvents.change, callback); -export const unobserve = (observableProxy, callback) => off(observableProxy, ObservableEvents.change, callback); +const observe = (observableProxy, callback) => on(observableProxy, ObservableEvents.change, callback); +const unobserve = (observableProxy, callback) => off(observableProxy, ObservableEvents.change, callback); ``` ## Notes From c93470e68b76eb41d9f3e11831bc5efd57ba6c23 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 27 Dec 2023 16:03:39 -0500 Subject: [PATCH 36/53] Observables are destroyed on tick/raf --- src/index.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/index.ts b/src/index.ts index 0f6e108..54234d6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -35,7 +35,13 @@ const tick = (): void => { changedProxies.clear(); destroyedProxies.forEach(proxy => { const observers = observersByProxy.get(proxy); - if(observers) observers.destroy.forEach((callback: ObservableCallback) => callback(proxy)); + if(observers) { + observers.destroy.forEach((callback: ObservableCallback) => callback(proxy)); + observers.change.clear(); + observers.destroy.clear(); + observablesByProxy.delete(proxy); + observersByProxy.delete(proxy); + } }); destroyedProxies.clear(); if(BROWSER) window.requestAnimationFrame(tick); @@ -110,12 +116,8 @@ export const unobserve = (observableProxy: Observable, callback: ObservableCallb export const destroy = (observableProxy: Observable): boolean => { const observers = observersByProxy.get(observableProxy); if(observers) { - observers.change.clear(); - observers.destroy.clear(); + destroyedProxies.add(observableProxy); observables.delete(observablesByProxy.get(observableProxy)); - observablesByProxy.delete(observableProxy); - observersByProxy.delete(observableProxy); - changedProxies.delete(observableProxy); return true; } return false; From 433849af4971a7c2adb1ef235ee39c2c04fb2a57 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 27 Dec 2023 16:04:48 -0500 Subject: [PATCH 37/53] Deleting an observable property returns true whether it exists or not. Avoids node throwing an error when false is returned from a deleteProxy handler. --- src/index.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index 54234d6..a03364a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -70,9 +70,11 @@ const makeObservableProxy = (data: Observable, rootProxy?: Observable): Observab if (key in target) { delete target[key as string]; changedProxies.add(rootProxy || proxy); - return true; } - return false; + // we return true whether the property existed or not, as node + // throws an error when false is returned which requires wrapping + // all delete statements in a try/catch block + return true; } }); observables.add(data); From dc338d66350f265373e24f10a2cbf2dd6fd27eb1 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 27 Dec 2023 16:05:47 -0500 Subject: [PATCH 38/53] Fixed error not being thrown when attempting to make an observable an observable. --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index a03364a..cbf177b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -49,8 +49,8 @@ const tick = (): void => { }; const makeObservableProxy = (data: Observable, rootProxy?: Observable): Observable => { - if(observables.has(data)) throw new Error('data is alreaby an observable'); if(rootProxy && !observablesByProxy.has(rootProxy)) throw new Error('rootProxy isn’t an observable'); + if(observables.has(data) || observablesByProxy.has(data)) throw new Error('data is alreaby an observable'); let observers: ObservableCallbackObject; const proxy = new Proxy(data, { get(target, key): any { From c08d42df2b1fa68a79819d8b525982ed39d917ce Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 27 Dec 2023 16:06:03 -0500 Subject: [PATCH 39/53] Disabled unused code --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index cbf177b..ac8e317 100644 --- a/src/index.ts +++ b/src/index.ts @@ -49,8 +49,8 @@ const tick = (): void => { }; const makeObservableProxy = (data: Observable, rootProxy?: Observable): Observable => { - if(rootProxy && !observablesByProxy.has(rootProxy)) throw new Error('rootProxy isn’t an observable'); if(observables.has(data) || observablesByProxy.has(data)) throw new Error('data is alreaby an observable'); + //if(rootProxy && !observablesByProxy.has(rootProxy)) throw new Error('rootProxy isn’t an observable'); let observers: ObservableCallbackObject; const proxy = new Proxy(data, { get(target, key): any { From d791de24207f2f25080a09a0b9457b751fe43edd Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 27 Dec 2023 16:06:38 -0500 Subject: [PATCH 40/53] Added and modified tests. --- scripts/test.ts | 152 ++++++++++++++++++++++++++---------------------- 1 file changed, 83 insertions(+), 69 deletions(-) diff --git a/scripts/test.ts b/scripts/test.ts index 5db1f74..6e22c98 100644 --- a/scripts/test.ts +++ b/scripts/test.ts @@ -81,21 +81,36 @@ describe('observable()', () => { }).toThrow(Error); }); - test('Throws error when observables are nested', done => { + test('Throws error when object is already observable', () => { + const state = observable({}); + console.log(state); + expect(() => { + const state2 = observable(state); + }).toThrow(Error); + }); + + test('Throws error when observables are nested', () => { const state1 = observable(createState()); expect(() => { const state2 = observable({ state: state1 }); }).toThrow(Error); - done(); + }); + + test('Throws error when attempting to set property as observable', () => { + const state1 = observable({}); + const state2 = observable({}); + expect(() => { + state1.test = state2; + }).toThrow(Error); }); }); describe('observe()', () => { - test('Triggers deferred callback when adding object key', done => { + test('Triggers deferred callback when adding object key', () => { const callback = jest.fn(); const state = observable(createState()); observe(state, callback); @@ -104,10 +119,9 @@ describe('observe()', () => { jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); expect(state.string2).toEqual('test2'); - done(); }); - test('Triggers deferred callback when modifying object key', done => { + test('Triggers deferred callback when modifying object key', () => { const callback = jest.fn(); const state = observable(createState()); observe(state, callback); @@ -117,10 +131,9 @@ describe('observe()', () => { jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); expect(state.boolean).toEqual(false); - done(); }); - test('Triggers deferred callback when deleting object key', done => { + test('Triggers deferred callback when deleting object key', () => { const callback = jest.fn(); const state = observable(createState()); observe(state, callback); @@ -129,10 +142,19 @@ describe('observe()', () => { jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); expect(state.string).toEqual(undefined); - done(); }); - test('Triggers deferred callback when modifying mutliple object keys', done => { + test('Does not trigger deferred callback when deleting non-existent key', () => { + const callback = jest.fn(); + const state = observable({}); + observe(state, callback); + delete state.test; + expect(callback).not.toBeCalled(); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).not.toBeCalled(); + }); + + test('Triggers deferred callback when modifying mutliple object keys', () => { const callback = jest.fn(); const state = observable(createState()); observe(state, callback); @@ -143,10 +165,9 @@ describe('observe()', () => { expect(callback).toHaveBeenCalledTimes(1); expect(state.boolean).toEqual(false); expect(state.number).toEqual(1); - done(); }); - test('Triggers deferred callback when modifying object using Object.assign()', done => { + test('Triggers deferred callback when modifying object using Object.assign()', () => { const callback = jest.fn(); const state = observable(createState()); observe(state, callback); @@ -159,10 +180,9 @@ describe('observe()', () => { expect(callback).toHaveBeenCalledTimes(1); expect(state.boolean).toEqual(false); expect(state.number).toEqual(1); - done(); }); - test('Triggers deferred callback when modifying array using pop', done => { + test('Triggers deferred callback when modifying array using pop', () => { const callback = jest.fn(); const state = observable([1, 2, 3]); observe(state, callback); @@ -173,10 +193,9 @@ describe('observe()', () => { expect(callback).toHaveBeenCalledTimes(1); expect(state.length).toEqual(2); expect(state).toEqual([1, 2]); - done(); }); - test('Triggers deferred callback when modifying array using push', done => { + test('Triggers deferred callback when modifying array using push', () => { const callback = jest.fn(); const state = observable([1, 2, 3]); observe(state, callback); @@ -187,10 +206,9 @@ describe('observe()', () => { expect(callback).toHaveBeenCalledTimes(1); expect(state.length).toEqual(4); expect(state).toEqual([1, 2, 3, 4]); - done(); }); - test('Triggers deferred callback when modifying array using index', done => { + test('Triggers deferred callback when modifying array using index', () => { const callback = jest.fn(); const state = observable([1, 2, 3]); observe(state, callback); @@ -201,10 +219,9 @@ describe('observe()', () => { expect(callback).toHaveBeenCalledTimes(1); expect(state.length).toEqual(3); expect(state).toEqual([0, 2, 3]); - done(); }); - test('Triggers deferred callback when modifying array using length', done => { + test('Triggers deferred callback when modifying array using length', () => { const callback = jest.fn(); const state = observable([1, 2, 3]); observe(state, callback); @@ -215,10 +232,9 @@ describe('observe()', () => { expect(callback).toHaveBeenCalledTimes(1); expect(state.length).toEqual(1); expect(state).toEqual([1]); - done(); }); - test('Triggers deferred callback when modifying nested array', done => { + test('Triggers deferred callback when modifying nested array', () => { const callback = jest.fn(); const state = observable(createState()); observe(state, callback); @@ -229,10 +245,9 @@ describe('observe()', () => { expect(callback).toHaveBeenCalledTimes(1); expect(state.array.length).toEqual(4); expect(state.array).toEqual([1, 2, 3, 4]); - done(); }); - test('Triggers deferred callback when modifying nested object', done => { + test('Triggers deferred callback when modifying nested object', () => { const callback = jest.fn(); const state = observable(createState()); observe(state, callback); @@ -242,10 +257,9 @@ describe('observe()', () => { jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); expect(state.object.string2).toEqual('test2'); - done(); }); - test('Triggers deferred callback for multiple observers', done => { + test('Triggers deferred callback for multiple observers', () => { const callback1 = jest.fn(); const callback2 = jest.fn(); const state = observable(createState()); @@ -256,20 +270,18 @@ describe('observe()', () => { expect(callback1).toHaveBeenCalledTimes(1); expect(callback2).toHaveBeenCalledTimes(1); expect(state.string).toEqual('test2'); - done(); }); - test('When trying to observe a non-observable returns false', done => { + test('When trying to observe a non-observable returns false', () => { const obj1 = createState(); expect(observe(obj1, ()=>{})).toEqual(false); - done(); }); }); describe('on()', () => { - test('Triggers deferred callback when adding object key', done => { + test('Triggers deferred callback when adding object key', () => { const callback = jest.fn(); const state = observable(createState()); on(state, ObservableEvents.change, callback); @@ -278,10 +290,9 @@ describe('on()', () => { jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); expect(state.string2).toEqual('test2'); - done(); }); - test('Triggers deferred callback when modifying object key', done => { + test('Triggers deferred callback when modifying object key', () => { const callback = jest.fn(); const state = observable(createState()); on(state, ObservableEvents.change, callback); @@ -291,10 +302,9 @@ describe('on()', () => { jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); expect(state.boolean).toEqual(false); - done(); }); - test('Triggers deferred callback when deleting object key', done => { + test('Triggers deferred callback when deleting object key', () => { const callback = jest.fn(); const state = observable(createState()); on(state, ObservableEvents.change, callback); @@ -303,10 +313,9 @@ describe('on()', () => { jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); expect(state.string).toEqual(undefined); - done(); }); - test('Triggers deferred callback when modifying mutliple object keys', done => { + test('Triggers deferred callback when modifying mutliple object keys', () => { const callback = jest.fn(); const state = observable(createState()); on(state, ObservableEvents.change, callback); @@ -317,10 +326,9 @@ describe('on()', () => { expect(callback).toHaveBeenCalledTimes(1); expect(state.boolean).toEqual(false); expect(state.number).toEqual(1); - done(); }); - test('Triggers deferred callback when modifying object using Object.assign()', done => { + test('Triggers deferred callback when modifying object using Object.assign()', () => { const callback = jest.fn(); const state = observable(createState()); on(state, ObservableEvents.change, callback); @@ -333,10 +341,9 @@ describe('on()', () => { expect(callback).toHaveBeenCalledTimes(1); expect(state.boolean).toEqual(false); expect(state.number).toEqual(1); - done(); }); - test('Triggers deferred callback when modifying array using pop', done => { + test('Triggers deferred callback when modifying array using pop', () => { const callback = jest.fn(); const state = observable([1, 2, 3]); on(state, ObservableEvents.change, callback); @@ -347,10 +354,9 @@ describe('on()', () => { expect(callback).toHaveBeenCalledTimes(1); expect(state.length).toEqual(2); expect(state).toEqual([1, 2]); - done(); }); - test('Triggers deferred callback when modifying array using push', done => { + test('Triggers deferred callback when modifying array using push', () => { const callback = jest.fn(); const state = observable([1, 2, 3]); on(state, ObservableEvents.change, callback); @@ -361,10 +367,9 @@ describe('on()', () => { expect(callback).toHaveBeenCalledTimes(1); expect(state.length).toEqual(4); expect(state).toEqual([1, 2, 3, 4]); - done(); }); - test('Triggers deferred callback when modifying array using index', done => { + test('Triggers deferred callback when modifying array using index', () => { const callback = jest.fn(); const state = observable([1, 2, 3]); on(state, ObservableEvents.change, callback); @@ -375,10 +380,9 @@ describe('on()', () => { expect(callback).toHaveBeenCalledTimes(1); expect(state.length).toEqual(3); expect(state).toEqual([0, 2, 3]); - done(); }); - test('Triggers deferred callback when modifying array using length', done => { + test('Triggers deferred callback when modifying array using length', () => { const callback = jest.fn(); const state = observable([1, 2, 3]); on(state, ObservableEvents.change, callback); @@ -389,10 +393,9 @@ describe('on()', () => { expect(callback).toHaveBeenCalledTimes(1); expect(state.length).toEqual(1); expect(state).toEqual([1]); - done(); }); - test('Triggers deferred callback when modifying nested array', done => { + test('Triggers deferred callback when modifying nested array', () => { const callback = jest.fn(); const state = observable(createState()); on(state, ObservableEvents.change, callback); @@ -403,10 +406,9 @@ describe('on()', () => { expect(callback).toHaveBeenCalledTimes(1); expect(state.array.length).toEqual(4); expect(state.array).toEqual([1, 2, 3, 4]); - done(); }); - test('Triggers deferred callback when modifying nested object', done => { + test('Triggers deferred callback when modifying nested object', () => { const callback = jest.fn(); const state = observable(createState()); on(state, ObservableEvents.change, callback); @@ -416,10 +418,9 @@ describe('on()', () => { jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); expect(state.object.string2).toEqual('test2'); - done(); }); - test('Triggers deferred callback when reobserved', done => { + test('Triggers deferred callback when reobserved', () => { const callback = jest.fn(); const state = observable(createState()); observe(state, callback); @@ -437,14 +438,13 @@ describe('on()', () => { jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(2); expect(state.string).toEqual('test4'); - done(); }); }); describe('unobserve()', () => { - test('No callback when object is unobserved', done => { + test('No callback when object is unobserved', () => { const callback = jest.fn(); const state = observable(createState()); observe(state, callback); @@ -457,48 +457,62 @@ describe('unobserve()', () => { jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); expect(state.string).toEqual('test3'); - done(); }); - test('After destroying a non-observable returns false', done => { + test('After destroying a non-observable returns false', () => { const state1 = destroy(observable(createState())); expect(unobserve(state1 as any, ()=>{})).toEqual(false); - done(); }); - test('When trying to unobserve a non-observable returns false w', done => { + test('When trying to unobserve a non-observable returns false w', () => { const obj1 = createState(); expect(unobserve(obj1, ()=>{})).toEqual(false); - done(); }); - }); describe('destroy()', () => { - test('When destroying an observable retuns true', done => { + test('When destroying an observable retuns true', () => { const state1 = observable(createState()); expect(destroy(state1)).toEqual(true); - done(); }); - test('When destroying a non-observable returns false', done => { + test('When destroying a non-observable returns false', () => { const state1 = destroy(observable(createState())); expect(observe(state1 as any, ()=>{})).toEqual(false); - done(); }); - test('Destroying an non-observable multiple times returns false', done => { + test('Destroying an non-observable multiple times returns false', () => { const state1 = destroy(observable(createState())); expect(destroy(state1 as any)).toEqual(false); - done(); }); - test('When trying to destroy a non-observable returns false', done => { - const obj1 = createState(); - expect(destroy(obj1)).toEqual(false); - done(); + test('When trying to destroy a non-observable returns false', () => { + const state1 = createState(); + expect(destroy(state1)).toEqual(false); + }); + + test('Destroying removes all observers', () => { + const state = observable({}); + const changeCallback = jest.fn(); + const destroyCallback = jest.fn(); + on(state, ObservableEvents.change, changeCallback); + on(state, ObservableEvents.destroy, destroyCallback); + state.test = 'test'; + expect(changeCallback).toHaveBeenCalledTimes(0); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(changeCallback).toHaveBeenCalledTimes(1); + destroy(state); + expect(destroyCallback).toHaveBeenCalledTimes(0); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(destroyCallback).toHaveBeenCalledTimes(1); + state.test = 'test2'; + jest.advanceTimersByTime(global.FRAME_TIME); + expect(changeCallback).toHaveBeenCalledTimes(1); + destroy(state); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(destroyCallback).toHaveBeenCalledTimes(1); }); }); \ No newline at end of file From d62008761fd1a13aedf6c1ee7f72ce971ad7eb50 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 27 Dec 2023 16:07:04 -0500 Subject: [PATCH 41/53] Added note regarding potential addition of support for Map and Set --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2e1e5d9..bc70270 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,7 @@ console.log('before state changed callback'); Version 3.0 will consider the following change: +- Add support for Map and Set - Instances of classes are observable ## Browser Support From f55cece8022caf8995dc459b83c057c89f93a8e7 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 27 Dec 2023 16:07:41 -0500 Subject: [PATCH 42/53] Built latest version --- dist/simple-observable-proxy.js | 36 ++++++++++++++--------------- dist/simple-observable-proxy.min.js | 2 +- lib/index.js | 36 ++++++++++++++--------------- lib/index.mjs | 36 ++++++++++++++--------------- 4 files changed, 52 insertions(+), 58 deletions(-) diff --git a/dist/simple-observable-proxy.js b/dist/simple-observable-proxy.js index 3695625..30e4518 100644 --- a/dist/simple-observable-proxy.js +++ b/dist/simple-observable-proxy.js @@ -14,15 +14,19 @@ const ObservableEvents = { change: "change", destroy: "destroy" }, changedProxies.clear(), destroyedProxies.forEach((proxy) => { const observers = observersByProxy.get(proxy); - observers && observers.destroy.forEach((callback) => callback(proxy)); + observers && + (observers.destroy.forEach((callback) => callback(proxy)), + observers.change.clear(), + observers.destroy.clear(), + observablesByProxy.delete(proxy), + observersByProxy.delete(proxy)); }), destroyedProxies.clear(), window.requestAnimationFrame(tick); }, makeObservableProxy = (data, rootProxy) => { - if (observables.has(data)) throw new Error("data is alreaby an observable"); - if (rootProxy && !observablesByProxy.has(rootProxy)) - throw new Error("rootProxy isn’t an observable"); + if (observables.has(data) || observablesByProxy.has(data)) + throw new Error("data is alreaby an observable"); let observers; const proxy = new Proxy(data, { get: (target, key) => target[key], @@ -37,9 +41,11 @@ const ObservableEvents = { change: "change", destroy: "destroy" }, } return !0; }, - deleteProperty: (target, key) => + deleteProperty: (target, key) => ( key in target && - (delete target[key], changedProxies.add(rootProxy || proxy), !0), + (delete target[key], changedProxies.add(rootProxy || proxy)), + !0 + ), }); return ( observables.add(data), @@ -100,18 +106,10 @@ const ObservableEvents = { change: "change", destroy: "destroy" }, on(observableProxy, ObservableEvents.change, callback), unobserve = (observableProxy, callback) => off(observableProxy, ObservableEvents.change, callback), - destroy = (observableProxy) => { - const observers = observersByProxy.get(observableProxy); - return ( - !!observers && - (observers.change.clear(), - observers.destroy.clear(), - observables.delete(observablesByProxy.get(observableProxy)), - observablesByProxy.delete(observableProxy), - observersByProxy.delete(observableProxy), - changedProxies.delete(observableProxy), - !0) - ); - }; + destroy = (observableProxy) => + !!observersByProxy.get(observableProxy) && + (destroyedProxies.add(observableProxy), + observables.delete(observablesByProxy.get(observableProxy)), + !0); tick(); export { ObservableEvents, destroy, observable, observe, off, on, unobserve }; diff --git a/dist/simple-observable-proxy.min.js b/dist/simple-observable-proxy.min.js index 1b68d62..a1b1457 100644 --- a/dist/simple-observable-proxy.min.js +++ b/dist/simple-observable-proxy.min.js @@ -1,2 +1,2 @@ /*! simple observable proxy v2.0.0 | MIT License | © 2022 Aleph1 Technologies Inc */ -const e={change:"change",destroy:"destroy"},r=new Set,t=new Map,n=new Map,o=new Set,a=new Set,s={}.constructor,c=()=>{o.forEach((e=>{const r=n.get(e);r&&r.change.forEach((r=>r(e)))})),o.clear(),a.forEach((e=>{const r=n.get(e);r&&r.destroy.forEach((r=>r(e)))})),a.clear(),window.requestAnimationFrame(c)},y=(e,a)=>{if(r.has(e))throw new Error("data is alreaby an observable");if(a&&!t.has(a))throw new Error("rootProxy isn’t an observable");let c;const d=new Proxy(e,{get:(e,r)=>e[r],set(e,r,n){if(e[r]!==n){if(c){if(t.has(n))throw new Error("Can’t nest observables");o.add(a||d)}e[r]=n}return!0},deleteProperty:(e,r)=>r in e&&(delete e[r],o.add(a||d),!0)});return r.add(e),t.set(d,e),(Array.isArray(e)?[...Array(e.length).keys()]:Object.keys(e)).forEach((r=>{const n=e[r];if(t.has(n))throw new Error("Can’t nest observables");(e=>Array.isArray(e)||(e=>!!e&&"object"==typeof e&&e.constructor===s)(e))(n)&&(d[r]=y(n,a||d))})),n.set(d,c={change:new Set,destroy:new Set}),d},d=e=>{if((e=>Array.isArray(e)||(e=>!!e&&"object"==typeof e&&e.constructor===s)(e))(e))return y(e);throw new Error("Only Arrays and plain Objects are observable")},h=(e,r,t)=>{const o=n.get(e);return!(!o||!o[r]||"function"!=typeof t||o[r].has(t))&&(o[r].add(t),!0)},l=(e,r,t)=>{const o=n.get(e);return!(!o||!o[r]||"function"!=typeof t)&&o[r].delete(t)},w=(r,t)=>h(r,e.change,t),i=(r,t)=>l(r,e.change,t),f=e=>{const a=n.get(e);return!!a&&(a.change.clear(),a.destroy.clear(),r.delete(t.get(e)),t.delete(e),n.delete(e),o.delete(e),!0)};c();export{e as ObservableEvents,f as destroy,d as observable,w as observe,l as off,h as on,i as unobserve}; +const e={change:"change",destroy:"destroy"},r=new Set,t=new Map,a=new Map,n=new Set,o=new Set,s={}.constructor,c=()=>{n.forEach((e=>{const r=a.get(e);r&&r.change.forEach((r=>r(e)))})),n.clear(),o.forEach((e=>{const r=a.get(e);r&&(r.destroy.forEach((r=>r(e))),r.change.clear(),r.destroy.clear(),t.delete(e),a.delete(e))})),o.clear(),window.requestAnimationFrame(c)},d=(e,o)=>{if(r.has(e)||t.has(e))throw new Error("data is alreaby an observable");let c;const y=new Proxy(e,{get:(e,r)=>e[r],set(e,r,a){if(e[r]!==a){if(c){if(t.has(a))throw new Error("Can’t nest observables");n.add(o||y)}e[r]=a}return!0},deleteProperty:(e,r)=>(r in e&&(delete e[r],n.add(o||y)),!0)});return r.add(e),t.set(y,e),(Array.isArray(e)?[...Array(e.length).keys()]:Object.keys(e)).forEach((r=>{const a=e[r];if(t.has(a))throw new Error("Can’t nest observables");(e=>Array.isArray(e)||(e=>!!e&&"object"==typeof e&&e.constructor===s)(e))(a)&&(y[r]=d(a,o||y))})),a.set(y,c={change:new Set,destroy:new Set}),y},y=e=>{if((e=>Array.isArray(e)||(e=>!!e&&"object"==typeof e&&e.constructor===s)(e))(e))return d(e);throw new Error("Only Arrays and plain Objects are observable")},h=(e,r,t)=>{const n=a.get(e);return!(!n||!n[r]||"function"!=typeof t||n[r].has(t))&&(n[r].add(t),!0)},l=(e,r,t)=>{const n=a.get(e);return!(!n||!n[r]||"function"!=typeof t)&&n[r].delete(t)},w=(r,t)=>h(r,e.change,t),f=(r,t)=>l(r,e.change,t),i=e=>!!a.get(e)&&(o.add(e),r.delete(t.get(e)),!0);c();export{e as ObservableEvents,i as destroy,y as observable,w as observe,l as off,h as on,f as unobserve}; diff --git a/lib/index.js b/lib/index.js index 6b4cce4..5c95e83 100644 --- a/lib/index.js +++ b/lib/index.js @@ -14,15 +14,19 @@ const ObservableEvents = { change: "change", destroy: "destroy" }, changedProxies.clear(), destroyedProxies.forEach((proxy) => { const observers = observersByProxy.get(proxy); - observers && observers.destroy.forEach((callback) => callback(proxy)); + observers && + (observers.destroy.forEach((callback) => callback(proxy)), + observers.change.clear(), + observers.destroy.clear(), + observablesByProxy.delete(proxy), + observersByProxy.delete(proxy)); }), destroyedProxies.clear(), setTimeout(tick, 16); }, makeObservableProxy = (data, rootProxy) => { - if (observables.has(data)) throw new Error("data is alreaby an observable"); - if (rootProxy && !observablesByProxy.has(rootProxy)) - throw new Error("rootProxy isn’t an observable"); + if (observables.has(data) || observablesByProxy.has(data)) + throw new Error("data is alreaby an observable"); let observers; const proxy = new Proxy(data, { get: (target, key) => target[key], @@ -37,9 +41,11 @@ const ObservableEvents = { change: "change", destroy: "destroy" }, } return !0; }, - deleteProperty: (target, key) => + deleteProperty: (target, key) => ( key in target && - (delete target[key], changedProxies.add(rootProxy || proxy), !0), + (delete target[key], changedProxies.add(rootProxy || proxy)), + !0 + ), }); return ( observables.add(data), @@ -86,19 +92,11 @@ const ObservableEvents = { change: "change", destroy: "destroy" }, }; tick(), (exports.ObservableEvents = ObservableEvents), - (exports.destroy = (observableProxy) => { - const observers = observersByProxy.get(observableProxy); - return ( - !!observers && - (observers.change.clear(), - observers.destroy.clear(), - observables.delete(observablesByProxy.get(observableProxy)), - observablesByProxy.delete(observableProxy), - observersByProxy.delete(observableProxy), - changedProxies.delete(observableProxy), - !0) - ); - }), + (exports.destroy = (observableProxy) => + !!observersByProxy.get(observableProxy) && + (destroyedProxies.add(observableProxy), + observables.delete(observablesByProxy.get(observableProxy)), + !0)), (exports.observable = (data) => { if ( ((data) => diff --git a/lib/index.mjs b/lib/index.mjs index 7593ed0..c3d653c 100644 --- a/lib/index.mjs +++ b/lib/index.mjs @@ -14,15 +14,19 @@ const ObservableEvents = { change: "change", destroy: "destroy" }, changedProxies.clear(), destroyedProxies.forEach((proxy) => { const observers = observersByProxy.get(proxy); - observers && observers.destroy.forEach((callback) => callback(proxy)); + observers && + (observers.destroy.forEach((callback) => callback(proxy)), + observers.change.clear(), + observers.destroy.clear(), + observablesByProxy.delete(proxy), + observersByProxy.delete(proxy)); }), destroyedProxies.clear(), setTimeout(tick, 16); }, makeObservableProxy = (data, rootProxy) => { - if (observables.has(data)) throw new Error("data is alreaby an observable"); - if (rootProxy && !observablesByProxy.has(rootProxy)) - throw new Error("rootProxy isn’t an observable"); + if (observables.has(data) || observablesByProxy.has(data)) + throw new Error("data is alreaby an observable"); let observers; const proxy = new Proxy(data, { get: (target, key) => target[key], @@ -37,9 +41,11 @@ const ObservableEvents = { change: "change", destroy: "destroy" }, } return !0; }, - deleteProperty: (target, key) => + deleteProperty: (target, key) => ( key in target && - (delete target[key], changedProxies.add(rootProxy || proxy), !0), + (delete target[key], changedProxies.add(rootProxy || proxy)), + !0 + ), }); return ( observables.add(data), @@ -100,18 +106,10 @@ const ObservableEvents = { change: "change", destroy: "destroy" }, on(observableProxy, ObservableEvents.change, callback), unobserve = (observableProxy, callback) => off(observableProxy, ObservableEvents.change, callback), - destroy = (observableProxy) => { - const observers = observersByProxy.get(observableProxy); - return ( - !!observers && - (observers.change.clear(), - observers.destroy.clear(), - observables.delete(observablesByProxy.get(observableProxy)), - observablesByProxy.delete(observableProxy), - observersByProxy.delete(observableProxy), - changedProxies.delete(observableProxy), - !0) - ); - }; + destroy = (observableProxy) => + !!observersByProxy.get(observableProxy) && + (destroyedProxies.add(observableProxy), + observables.delete(observablesByProxy.get(observableProxy)), + !0); tick(); export { ObservableEvents, destroy, observable, observe, off, on, unobserve }; From 5f18f8247ad9e83dcf7d342f9f7b41318e3ad4ef Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 27 Dec 2023 16:09:40 -0500 Subject: [PATCH 43/53] Removed call to console.log --- scripts/test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/test.ts b/scripts/test.ts index 6e22c98..5024bec 100644 --- a/scripts/test.ts +++ b/scripts/test.ts @@ -83,7 +83,6 @@ describe('observable()', () => { test('Throws error when object is already observable', () => { const state = observable({}); - console.log(state); expect(() => { const state2 = observable(state); }).toThrow(Error); From 9766c91f89507939b5c8170f00f5b9f1cfe80da2 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 27 Dec 2023 16:32:02 -0500 Subject: [PATCH 44/53] Added tests for Map and Set --- scripts/test.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/scripts/test.ts b/scripts/test.ts index 5024bec..dd39373 100644 --- a/scripts/test.ts +++ b/scripts/test.ts @@ -62,6 +62,18 @@ describe('observable()', () => { }).toThrow(Error); }); + test('Throws error when passed Map', () => { + expect(() => { + const state = observable(new Map()); + }).toThrow(Error); + }); + + test('Throws error when passed Set', () => { + expect(() => { + const state = observable(new Set()); + }).toThrow(Error); + }); + test('Throws error when passed undefined', () => { expect(() => { const state = observable(undefined as any); From 5ff3e6531ab5deacbfda7466c6b8f5450d7e7fb1 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 27 Dec 2023 16:32:14 -0500 Subject: [PATCH 45/53] Added tests for deleting properties --- scripts/test.ts | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/scripts/test.ts b/scripts/test.ts index dd39373..21522d1 100644 --- a/scripts/test.ts +++ b/scripts/test.ts @@ -526,4 +526,31 @@ describe('destroy()', () => { expect(destroyCallback).toHaveBeenCalledTimes(1); }); +}); + +describe('miscellaneous', () => { + + test('Deleting an existing property returns true', () => { + const state = observable({ + test: 'test' + }); + expect(delete state.test).toEqual(true); + }); + + // we return true even if a property is non-existent to avoid + // an error being thrown in Node + test('Deleting a non-existent property returns true', () => { + const state = observable({}); + expect(delete state.test).toEqual(true); + }); + + test('Deleted property no longer exists on observable proxy', () => { + const state = observable({ + test: 'test' + }); + expect('test' in state).toEqual(true); + delete state.test; + expect('test' in state).toEqual(false); + }); + }); \ No newline at end of file From 3bd858278986bd83b7bc3775150c676704260c10 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 27 Dec 2023 16:32:37 -0500 Subject: [PATCH 46/53] Modified note regarding roadmap --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bc70270..c4ee150 100644 --- a/README.md +++ b/README.md @@ -150,7 +150,7 @@ console.log('before state changed callback'); Version 3.0 will consider the following change: -- Add support for Map and Set +- Support for Map and Set - Instances of classes are observable ## Browser Support From c3b6186173f6f791a1837f8439985ecc5a879e81 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 27 Dec 2023 17:00:23 -0500 Subject: [PATCH 47/53] Removed use of createState function in tests that can use a simpler object --- scripts/test.ts | 148 +++++++++++++++++++++++++++++------------------- 1 file changed, 90 insertions(+), 58 deletions(-) diff --git a/scripts/test.ts b/scripts/test.ts index 21522d1..be245ae 100644 --- a/scripts/test.ts +++ b/scripts/test.ts @@ -101,7 +101,7 @@ describe('observable()', () => { }); test('Throws error when observables are nested', () => { - const state1 = observable(createState()); + const state1 = observable({}); expect(() => { const state2 = observable({ state: state1 @@ -123,36 +123,40 @@ describe('observe()', () => { test('Triggers deferred callback when adding object key', () => { const callback = jest.fn(); - const state = observable(createState()); + const state = observable({}); observe(state, callback); - state.string2 = 'test2'; + state.test = 'test'; expect(callback).not.toBeCalled(); jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); - expect(state.string2).toEqual('test2'); + expect(state.test).toEqual('test'); }); test('Triggers deferred callback when modifying object key', () => { const callback = jest.fn(); - const state = observable(createState()); + const state = observable({ + test: 'test' + }); observe(state, callback); - expect(state.boolean).toEqual(true); - state.boolean = false; + expect(state.test).toEqual('test'); + state.test = 'test2'; expect(callback).not.toBeCalled(); jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); - expect(state.boolean).toEqual(false); + expect(state.test).toEqual('test2'); }); test('Triggers deferred callback when deleting object key', () => { const callback = jest.fn(); - const state = observable(createState()); + const state = observable({ + test: 'test', + }); observe(state, callback); - delete state.string; + delete state.test; expect(callback).not.toBeCalled(); jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); - expect(state.string).toEqual(undefined); + expect('test' in state).toEqual(false); }); test('Does not trigger deferred callback when deleting non-existent key', () => { @@ -167,30 +171,36 @@ describe('observe()', () => { test('Triggers deferred callback when modifying mutliple object keys', () => { const callback = jest.fn(); - const state = observable(createState()); + const state = observable({ + test: 'test', + test2: 'test2', + }); observe(state, callback); - state.boolean = false; - state.number = 1; + state.test = 'test3'; + state.test2 = 'test4'; expect(callback).not.toBeCalled(); jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); - expect(state.boolean).toEqual(false); - expect(state.number).toEqual(1); + expect(state.test).toEqual('test3'); + expect(state.test2).toEqual('test4'); }); test('Triggers deferred callback when modifying object using Object.assign()', () => { const callback = jest.fn(); - const state = observable(createState()); + const state = observable({ + test: 'test', + test2: 'test2', + }); observe(state, callback); Object.assign(state, { - boolean: false, - number: 1 + test: 'test3', + test2: 'test4', }); expect(callback).not.toBeCalled(); jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); - expect(state.boolean).toEqual(false); - expect(state.number).toEqual(1); + expect(state.test).toEqual('test3'); + expect(state.test2).toEqual('test4'); }); test('Triggers deferred callback when modifying array using pop', () => { @@ -284,7 +294,7 @@ describe('observe()', () => { }); test('When trying to observe a non-observable returns false', () => { - const obj1 = createState(); + const obj1 = {}; expect(observe(obj1, ()=>{})).toEqual(false); }); @@ -294,36 +304,40 @@ describe('on()', () => { test('Triggers deferred callback when adding object key', () => { const callback = jest.fn(); - const state = observable(createState()); + const state = observable({}); on(state, ObservableEvents.change, callback); - state.string2 = 'test2'; + state.test = 'test'; expect(callback).not.toBeCalled(); jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); - expect(state.string2).toEqual('test2'); + expect(state.test).toEqual('test'); }); test('Triggers deferred callback when modifying object key', () => { const callback = jest.fn(); - const state = observable(createState()); + const state = observable({ + test: 'test', + }); on(state, ObservableEvents.change, callback); - expect(state.boolean).toEqual(true); - state.boolean = false; + expect(state.test).toEqual('test'); + state.test = 'test2'; expect(callback).not.toBeCalled(); jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); - expect(state.boolean).toEqual(false); + expect(state.test).toEqual('test2'); }); test('Triggers deferred callback when deleting object key', () => { const callback = jest.fn(); - const state = observable(createState()); + const state = observable({ + test: 'test', + }); on(state, ObservableEvents.change, callback); - delete state.string; + delete state.test; expect(callback).not.toBeCalled(); jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); - expect(state.string).toEqual(undefined); + expect('test' in state).toEqual(false); }); test('Triggers deferred callback when modifying mutliple object keys', () => { @@ -341,17 +355,17 @@ describe('on()', () => { test('Triggers deferred callback when modifying object using Object.assign()', () => { const callback = jest.fn(); - const state = observable(createState()); + const state = observable({ + test: 'test', + }); on(state, ObservableEvents.change, callback); Object.assign(state, { - boolean: false, - number: 1 + test: 'test2', }); expect(callback).not.toBeCalled(); jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); - expect(state.boolean).toEqual(false); - expect(state.number).toEqual(1); + expect(state.test).toEqual('test2'); }); test('Triggers deferred callback when modifying array using pop', () => { @@ -408,27 +422,45 @@ describe('on()', () => { test('Triggers deferred callback when modifying nested array', () => { const callback = jest.fn(); - const state = observable(createState()); + const state = observable({ + test: [1, 2, 3] + }); on(state, ObservableEvents.change, callback); - expect(state.array).toEqual([1, 2, 3]); - state.array.push(4); + expect(state.test).toEqual([1, 2, 3]); + state.test.push(4); expect(callback).not.toBeCalled(); jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); - expect(state.array.length).toEqual(4); - expect(state.array).toEqual([1, 2, 3, 4]); + expect(state.test.length).toEqual(4); + expect(state.test).toEqual([1, 2, 3, 4]); }); - test('Triggers deferred callback when modifying nested object', () => { + test('Triggers deferred callback when adding key to nested object', () => { const callback = jest.fn(); - const state = observable(createState()); + const state = observable({ + test: {} + }); on(state, ObservableEvents.change, callback); - expect(state.array).toEqual([1, 2, 3]); - state.object.string2 = 'test2'; + state.test.test = 'test'; expect(callback).not.toBeCalled(); jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); - expect(state.object.string2).toEqual('test2'); + expect(state.test.test).toEqual('test'); + }); + + test('Triggers deferred callback when modifying nested object key', () => { + const callback = jest.fn(); + const state = observable({ + test: { + test: 'test', + }, + }); + on(state, ObservableEvents.change, callback); + state.test.test = 'test2'; + expect(callback).not.toBeCalled(); + jest.advanceTimersByTime(global.FRAME_TIME); + expect(callback).toHaveBeenCalledTimes(1); + expect(state.test.test).toEqual('test2'); }); test('Triggers deferred callback when reobserved', () => { @@ -457,26 +489,26 @@ describe('unobserve()', () => { test('No callback when object is unobserved', () => { const callback = jest.fn(); - const state = observable(createState()); + const state = observable({}); observe(state, callback); - state.string = 'test2'; + state.test = 'test'; jest.advanceTimersByTime(global.FRAME_TIME); - expect(state.string).toEqual('test2'); + expect(state.test).toEqual('test'); expect(callback).toHaveBeenCalledTimes(1); unobserve(state, callback); - state.string = 'test3'; + state.test = 'test2'; jest.advanceTimersByTime(global.FRAME_TIME); expect(callback).toHaveBeenCalledTimes(1); - expect(state.string).toEqual('test3'); + expect(state.test).toEqual('test2'); }); test('After destroying a non-observable returns false', () => { - const state1 = destroy(observable(createState())); + const state1 = destroy(observable({})); expect(unobserve(state1 as any, ()=>{})).toEqual(false); }); test('When trying to unobserve a non-observable returns false w', () => { - const obj1 = createState(); + const obj1 = {}; expect(unobserve(obj1, ()=>{})).toEqual(false); }); @@ -485,22 +517,22 @@ describe('unobserve()', () => { describe('destroy()', () => { test('When destroying an observable retuns true', () => { - const state1 = observable(createState()); + const state1 = observable({}); expect(destroy(state1)).toEqual(true); }); test('When destroying a non-observable returns false', () => { - const state1 = destroy(observable(createState())); + const state1 = destroy(observable({})); expect(observe(state1 as any, ()=>{})).toEqual(false); }); test('Destroying an non-observable multiple times returns false', () => { - const state1 = destroy(observable(createState())); + const state1 = destroy(observable({})); expect(destroy(state1 as any)).toEqual(false); }); test('When trying to destroy a non-observable returns false', () => { - const state1 = createState(); + const state1 = {}; expect(destroy(state1)).toEqual(false); }); From 52d3196a62ae5ca4bce7afc0526c0956f6ab86e2 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 27 Dec 2023 17:07:53 -0500 Subject: [PATCH 48/53] Moved scripts/test.ts to src/index.test.ts --- scripts/test.ts => src/index.test.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename scripts/test.ts => src/index.test.ts (100%) diff --git a/scripts/test.ts b/src/index.test.ts similarity index 100% rename from scripts/test.ts rename to src/index.test.ts From 95ee450447fcda0413e8acdc7b6f5b883f071649 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 27 Dec 2023 17:08:39 -0500 Subject: [PATCH 49/53] Change import path --- src/index.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.test.ts b/src/index.test.ts index be245ae..e4fa452 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -1,4 +1,4 @@ -import { observable, on, off, observe, unobserve, destroy, Observable, ObservableEvents } from '../src/index'; +import { observable, on, off, observe, unobserve, destroy, Observable, ObservableEvents } from './index'; function createState(): Observable { return { From 7bdc0284dd645a88f672dbcdfcae001d844233c1 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 27 Dec 2023 19:05:54 -0500 Subject: [PATCH 50/53] Renamed demo and made changed observe to on --- demo/{index.html => single-observer.html} | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) rename demo/{index.html => single-observer.html} (50%) diff --git a/demo/index.html b/demo/single-observer.html similarity index 50% rename from demo/index.html rename to demo/single-observer.html index 0d2405d..40c44a1 100644 --- a/demo/index.html +++ b/demo/single-observer.html @@ -9,20 +9,20 @@ Check the console :) From 5c18b88bc4c7c762027ccff4ae42fceedcf9aae0 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 27 Dec 2023 19:06:07 -0500 Subject: [PATCH 51/53] Added multi observer demo based on readme example --- demo/multi-obserever.html | 45 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 demo/multi-obserever.html diff --git a/demo/multi-obserever.html b/demo/multi-obserever.html new file mode 100644 index 0000000..9ae1096 --- /dev/null +++ b/demo/multi-obserever.html @@ -0,0 +1,45 @@ + + + + + Simple Observable Proxy Demo + + + + + Check the console :) + + + \ No newline at end of file From 12da8abaf029692113a3b0c8e492fa9b1d348315 Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Wed, 27 Dec 2023 19:06:23 -0500 Subject: [PATCH 52/53] Modified performance demo to use preferred v2 syntax --- demo/performance.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/demo/performance.html b/demo/performance.html index ad86626..0cd9cef 100644 --- a/demo/performance.html +++ b/demo/performance.html @@ -9,7 +9,7 @@ Check the console :)