diff --git a/package-lock.json b/package-lock.json index 75e6d5b9..24d922cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -541,6 +541,17 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime": { + "version": "7.22.6", + "dev": true, + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.21.9", "dev": true, @@ -1249,6 +1260,70 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@testing-library/dom": { + "version": "9.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.1.3", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@testing-library/dom/node_modules/ansi-styles": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/pretty-format": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@testing-library/dom/node_modules/react-is": { + "version": "17.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@testing-library/react": { + "version": "14.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^9.0.0", + "@types/react-dom": "^18.0.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "dev": true, @@ -1266,6 +1341,11 @@ "@types/readdir-glob": "*" } }, + "node_modules/@types/aria-query": { + "version": "5.0.1", + "dev": true, + "license": "MIT" + }, "node_modules/@types/babel__core": { "version": "7.20.1", "dev": true, @@ -1398,6 +1478,29 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/prop-types": { + "version": "15.7.5", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.2.14", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.2.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/readdir-glob": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/readdir-glob/-/readdir-glob-1.1.1.tgz", @@ -1407,6 +1510,11 @@ "@types/node": "*" } }, + "node_modules/@types/scheduler": { + "version": "0.16.3", + "dev": true, + "license": "MIT" + }, "node_modules/@types/semver": { "version": "7.5.0", "dev": true, @@ -2132,6 +2240,14 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/aria-query": { + "version": "5.1.3", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "deep-equal": "^2.0.5" + } + }, "node_modules/arr-diff": { "version": "4.0.0", "dev": true, @@ -3439,6 +3555,11 @@ "dev": true, "license": "MIT" }, + "node_modules/csstype": { + "version": "3.1.2", + "dev": true, + "license": "MIT" + }, "node_modules/cyclist": { "version": "1.0.2", "dev": true, @@ -3694,6 +3815,39 @@ "dev": true, "license": "MIT" }, + "node_modules/deep-equal": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.0", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.0", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-equal/node_modules/isarray": { + "version": "2.0.5", + "dev": true, + "license": "MIT" + }, "node_modules/deep-is": { "version": "0.1.4", "dev": true, @@ -3803,6 +3957,11 @@ "node": ">=6.0.0" } }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "dev": true, + "license": "MIT" + }, "node_modules/domain-browser": { "version": "1.2.0", "dev": true, @@ -3992,6 +4151,30 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-get-iterator/node_modules/isarray": { + "version": "2.0.5", + "dev": true, + "license": "MIT" + }, "node_modules/es-module-lexer": { "version": "1.3.0", "license": "MIT" @@ -5627,6 +5810,21 @@ "node": ">=0.10.0" } }, + "node_modules/is-arguments": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-array-buffer": { "version": "3.0.2", "dev": true, @@ -5794,6 +5992,14 @@ "node": ">=0.10.0" } }, + "node_modules/is-map": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-natural-number": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", @@ -5872,6 +6078,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-set": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-shared-array-buffer": { "version": "1.0.2", "dev": true, @@ -5940,6 +6154,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-weakmap": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-weakref": { "version": "1.0.2", "dev": true, @@ -5951,6 +6173,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-weakset": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-windows": { "version": "1.0.2", "dev": true, @@ -6674,7 +6908,6 @@ }, "node_modules/js-tokens": { "version": "4.0.0", - "dev": true, "license": "MIT" }, "node_modules/js-yaml": { @@ -6914,6 +7147,17 @@ "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==" }, + "node_modules/loose-envify": { + "version": "1.4.0", + "license": "MIT", + "peer": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, "node_modules/lru-cache": { "version": "9.1.1", "dev": true, @@ -6922,6 +7166,14 @@ "node": "14 || >=16.14" } }, + "node_modules/lz-string": { + "version": "1.5.0", + "dev": true, + "license": "MIT", + "bin": { + "lz-string": "bin/bin.js" + } + }, "node_modules/make-dir": { "version": "3.1.0", "dev": true, @@ -7415,6 +7667,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object-is": { + "version": "1.1.5", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/object-keys": { "version": "1.1.1", "dev": true, @@ -8054,6 +8321,30 @@ "safe-buffer": "^5.1.0" } }, + "node_modules/react": { + "version": "18.2.0", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.2.0", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, "node_modules/react-is": { "version": "18.2.0", "dev": true, @@ -8133,6 +8424,11 @@ "node": ">= 10.13.0" } }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "dev": true, + "license": "MIT" + }, "node_modules/regex-not": { "version": "1.0.2", "dev": true, @@ -8380,6 +8676,15 @@ "node": ">=v12.22.7" } }, + "node_modules/scheduler": { + "version": "0.23.0", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + } + }, "node_modules/schema-utils": { "version": "3.3.0", "license": "MIT", @@ -8410,7 +8715,7 @@ } }, "node_modules/semver": { - "version": "7.5.1", + "version": "7.5.4", "dev": true, "license": "ISC", "dependencies": { @@ -8907,6 +9212,17 @@ "node": ">=0.10.0" } }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/stream-browserify": { "version": "2.0.2", "dev": true, @@ -9425,7 +9741,7 @@ } }, "node_modules/ts-jest": { - "version": "29.1.0", + "version": "29.1.1", "dev": true, "license": "MIT", "dependencies": { @@ -9435,7 +9751,7 @@ "json5": "^2.2.3", "lodash.memoize": "4.x", "make-error": "1.x", - "semver": "7.x", + "semver": "^7.5.3", "yargs-parser": "^21.0.1" }, "bin": { @@ -9632,9 +9948,8 @@ }, "node_modules/typescript": { "version": "5.0.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", - "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -10885,6 +11200,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/which-collection": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/which-typed-array": { "version": "1.1.9", "dev": true, @@ -11230,7 +11559,15 @@ "version": "0.0.1", "license": "MIT", "devDependencies": { + "@testing-library/react": "^14.0.0", + "@types/react": "^18.2.14", + "jest": "^29.5.0", + "jest-environment-jsdom": "^29.5.0", + "ts-jest": "^29.1.1", "typescript": "^5.0.4" + }, + "peerDependencies": { + "react": ">=16.14.0" } }, "packages/sdk-core": { @@ -11629,6 +11966,13 @@ "@babel/helper-plugin-utils": "^7.20.2" } }, + "@babel/runtime": { + "version": "7.22.6", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.11" + } + }, "@babel/template": { "version": "7.21.9", "dev": true, @@ -11710,6 +12054,11 @@ "@backtrace/react": { "version": "file:packages/react", "requires": { + "@testing-library/react": "^14.0.0", + "@types/react": "^18.2.14", + "jest": "^29.5.0", + "jest-environment-jsdom": "^29.5.0", + "ts-jest": "^29.1.1", "typescript": "^5.0.4" } }, @@ -11726,7 +12075,7 @@ "version": "file:tools/sourcemap-tools", "requires": { "@types/archiver": "^5.3.2", - "@types/decompress": "*", + "@types/decompress": "^4.2.4", "@types/jest": "^29.5.1", "archiver": "^5.3.1", "decompress": "^4.2.1", @@ -12191,6 +12540,48 @@ "@sinonjs/commons": "^3.0.0" } }, + "@testing-library/dom": { + "version": "9.3.1", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.1.3", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "dev": true + }, + "pretty-format": { + "version": "27.5.1", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "dev": true + } + } + }, + "@testing-library/react": { + "version": "14.0.0", + "dev": true, + "requires": { + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^9.0.0", + "@types/react-dom": "^18.0.0" + } + }, "@tootallnate/once": { "version": "2.0.0", "dev": true @@ -12204,6 +12595,10 @@ "@types/readdir-glob": "*" } }, + "@types/aria-query": { + "version": "5.0.1", + "dev": true + }, "@types/babel__core": { "version": "7.20.1", "dev": true, @@ -12319,6 +12714,26 @@ "version": "2.7.2", "dev": true }, + "@types/prop-types": { + "version": "15.7.5", + "dev": true + }, + "@types/react": { + "version": "18.2.14", + "dev": true, + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "@types/react-dom": { + "version": "18.2.6", + "dev": true, + "requires": { + "@types/react": "*" + } + }, "@types/readdir-glob": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/readdir-glob/-/readdir-glob-1.1.1.tgz", @@ -12328,6 +12743,10 @@ "@types/node": "*" } }, + "@types/scheduler": { + "version": "0.16.3", + "dev": true + }, "@types/semver": { "version": "7.5.0", "dev": true @@ -12822,6 +13241,13 @@ "version": "2.0.1", "dev": true }, + "aria-query": { + "version": "5.1.3", + "dev": true, + "requires": { + "deep-equal": "^2.0.5" + } + }, "arr-diff": { "version": "4.0.0", "dev": true @@ -13738,6 +14164,10 @@ } } }, + "csstype": { + "version": "3.1.2", + "dev": true + }, "cyclist": { "version": "1.0.2", "dev": true @@ -13937,6 +14367,36 @@ "version": "0.7.0", "dev": true }, + "deep-equal": { + "version": "2.2.1", + "dev": true, + "requires": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.0", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.0", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "dev": true + } + } + }, "deep-is": { "version": "0.1.4", "dev": true @@ -14009,6 +14469,10 @@ "esutils": "^2.0.2" } }, + "dom-accessibility-api": { + "version": "0.5.16", + "dev": true + }, "domain-browser": { "version": "1.2.0", "dev": true @@ -14143,6 +14607,27 @@ "which-typed-array": "^1.1.9" } }, + "es-get-iterator": { + "version": "1.1.3", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "dev": true + } + } + }, "es-module-lexer": { "version": "1.3.0" }, @@ -15215,6 +15700,14 @@ "kind-of": "^6.0.0" } }, + "is-arguments": { + "version": "1.1.1", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, "is-array-buffer": { "version": "3.0.2", "dev": true, @@ -15315,6 +15808,10 @@ "is-extglob": "^2.1.1" } }, + "is-map": { + "version": "2.0.2", + "dev": true + }, "is-natural-number": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", @@ -15359,6 +15856,10 @@ "has-tostringtag": "^1.0.0" } }, + "is-set": { + "version": "2.0.2", + "dev": true + }, "is-shared-array-buffer": { "version": "1.0.2", "dev": true, @@ -15395,6 +15896,10 @@ "has-tostringtag": "^1.0.0" } }, + "is-weakmap": { + "version": "2.0.1", + "dev": true + }, "is-weakref": { "version": "1.0.2", "dev": true, @@ -15402,6 +15907,14 @@ "call-bind": "^1.0.2" } }, + "is-weakset": { + "version": "2.0.2", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, "is-windows": { "version": "1.0.2", "dev": true @@ -15896,8 +16409,7 @@ } }, "js-tokens": { - "version": "4.0.0", - "dev": true + "version": "4.0.0" }, "js-yaml": { "version": "4.1.0", @@ -16061,10 +16573,21 @@ "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==" }, + "loose-envify": { + "version": "1.4.0", + "peer": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, "lru-cache": { "version": "9.1.1", "dev": true }, + "lz-string": { + "version": "1.5.0", + "dev": true + }, "make-dir": { "version": "3.1.0", "dev": true, @@ -16414,6 +16937,14 @@ "version": "1.12.3", "dev": true }, + "object-is": { + "version": "1.1.5", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, "object-keys": { "version": "1.1.1", "dev": true @@ -16814,6 +17345,22 @@ "safe-buffer": "^5.1.0" } }, + "react": { + "version": "18.2.0", + "peer": true, + "requires": { + "loose-envify": "^1.1.0" + } + }, + "react-dom": { + "version": "18.2.0", + "dev": true, + "peer": true, + "requires": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + } + }, "react-is": { "version": "18.2.0", "dev": true @@ -16882,6 +17429,10 @@ "resolve": "^1.20.0" } }, + "regenerator-runtime": { + "version": "0.13.11", + "dev": true + }, "regex-not": { "version": "1.0.2", "dev": true, @@ -17021,6 +17572,14 @@ "xmlchars": "^2.2.0" } }, + "scheduler": { + "version": "0.23.0", + "dev": true, + "peer": true, + "requires": { + "loose-envify": "^1.1.0" + } + }, "schema-utils": { "version": "3.3.0", "requires": { @@ -17039,7 +17598,7 @@ } }, "semver": { - "version": "7.5.1", + "version": "7.5.4", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -17385,6 +17944,13 @@ } } }, + "stop-iteration-iterator": { + "version": "1.0.0", + "dev": true, + "requires": { + "internal-slot": "^1.0.4" + } + }, "stream-browserify": { "version": "2.0.2", "dev": true, @@ -17732,7 +18298,7 @@ } }, "ts-jest": { - "version": "29.1.0", + "version": "29.1.1", "dev": true, "requires": { "bs-logger": "0.x", @@ -17741,7 +18307,7 @@ "json5": "^2.2.3", "lodash.memoize": "4.x", "make-error": "1.x", - "semver": "7.x", + "semver": "^7.5.3", "yargs-parser": "^21.0.1" }, "dependencies": { @@ -17850,8 +18416,6 @@ }, "typescript": { "version": "5.0.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", - "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", "dev": true }, "ua-parser-js": { @@ -18730,6 +19294,16 @@ "is-symbol": "^1.0.3" } }, + "which-collection": { + "version": "1.0.1", + "dev": true, + "requires": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + } + }, "which-typed-array": { "version": "1.1.9", "dev": true, diff --git a/packages/browser/src/index.ts b/packages/browser/src/index.ts index f019e6eb..85fa6096 100644 --- a/packages/browser/src/index.ts +++ b/packages/browser/src/index.ts @@ -2,3 +2,5 @@ export { BacktraceReport } from '@backtrace/sdk-core'; export * from '@backtrace/sdk-core/lib/model/attachment'; export * from './BacktraceClient'; export * from './BacktraceConfiguration'; +export * from './builder/BacktraceClientBuilder'; +export * from './agentDefinition'; diff --git a/packages/react/jest.config.js b/packages/react/jest.config.js new file mode 100644 index 00000000..5d54b9b5 --- /dev/null +++ b/packages/react/jest.config.js @@ -0,0 +1,5 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} */ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'jsdom', +}; diff --git a/packages/react/package.json b/packages/react/package.json index 17695415..c4a3f42c 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -8,7 +8,8 @@ "clean": "rimraf \"lib\"", "format": "prettier --write '**/*.ts'", "lint": "eslint . --ext .ts", - "watch": "webpack -w" + "watch": "webpack -w", + "test": "NODE_ENV=test jest" }, "repository": { "type": "git", @@ -31,6 +32,14 @@ }, "homepage": "https://github.com/backtrace-labs/backtrace-javascript#readme", "devDependencies": { + "@testing-library/react": "^14.0.0", + "@types/react": "^18.2.14", + "jest": "^29.5.0", + "jest-environment-jsdom": "^29.5.0", + "ts-jest": "^29.1.1", "typescript": "^5.0.4" + }, + "peerDependencies": { + "react": ">=16.14.0" } } diff --git a/packages/react/src/BacktraceClient.ts b/packages/react/src/BacktraceClient.ts new file mode 100644 index 00000000..b5780c09 --- /dev/null +++ b/packages/react/src/BacktraceClient.ts @@ -0,0 +1,37 @@ +import { + BacktraceAttributeProvider, + BacktraceCoreClient, + BacktraceRequestHandler, + BacktraceStackTraceConverter, +} from '@backtrace/sdk-core'; +import { AGENT } from '@backtrace/browser'; +import { BacktraceConfiguration } from '@backtrace/browser'; +import { BacktraceClientBuilder } from '@backtrace/browser'; + +export class BacktraceClient extends BacktraceCoreClient { + private static _instance?: BacktraceClient; + constructor( + options: BacktraceConfiguration, + handler: BacktraceRequestHandler, + attributeProviders: BacktraceAttributeProvider[], + stackTraceConverter: BacktraceStackTraceConverter, + ) { + super(options, AGENT, handler, attributeProviders, stackTraceConverter); + } + + public static builder(options: BacktraceConfiguration): BacktraceClientBuilder { + return new BacktraceClientBuilder(options); + } + + public static initialize(options: BacktraceConfiguration): BacktraceClient { + this._instance = this.builder(options).build(); + return this._instance; + } + + public static get instance(): BacktraceClient { + if (!this._instance) { + throw new Error('BacktraceClient is uninitialized. Call "BacktraceClient.initialize" function first.'); + } + return this._instance; + } +} diff --git a/packages/react/src/ErrorBoundary.tsx b/packages/react/src/ErrorBoundary.tsx new file mode 100644 index 00000000..4cf94e44 --- /dev/null +++ b/packages/react/src/ErrorBoundary.tsx @@ -0,0 +1,52 @@ +import { Component, ErrorInfo, ReactElement, ReactNode, isValidElement } from 'react'; +import { BacktraceClient } from './BacktraceClient'; + +type RenderFallback = () => ReactElement; + +export interface Props { + children: ReactNode; + fallback?: ReactElement | RenderFallback; +} + +export interface State { + hasError: boolean; + error?: Error; +} + +export class ErrorBoundary extends Component { + private _client: BacktraceClient; + constructor(props: Props) { + super(props); + this.state = { + hasError: false, + error: undefined, + }; + // grabbing here so it will fail fast if BacktraceClient is uninitialized + this._client = BacktraceClient.instance; + } + + static getDerivedStateFromError(error: Error) { + return { hasError: true, error }; + } + + componentDidCatch(error: Error, info: ErrorInfo) { + this._client.send(error); + } + + render() { + const { fallback, children } = this.props; + + if (!this.state.hasError) { + return children; + } + + const fallbackComponent = typeof fallback === 'function' ? fallback() : fallback; + + if (fallbackComponent && isValidElement(fallbackComponent)) { + return fallbackComponent; + } + + // no or invalid fallback + return null; + } +} diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index ee259e05..1263636a 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -1 +1,3 @@ export * from '@backtrace/browser'; +export * from './ErrorBoundary'; +export { BacktraceClient } from './BacktraceClient'; diff --git a/packages/react/tests/errorBoundaryTests.spec.tsx b/packages/react/tests/errorBoundaryTests.spec.tsx new file mode 100644 index 00000000..f397788a --- /dev/null +++ b/packages/react/tests/errorBoundaryTests.spec.tsx @@ -0,0 +1,86 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import { ErrorBoundary } from '../src/ErrorBoundary'; +import { BacktraceClient } from '../src/BacktraceClient'; + +describe('Error Boundary', () => { + const childrenText = 'I am the children'; + const fallbackText = 'This is a fallback'; + const errorText = 'Rendering error!'; + + function ValidComponent() { + return

{childrenText}

; + } + + function ErrorComponent() { + throw new Error(errorText); + return

{childrenText}

; + } + + function Fallback() { + return

{fallbackText}

; + } + + const fallbackFunction = () => ; + + describe('With BacktraeClient uninitialized', () => { + it('Should throw an error when BacktraceClient is uninitialized and an ErrorBoundary is used', () => { + expect(() => + render(}>{}), + ).toThrowError(); + }); + }); + + describe('With BacktraceClient initialized', () => { + let client: BacktraceClient; + beforeEach(() => { + client = BacktraceClient.initialize({ + url: `https://submit.backtrace.io/universe/token/json`, + name: 'test', + version: '1.0.0', + }); + }); + + it('Should not throw an error when BacktraceClient is initialized and an ErrorBoundary is used', () => { + expect(() => + render({}), + ).not.toThrowError(); + }); + + it('Should render children', () => { + render({}); + expect(screen.getByText(childrenText)); + }); + + it('Should render fallback function on rendering error', () => { + render({}); + expect(screen.getByText(fallbackText)); + }); + + it('Should render fallback component on rendering error', () => { + render(}>{}); + expect(screen.getByText(fallbackText)); + }); + + it('Should render nothing if no fallback is passed in and rendering error', () => { + const { container } = render( + + + , + ); + expect(container.firstChild).toBeNull(); + }); + + it('Should send to Backtrace on rendering error', () => { + const clientSpy = jest.spyOn(client, 'send'); + render(}>{}); + expect(clientSpy).toHaveBeenCalled(); + }); + + it('Should not send to Backtrace when no rendering error occurs', () => { + const clientSpy = jest.spyOn(client, 'send'); + render(}>{}); + expect(clientSpy).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/packages/react/tsconfig.json b/packages/react/tsconfig.json index c30e95c5..c66b8503 100644 --- a/packages/react/tsconfig.json +++ b/packages/react/tsconfig.json @@ -2,7 +2,8 @@ "extends": "../../tsconfig.base.json", "compilerOptions": { "rootDir": "./src", - "outDir": "./lib" + "outDir": "./lib", + "jsx": "react" }, "exclude": ["node_modules", "tests", "lib"], "references": [