diff --git a/.rollup/index.mjs b/.rollup/index.mjs index 24605f46b0..0861ab51f4 100644 --- a/.rollup/index.mjs +++ b/.rollup/index.mjs @@ -14,7 +14,7 @@ const defaultOptions = () => ({ output: undefined }) -const sharedOutput = { +export const sharedOutput = { dir: 'dist', generatedCode: { preset: 'es2015', @@ -59,7 +59,8 @@ function createRollupConfig (options = defaultOptions()) { emitDeclarationOnly: true, declarationDir: 'dist/types', } - }) + }), + ...(options.plugins ?? []) ] } } diff --git a/package-lock.json b/package-lock.json index 8533170476..262f10edd4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52,7 +52,6 @@ "browserify": "^17.0.1", "browserify-versionify": "^1.0.6", "coverage-diff": "^1.6.0", - "cross-env": "^7.0.3", "electron": "*", "envify": "^4.1.0", "eslint": "^6.8.0", @@ -74,7 +73,6 @@ "ncp": "^2.0.0", "node-fetch": "^2.6.0", "playwright": "^1.10.0", - "proxyquire": "^2.1.3", "ps-list": "^7.2.0", "react": "^16.13.1", "react-native": "^0.63.4", @@ -9680,6 +9678,32 @@ "nanoid": "^3.1.15" } }, + "node_modules/@rollup/plugin-babel": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-6.0.4.tgz", + "integrity": "sha512-YF7Y52kFdFT/xVSuVdjkV5ZdX/3YtmX0QulG+x0taQOtJdHYzVU61aSSkAgVJ7NOv6qPkIYiJSgSWWN/DM5sGw==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.18.6", + "@rollup/pluginutils": "^5.0.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "@types/babel__core": "^7.1.9", + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "@types/babel__core": { + "optional": true + }, + "rollup": { + "optional": true + } + } + }, "node_modules/@rollup/plugin-commonjs": { "version": "28.0.0", "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.0.tgz", @@ -9790,6 +9814,28 @@ "@jridgewell/sourcemap-codec": "^1.5.0" } }, + "node_modules/@rollup/plugin-terser": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", + "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==", + "dev": true, + "dependencies": { + "serialize-javascript": "^6.0.1", + "smob": "^1.0.0", + "terser": "^5.17.4" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, "node_modules/@rollup/plugin-typescript": { "version": "12.1.0", "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-12.1.0.tgz", @@ -15967,83 +16013,6 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, - "node_modules/cross-env": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "bin": { - "cross-env": "src/bin/cross-env.js", - "cross-env-shell": "src/bin/cross-env-shell.js" - }, - "engines": { - "node": ">=10.14", - "npm": ">=6", - "yarn": ">=1" - } - }, - "node_modules/cross-env/node_modules/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, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cross-env/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/cross-env/node_modules/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, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cross-env/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/cross-env/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -19013,19 +18982,6 @@ "node": ">=10" } }, - "node_modules/fill-keys": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", - "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", - "dev": true, - "dependencies": { - "is-object": "~1.0.1", - "merge-descriptors": "~1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -21620,12 +21576,6 @@ "node": ">=8" } }, - "node_modules/is-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", - "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", - "dev": true - }, "node_modules/is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -30509,12 +30459,6 @@ "resolve": "^1.17.0" } }, - "node_modules/module-not-found-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", - "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", - "dev": true - }, "node_modules/mold-source-map": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/mold-source-map/-/mold-source-map-0.4.0.tgz", @@ -32656,8 +32600,6 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, - "optional": true, - "peer": true, "engines": { "node": ">=12" }, @@ -33171,17 +33113,6 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, - "node_modules/proxyquire": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-2.1.3.tgz", - "integrity": "sha512-BQWfCqYM+QINd+yawJz23tbBM40VIGXOdDw3X344KcclI/gtBbdWF6SlQ4nK/bYhF9d27KYug9WzljHC6B9Ysg==", - "dev": true, - "dependencies": { - "fill-keys": "^1.0.2", - "module-not-found-error": "^1.0.1", - "resolve": "^1.11.1" - } - }, "node_modules/prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", @@ -35001,6 +34932,12 @@ "npm": ">= 3.0.0" } }, + "node_modules/smob": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz", + "integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==", + "dev": true + }, "node_modules/snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -38952,9 +38889,110 @@ "@bugsnag/plugin-simple-throttle": "^8.1.1", "@bugsnag/plugin-strip-query-string": "^8.1.1", "@bugsnag/plugin-window-onerror": "^8.1.1", - "@bugsnag/plugin-window-unhandled-rejection": "^8.1.1" + "@bugsnag/plugin-window-unhandled-rejection": "^8.1.1", + "@rollup/plugin-babel": "^6.0.4", + "@rollup/plugin-commonjs": "^28.0.2", + "@rollup/plugin-node-resolve": "^16.0.0", + "@rollup/plugin-replace": "^6.0.2", + "@rollup/plugin-terser": "^0.4.4", + "tslib": "^2.8.1" } }, + "packages/browser/node_modules/@rollup/plugin-commonjs": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.2.tgz", + "integrity": "sha512-BEFI2EDqzl+vA1rl97IDRZ61AIwGH093d9nz8+dThxJNH8oSoB7MjWvPCX3dkaK1/RCJ/1v/R1XB15FuSs0fQw==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "commondir": "^1.0.1", + "estree-walker": "^2.0.2", + "fdir": "^6.2.0", + "is-reference": "1.2.1", + "magic-string": "^0.30.3", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=16.0.0 || 14 >= 14.17" + }, + "peerDependencies": { + "rollup": "^2.68.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "packages/browser/node_modules/@rollup/plugin-node-resolve": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.0.tgz", + "integrity": "sha512-0FPvAeVUT/zdWoO0jnb/V5BlBsUSNfkIOtFHzMO4H9MOklrmQFY6FduVHKucNb/aTFxvnGhj4MNj/T1oNdDfNg==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "packages/browser/node_modules/@rollup/plugin-replace": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-6.0.2.tgz", + "integrity": "sha512-7QaYCf8bqF04dOy7w/eHmJeNExxTYwvKAmlSAH/EaWWUzbT0h5sbF6bktFoX/0F/0qwng5/dWFMyf3gzaM8DsQ==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "magic-string": "^0.30.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "packages/browser/node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/browser/node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "packages/browser/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true + }, "packages/core": { "name": "@bugsnag/core", "version": "8.1.1", @@ -42885,7 +42923,74 @@ "@bugsnag/plugin-simple-throttle": "^8.1.1", "@bugsnag/plugin-strip-query-string": "^8.1.1", "@bugsnag/plugin-window-onerror": "^8.1.1", - "@bugsnag/plugin-window-unhandled-rejection": "^8.1.1" + "@bugsnag/plugin-window-unhandled-rejection": "^8.1.1", + "@rollup/plugin-babel": "^6.0.4", + "@rollup/plugin-commonjs": "^28.0.2", + "@rollup/plugin-node-resolve": "^16.0.0", + "@rollup/plugin-replace": "^6.0.2", + "@rollup/plugin-terser": "^0.4.4", + "tslib": "^2.8.1" + }, + "dependencies": { + "@rollup/plugin-commonjs": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.2.tgz", + "integrity": "sha512-BEFI2EDqzl+vA1rl97IDRZ61AIwGH093d9nz8+dThxJNH8oSoB7MjWvPCX3dkaK1/RCJ/1v/R1XB15FuSs0fQw==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^5.0.1", + "commondir": "^1.0.1", + "estree-walker": "^2.0.2", + "fdir": "^6.2.0", + "is-reference": "1.2.1", + "magic-string": "^0.30.3", + "picomatch": "^4.0.2" + } + }, + "@rollup/plugin-node-resolve": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.0.tgz", + "integrity": "sha512-0FPvAeVUT/zdWoO0jnb/V5BlBsUSNfkIOtFHzMO4H9MOklrmQFY6FduVHKucNb/aTFxvnGhj4MNj/T1oNdDfNg==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + } + }, + "@rollup/plugin-replace": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-6.0.2.tgz", + "integrity": "sha512-7QaYCf8bqF04dOy7w/eHmJeNExxTYwvKAmlSAH/EaWWUzbT0h5sbF6bktFoX/0F/0qwng5/dWFMyf3gzaM8DsQ==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^5.0.1", + "magic-string": "^0.30.3" + } + }, + "deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true + }, + "magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "requires": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true + } } }, "@bugsnag/core": { @@ -48859,6 +48964,16 @@ "nanoid": "^3.1.15" } }, + "@rollup/plugin-babel": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-6.0.4.tgz", + "integrity": "sha512-YF7Y52kFdFT/xVSuVdjkV5ZdX/3YtmX0QulG+x0taQOtJdHYzVU61aSSkAgVJ7NOv6qPkIYiJSgSWWN/DM5sGw==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.18.6", + "@rollup/pluginutils": "^5.0.1" + } + }, "@rollup/plugin-commonjs": { "version": "28.0.0", "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.0.tgz", @@ -48933,6 +49048,17 @@ } } }, + "@rollup/plugin-terser": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", + "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==", + "dev": true, + "requires": { + "serialize-javascript": "^6.0.1", + "smob": "^1.0.0", + "terser": "^5.17.4" + } + }, "@rollup/plugin-typescript": { "version": "12.1.0", "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-12.1.0.tgz", @@ -53973,58 +54099,6 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, - "cross-env": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.1" - }, - "dependencies": { - "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" - } - }, - "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 - }, - "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 - }, - "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" - } - } - } - }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -56407,16 +56481,6 @@ } } }, - "fill-keys": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", - "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", - "dev": true, - "requires": { - "is-object": "~1.0.1", - "merge-descriptors": "~1.0.0" - } - }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -58352,12 +58416,6 @@ "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "dev": true }, - "is-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", - "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", - "dev": true - }, "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -65284,12 +65342,6 @@ } } }, - "module-not-found-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", - "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", - "dev": true - }, "mold-source-map": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/mold-source-map/-/mold-source-map-0.4.0.tgz", @@ -66915,9 +66967,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "dev": true, - "optional": true, - "peer": true + "dev": true }, "pify": { "version": "5.0.0", @@ -67307,17 +67357,6 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, - "proxyquire": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-2.1.3.tgz", - "integrity": "sha512-BQWfCqYM+QINd+yawJz23tbBM40VIGXOdDw3X344KcclI/gtBbdWF6SlQ4nK/bYhF9d27KYug9WzljHC6B9Ysg==", - "dev": true, - "requires": { - "fill-keys": "^1.0.2", - "module-not-found-error": "^1.0.1", - "resolve": "^1.11.1" - } - }, "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", @@ -68788,6 +68827,12 @@ "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "dev": true }, + "smob": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz", + "integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==", + "dev": true + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", diff --git a/package.json b/package.json index 36818f99c5..ef4ad17a17 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,6 @@ "browserify": "^17.0.1", "browserify-versionify": "^1.0.6", "coverage-diff": "^1.6.0", - "cross-env": "^7.0.3", "electron": "*", "envify": "^4.1.0", "eslint": "^6.8.0", @@ -66,7 +65,6 @@ "ncp": "^2.0.0", "node-fetch": "^2.6.0", "playwright": "^1.10.0", - "proxyquire": "^2.1.3", "ps-list": "^7.2.0", "react": "^16.13.1", "react-native": "^0.63.4", diff --git a/packages/browser/babel.config.js b/packages/browser/babel.config.js new file mode 100644 index 0000000000..235ee4504b --- /dev/null +++ b/packages/browser/babel.config.js @@ -0,0 +1,3 @@ +const babelConfig = require('../../babel.config.js') + +module.exports = babelConfig diff --git a/packages/browser/package.json b/packages/browser/package.json index 5e81bc2618..e360c98d9b 100644 --- a/packages/browser/package.json +++ b/packages/browser/package.json @@ -1,17 +1,22 @@ { "name": "@bugsnag/browser", "version": "8.1.2", - "main": "dist/bugsnag.js", - "types": "types/bugsnag.d.ts", + "main": "dist/index-cjs.cjs", + "types": "dist/types/index-es.d.ts", + "browser": "./dist/bugsnag.js", + "exports": { + ".": { + "types": "./dist/types/index-es.d.ts", + "import": "./dist/index-es.mjs", + "default": "./dist/index-cjs.cjs" + } + }, "description": "Bugsnag error reporter for browser JavaScript", "homepage": "https://www.bugsnag.com/", "repository": { "type": "git", "url": "git@github.com:bugsnag/bugsnag-js.git" }, - "browser": { - "types/bugsnag": "./dist/bugsnag.js" - }, "publishConfig": { "access": "public" }, @@ -22,9 +27,8 @@ "scripts": { "size": "../../bin/size dist/bugsnag.min.js", "clean": "rm -fr dist && mkdir dist", - "build": "npm run clean && npm run build:dist && npm run build:dist:min", - "build:dist": "cross-env NODE_ENV=production bash -c '../../bin/bundle src/notifier.js --standalone=Bugsnag | ../../bin/extract-source-map dist/bugsnag.js'", - "build:dist:min": "cross-env NODE_ENV=production bash -c '../../bin/bundle src/notifier.js --standalone=Bugsnag | ../../bin/minify dist/bugsnag.min.js'", + "build": "npm run clean && npm run build:npm", + "build:npm": "rollup --config rollup.config.npm.mjs", "cdn-upload": "../../bin/cdn-upload dist/*" }, "author": "Bugsnag", @@ -46,7 +50,13 @@ "@bugsnag/plugin-simple-throttle": "^8.1.1", "@bugsnag/plugin-strip-query-string": "^8.1.1", "@bugsnag/plugin-window-onerror": "^8.1.1", - "@bugsnag/plugin-window-unhandled-rejection": "^8.1.1" + "@bugsnag/plugin-window-unhandled-rejection": "^8.1.1", + "@rollup/plugin-babel": "^6.0.4", + "@rollup/plugin-commonjs": "^28.0.2", + "@rollup/plugin-node-resolve": "^16.0.0", + "@rollup/plugin-replace": "^6.0.2", + "@rollup/plugin-terser": "^0.4.4", + "tslib": "^2.8.1" }, "dependencies": { "@bugsnag/core": "^8.1.1" diff --git a/packages/browser/rollup.config.npm.mjs b/packages/browser/rollup.config.npm.mjs new file mode 100644 index 0000000000..9fbe5fd263 --- /dev/null +++ b/packages/browser/rollup.config.npm.mjs @@ -0,0 +1,85 @@ +import babel from '@rollup/plugin-babel'; +import commonjs from '@rollup/plugin-commonjs' +import nodeResolve from '@rollup/plugin-node-resolve' +import replace from '@rollup/plugin-replace' +import terser from '@rollup/plugin-terser' +import typescript from '@rollup/plugin-typescript' +import fs from 'fs' + +import createRollupConfig, { sharedOutput as commonSharedOutput } from "../../.rollup/index.mjs" + +const packageJson = JSON.parse(fs.readFileSync('./package.json')) + +const sharedOutput = { + ...commonSharedOutput, + strict: false, // 'use strict' in WebKit enables Tail Call Optimization, which breaks stack trace handling +} + +const plugins = [ + nodeResolve({ + browser: true + }), + commonjs(), + typescript({ + removeComments: true, + // don't output anything if there's a TS error + noEmitOnError: true, + compilerOptions: { + target: 'es3', + } + }), + babel({ babelHelpers: 'bundled' }), + replace({ + preventAssignment: true, + values: { + 'process.env.NODE_ENV': JSON.stringify('production'), + values: { __VERSION__: packageJson.version }, + }, + }), +] + +export default [ + createRollupConfig({ + input: "src/index-es.ts", + output: [ + { + ...sharedOutput, + preserveModules: false, + entryFileNames: '[name].mjs', + format: 'esm' + } + ], + plugins + }), + createRollupConfig({ + input: "src/index-cjs.ts", + output: [ + { + ...sharedOutput, + entryFileNames: '[name].cjs', + format: 'cjs', + }, + ], + plugins + }), + createRollupConfig({ + input: "src/index-umd.ts", + output: [ + { + ...sharedOutput, + entryFileNames: 'bugsnag.js', + format: 'umd', + name: 'Bugsnag' + }, + { + ...sharedOutput, + entryFileNames: 'bugsnag.min.js', + format: 'umd', + compact: true, + name: 'Bugsnag', + plugins: [terser()], + }, + ], + plugins + }) +]; diff --git a/packages/browser/src/bugsnag.ts b/packages/browser/src/bugsnag.ts new file mode 100644 index 0000000000..d305d4036a --- /dev/null +++ b/packages/browser/src/bugsnag.ts @@ -0,0 +1,133 @@ +import ClientWithInternals from '@bugsnag/core/client' +import type { BugsnagStatic, Config } from '@bugsnag/core' + +import map from '@bugsnag/core/lib/es-utils/map' +import keys from '@bugsnag/core/lib/es-utils/keys' +import assign from '@bugsnag/core/lib/es-utils/assign' + +// extend the base config schema with some browser-specific options +import { schema as baseConfig } from '@bugsnag/core/config' +import browserConfig from './config' + +import pluginWindowOnerror from '@bugsnag/plugin-window-onerror' +import pluginUnhandledRejection from '@bugsnag/plugin-window-unhandled-rejection' +import pluginApp from '@bugsnag/plugin-app-duration' +import pluginDevice from '@bugsnag/plugin-browser-device' +import pluginContext from '@bugsnag/plugin-browser-context' +import pluginRequest from '@bugsnag/plugin-browser-request' +import pluginThrottle from '@bugsnag/plugin-simple-throttle' +import pluginConsoleBreadcrumbs from '@bugsnag/plugin-console-breadcrumbs' +import pluginNetworkBreadcrumbs from '@bugsnag/plugin-network-breadcrumbs' +import pluginNavigationBreadcrumbs from '@bugsnag/plugin-navigation-breadcrumbs' +import pluginInteractionBreadcrumbs from '@bugsnag/plugin-interaction-breadcrumbs' +// @ts-ignore +import pluginInlineScriptContent from '@bugsnag/plugin-inline-script-content' +import pluginSession from '@bugsnag/plugin-browser-session' +import pluginIp from '@bugsnag/plugin-client-ip' +import pluginStripQueryString from '@bugsnag/plugin-strip-query-string' + +// delivery mechanisms +import dXDomainRequest from '@bugsnag/delivery-x-domain-request' +import dXMLHttpRequest from '@bugsnag/delivery-xml-http-request' + +const name = 'Bugsnag JavaScript' +const version = '__VERSION__' +const url = 'https://github.com/bugsnag/bugsnag-js' + +const schema = assign({}, baseConfig, browserConfig) + +export interface BrowserConfig extends Config { + maxEvents?: number + collectUserIp?: boolean + generateAnonymousId?: boolean + trackInlineScripts?: boolean +} + +export interface BrowserBugsnagStatic extends BugsnagStatic { + start(apiKeyOrOpts: string | BrowserConfig): ClientWithInternals + createClient(apiKeyOrOpts: string | BrowserConfig): ClientWithInternals +} + +declare global { + interface Window { + XDomainRequest: unknown + } +} + +type BrowserClient = Partial & { + _client: ClientWithInternals | null + createClient: (opts?: Config) => ClientWithInternals + start: (opts?: Config) => ClientWithInternals + isStarted: () => boolean +} + +const notifier: BrowserClient = { + _client: null, + createClient: (opts) => { + // handle very simple use case where user supplies just the api key as a string + if (typeof opts === 'string') opts = { apiKey: opts } + if (!opts) opts = {} as unknown as Config + + const internalPlugins = [ + // add browser-specific plugins + pluginApp, + pluginDevice(), + pluginContext(), + pluginRequest(), + pluginThrottle, + pluginSession, + pluginIp, + pluginStripQueryString, + pluginWindowOnerror(), + pluginUnhandledRejection(), + pluginNavigationBreadcrumbs(), + pluginInteractionBreadcrumbs(), + pluginNetworkBreadcrumbs(), + pluginConsoleBreadcrumbs, + + // this one added last to avoid wrapping functionality before bugsnag uses it + pluginInlineScriptContent() + ] + + // configure a client with user supplied options + const bugsnag = new ClientWithInternals(opts, schema, internalPlugins, { name, version, url }); + + // set delivery based on browser capability (IE 8+9 have an XDomainRequest object) + (bugsnag as BrowserClient)._setDelivery?.(window.XDomainRequest ? dXDomainRequest : dXMLHttpRequest) + + bugsnag._logger.debug('Loaded!') + bugsnag.leaveBreadcrumb('Bugsnag loaded', {}, 'state') + + return bugsnag._config.autoTrackSessions + ? bugsnag.startSession() + : bugsnag + }, + start: (opts) => { + if (notifier._client) { + notifier._client._logger.warn('Bugsnag.start() was called more than once. Ignoring.') + return notifier._client + } + notifier._client = notifier.createClient(opts) + return notifier._client + }, + isStarted: () => { + return notifier._client != null + } +} + +type Method = keyof typeof ClientWithInternals.prototype + +map(['resetEventCount'].concat(keys(ClientWithInternals.prototype)) as Method[], (m) => { + if (/^_/.test(m)) return + notifier[m] = function () { + if (!notifier._client) return console.log(`Bugsnag.${m}() was called before Bugsnag.start()`) + notifier._client._depth += 1 + const ret = notifier._client[m].apply(notifier._client, arguments) + notifier._client._depth -= 1 + return ret + } +}) + +const Bugsnag = notifier as BrowserBugsnagStatic + +export default Bugsnag diff --git a/packages/browser/src/config.js b/packages/browser/src/config.js deleted file mode 100644 index 12a003b5f1..0000000000 --- a/packages/browser/src/config.js +++ /dev/null @@ -1,35 +0,0 @@ -const { schema } = require('@bugsnag/core/config') -const map = require('@bugsnag/core/lib/es-utils/map') -const assign = require('@bugsnag/core/lib/es-utils/assign') - -module.exports = { - releaseStage: assign({}, schema.releaseStage, { - defaultValue: () => { - if (/^localhost(:\d+)?$/.test(window.location.host)) return 'development' - return 'production' - } - }), - appType: { - ...schema.appType, - defaultValue: () => 'browser' - }, - logger: assign({}, schema.logger, { - defaultValue: () => - // set logger based on browser capability - (typeof console !== 'undefined' && typeof console.debug === 'function') - ? getPrefixedConsole() - : undefined - }) -} - -const getPrefixedConsole = () => { - const logger = {} - const consoleLog = console.log - map(['debug', 'info', 'warn', 'error'], (method) => { - const consoleMethod = console[method] - logger[method] = typeof consoleMethod === 'function' - ? consoleMethod.bind(console, '[bugsnag]') - : consoleLog.bind(console, '[bugsnag]') - }) - return logger -} diff --git a/packages/browser/src/config.ts b/packages/browser/src/config.ts new file mode 100644 index 0000000000..fd9c49a335 --- /dev/null +++ b/packages/browser/src/config.ts @@ -0,0 +1,24 @@ +import { schema } from '@bugsnag/core/config' +import assign from '@bugsnag/core/lib/es-utils/assign' +import getPrefixedConsole from './get-prefixed-console' + +const config = { + releaseStage: assign({}, schema.releaseStage, { + defaultValue: () => { + if (/^localhost(:\d+)?$/.test(window.location.host)) return 'development' + return 'production' + } + }), + appType: assign({}, schema.appType, { + defaultValue: () => 'browser' + }), + logger: assign({}, schema.logger, { + defaultValue: () => + // set logger based on browser capability + (typeof console !== 'undefined' && typeof console.debug === 'function') + ? getPrefixedConsole() + : undefined + }) +} + +export default config diff --git a/packages/browser/src/get-prefixed-console.ts b/packages/browser/src/get-prefixed-console.ts new file mode 100644 index 0000000000..2fcb2bc1b0 --- /dev/null +++ b/packages/browser/src/get-prefixed-console.ts @@ -0,0 +1,17 @@ +import map from '@bugsnag/core/lib/es-utils/map' + +type LoggerMethod = 'debug' | 'info' | 'warn' | 'error' + +const getPrefixedConsole = () => { + const logger: Record = {} + const consoleLog = console.log + map(['debug', 'info', 'warn', 'error'], (method: LoggerMethod) => { + const consoleMethod = console[method] + logger[method] = typeof consoleMethod === 'function' + ? consoleMethod.bind(console, '[bugsnag]') + : consoleLog.bind(console, '[bugsnag]') + }) + return logger +} + +export default getPrefixedConsole diff --git a/packages/browser/src/index-cjs.ts b/packages/browser/src/index-cjs.ts new file mode 100644 index 0000000000..759963c6c1 --- /dev/null +++ b/packages/browser/src/index-cjs.ts @@ -0,0 +1,10 @@ +import Client from '@bugsnag/core/client' +import Event from '@bugsnag/core/event' +import Session from '@bugsnag/core/session' +import Breadcrumb from '@bugsnag/core/breadcrumb' + +import assign from '@bugsnag/core/lib/es-utils/assign' + +import Bugsnag from './bugsnag' + +export default assign(Bugsnag, { Breadcrumb, Client, Event, Session }) diff --git a/packages/browser/src/index-es.ts b/packages/browser/src/index-es.ts new file mode 100644 index 0000000000..7f043e3442 --- /dev/null +++ b/packages/browser/src/index-es.ts @@ -0,0 +1,4 @@ +export { default } from './bugsnag' +export type { BrowserBugsnagStatic, BrowserConfig } from './bugsnag' + +export * from '@bugsnag/core' diff --git a/packages/browser/src/index-umd.ts b/packages/browser/src/index-umd.ts new file mode 100644 index 0000000000..759963c6c1 --- /dev/null +++ b/packages/browser/src/index-umd.ts @@ -0,0 +1,10 @@ +import Client from '@bugsnag/core/client' +import Event from '@bugsnag/core/event' +import Session from '@bugsnag/core/session' +import Breadcrumb from '@bugsnag/core/breadcrumb' + +import assign from '@bugsnag/core/lib/es-utils/assign' + +import Bugsnag from './bugsnag' + +export default assign(Bugsnag, { Breadcrumb, Client, Event, Session }) diff --git a/packages/browser/src/notifier.d.ts b/packages/browser/src/notifier.d.ts deleted file mode 100644 index 844bfb518c..0000000000 --- a/packages/browser/src/notifier.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from '../types/bugsnag' -export * from '../types/bugsnag' diff --git a/packages/browser/src/notifier.js b/packages/browser/src/notifier.js deleted file mode 100644 index dcb9fb1eda..0000000000 --- a/packages/browser/src/notifier.js +++ /dev/null @@ -1,110 +0,0 @@ -const name = 'Bugsnag JavaScript' -const version = '__VERSION__' -const url = 'https://github.com/bugsnag/bugsnag-js' - -const Client = require('@bugsnag/core/client') -const Event = require('@bugsnag/core/event') -const Session = require('@bugsnag/core/session') -const Breadcrumb = require('@bugsnag/core/breadcrumb') - -const map = require('@bugsnag/core/lib/es-utils/map') -const keys = require('@bugsnag/core/lib/es-utils/keys') -const assign = require('@bugsnag/core/lib/es-utils/assign') - -// extend the base config schema with some browser-specific options -const schema = assign({}, require('@bugsnag/core/config').schema, require('./config')) - -const pluginWindowOnerror = require('@bugsnag/plugin-window-onerror') -const pluginUnhandledRejection = require('@bugsnag/plugin-window-unhandled-rejection') -const pluginApp = require('@bugsnag/plugin-app-duration') -const pluginDevice = require('@bugsnag/plugin-browser-device') -const pluginContext = require('@bugsnag/plugin-browser-context') -const pluginRequest = require('@bugsnag/plugin-browser-request') -const pluginThrottle = require('@bugsnag/plugin-simple-throttle') -const pluginConsoleBreadcrumbs = require('@bugsnag/plugin-console-breadcrumbs') -const pluginNetworkBreadcrumbs = require('@bugsnag/plugin-network-breadcrumbs') -const pluginNavigationBreadcrumbs = require('@bugsnag/plugin-navigation-breadcrumbs') -const pluginInteractionBreadcrumbs = require('@bugsnag/plugin-interaction-breadcrumbs') -const pluginInlineScriptContent = require('@bugsnag/plugin-inline-script-content') -const pluginSession = require('@bugsnag/plugin-browser-session') -const pluginIp = require('@bugsnag/plugin-client-ip') -const pluginStripQueryString = require('@bugsnag/plugin-strip-query-string') - -// delivery mechanisms -const dXDomainRequest = require('@bugsnag/delivery-x-domain-request') -const dXMLHttpRequest = require('@bugsnag/delivery-xml-http-request') - -const Bugsnag = { - _client: null, - createClient: (opts) => { - // handle very simple use case where user supplies just the api key as a string - if (typeof opts === 'string') opts = { apiKey: opts } - if (!opts) opts = {} - - const internalPlugins = [ - // add browser-specific plugins - pluginApp, - pluginDevice(), - pluginContext(), - pluginRequest(), - pluginThrottle, - pluginSession, - pluginIp, - pluginStripQueryString, - pluginWindowOnerror(), - pluginUnhandledRejection(), - pluginNavigationBreadcrumbs(), - pluginInteractionBreadcrumbs(), - pluginNetworkBreadcrumbs(), - pluginConsoleBreadcrumbs, - - // this one added last to avoid wrapping functionality before bugsnag uses it - pluginInlineScriptContent() - ] - - // configure a client with user supplied options - const bugsnag = new Client(opts, schema, internalPlugins, { name, version, url }) - - // set delivery based on browser capability (IE 8+9 have an XDomainRequest object) - bugsnag._setDelivery(window.XDomainRequest ? dXDomainRequest : dXMLHttpRequest) - - bugsnag._logger.debug('Loaded!') - bugsnag.leaveBreadcrumb('Bugsnag loaded', {}, 'state') - - return bugsnag._config.autoTrackSessions - ? bugsnag.startSession() - : bugsnag - }, - start: (opts) => { - if (Bugsnag._client) { - Bugsnag._client._logger.warn('Bugsnag.start() was called more than once. Ignoring.') - return Bugsnag._client - } - Bugsnag._client = Bugsnag.createClient(opts) - return Bugsnag._client - }, - isStarted: () => { - return Bugsnag._client != null - } -} - -map(['resetEventCount'].concat(keys(Client.prototype)), (m) => { - if (/^_/.test(m)) return - Bugsnag[m] = function () { - if (!Bugsnag._client) return console.log(`Bugsnag.${m}() was called before Bugsnag.start()`) - Bugsnag._client._depth += 1 - const ret = Bugsnag._client[m].apply(Bugsnag._client, arguments) - Bugsnag._client._depth -= 1 - return ret - } -}) - -module.exports = Bugsnag - -module.exports.Client = Client -module.exports.Event = Event -module.exports.Session = Session -module.exports.Breadcrumb = Breadcrumb - -// Export a "default" property for compatibility with ESM imports -module.exports.default = Bugsnag diff --git a/packages/browser/test/index.test.ts b/packages/browser/test/index.test.ts index 7e39b8cb13..23396e07e0 100644 --- a/packages/browser/test/index.test.ts +++ b/packages/browser/test/index.test.ts @@ -1,4 +1,4 @@ -import BugsnagBrowserStatic, { Breadcrumb, BrowserConfig, Session } from '../src/notifier' +import BugsnagBrowserStatic, { Breadcrumb, BrowserConfig, Session } from '../' const DONE = window.XMLHttpRequest.DONE @@ -39,7 +39,7 @@ describe('browser notifier', () => { }) function getBugsnag (): typeof BugsnagBrowserStatic { - const Bugsnag = require('../src/notifier') as typeof BugsnagBrowserStatic + const Bugsnag = require('../src/bugsnag').default return Bugsnag } @@ -138,7 +138,7 @@ describe('browser notifier', () => { it('accepts all config options', (done) => { const Bugsnag = getBugsnag() - const completeConfig: Required = { + const completeConfig: BrowserConfig = { apiKey: API_KEY, appVersion: '1.2.3', appType: 'worker', @@ -148,7 +148,7 @@ describe('browser notifier', () => { unhandledRejections: true }, onError: [ - event => true + () => true ], onBreadcrumb: (b: Breadcrumb) => { return false diff --git a/packages/browser/tsconfig.json b/packages/browser/tsconfig.json new file mode 100644 index 0000000000..a5cb75c562 --- /dev/null +++ b/packages/browser/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "include": ["src/**/*.ts"] +} diff --git a/packages/browser/types/bugsnag.d.ts b/packages/browser/types/bugsnag.d.ts deleted file mode 100644 index d198264fb7..0000000000 --- a/packages/browser/types/bugsnag.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Client, Config, BugsnagStatic } from '@bugsnag/core' - -interface BrowserConfig extends Config { - maxEvents?: number - collectUserIp?: boolean - generateAnonymousId?: boolean - trackInlineScripts?: boolean -} - -export interface BrowserBugsnagStatic extends BugsnagStatic { - start(apiKeyOrOpts: string | BrowserConfig): Client - createClient(apiKeyOrOpts: string | BrowserConfig): Client -} - -declare const Bugsnag: BrowserBugsnagStatic - -export default Bugsnag -export * from '@bugsnag/core' -export { BrowserConfig } diff --git a/packages/browser/types/global.d.ts b/packages/browser/types/global.d.ts deleted file mode 100644 index 713330a3f0..0000000000 --- a/packages/browser/types/global.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -import bugsnag from './bugsnag' - -export as namespace bugsnag; -export = bugsnag; diff --git a/packages/core/client.js b/packages/core/client.js index 5e8a6988e5..4de54e2b49 100644 --- a/packages/core/client.js +++ b/packages/core/client.js @@ -67,7 +67,7 @@ class Client { }) // when notify() is called we need to know how many frames are from our own source - // this inital value is 1 not 0 because we wrap notify() to ensure it is always + // this initial value is 1 not 0 because we wrap notify() to ensure it is always // bound to have the client as its `this` value – see below. this._depth = 1 diff --git a/packages/core/config.d.ts b/packages/core/config.d.ts new file mode 100644 index 0000000000..cee871526c --- /dev/null +++ b/packages/core/config.d.ts @@ -0,0 +1,115 @@ +export interface Schema { + apiKey: { + defaultValue: () => null + message: string + validate: (value: unknown) => boolean + } + appVersion: { + defaultValue: () => undefined + message: string + validate: (value: unknown) => boolean + } + appType: { + defaultValue: () => undefined + message: string + validate: (value: unknown) => boolean + } + autoDetectErrors: { + defaultValue: () => true + message: string + validate: (value: unknown) => boolean + } + enabledErrorTypes: { + defaultValue: () => { unhandledExceptions: boolean, unhandledRejections: boolean } + message: string + allowPartialObject: boolean + validate: (value: unknown) => boolean + } + onError: { + defaultValue: () => [] + message: string + validate: (value: unknown) => boolean + } + onSession: { + defaultValue: () => [] + message: string + validate: (value: unknown) => boolean + } + onBreadcrumb: { + defaultValue: () => [] + message: string + validate: (value: unknown) => boolean + } + endpoints: { + defaultValue: (endpoints: { notify: string, sessions: string } | undefined) => { notify: string | null, sessions: string | null } + message: string + validate: (value: unknown) => boolean + } + autoTrackSessions: { + defaultValue: () => boolean + message: string + validate: (value: unknown) => boolean + } + enabledReleaseStages: { + defaultValue: () => null + message: string + validate: (value: unknown) => boolean + } + releaseStage: { + defaultValue: () => 'production' + message: string + validate: (value: unknown) => boolean + } + maxBreadcrumbs: { + defaultValue: () => 25 + message: string + validate: (value: unknown) => boolean + } + enabledBreadcrumbTypes: { + defaultValue: () => ['navigation', 'request', 'process', 'log', 'user', 'state', 'error', 'manual'] + message: string + validate: (value: unknown) => boolean + } + context: { + defaultValue: () => undefined + message: string + validate: (value: unknown) => boolean + } + user: { + defaultValue: () => {} + message: string + validate: (value: unknown) => boolean + } + metadata: { + defaultValue: () => {} + message: string + validate: (value: unknown) => boolean + } + logger: { + defaultValue: () => undefined + message: string + validate: (value: unknown) => boolean + } + redactedKeys: { + defaultValue: () => ['password'] + message: string + validate: (value: unknown) => boolean + } + plugins: { + defaultValue: () => [] + message: string + validate: (value: unknown) => boolean + } + featureFlags: { + defaultValue: () => [] + message: string + validate: (value: unknown) => boolean + } + reportUnhandledPromiseRejectionsAsHandled: { + defaultValue: () => false + message: string + validate: (value: unknown) => boolean + } +} + +export const schema: Schema diff --git a/packages/plugin-interaction-breadcrumbs/package.json b/packages/plugin-interaction-breadcrumbs/package.json index 3d11035d01..1549f67872 100644 --- a/packages/plugin-interaction-breadcrumbs/package.json +++ b/packages/plugin-interaction-breadcrumbs/package.json @@ -1,7 +1,15 @@ { "name": "@bugsnag/plugin-interaction-breadcrumbs", "version": "8.1.1", - "main": "interaction-breadcrumbs.js", + "main": "dist/interaction-breadcrumbs.js", + "types": "dist/types/interaction-breadcrumbs.d.ts", + "exports": { + ".": { + "types": "./dist/types/interaction-breadcrumbs.d.ts", + "default": "./dist/interaction-breadcrumbs.js", + "import": "./dist/interaction-breadcrumbs.mjs" + } + }, "description": "@bugsnag/js plugin to record UI click events as breadcrumbs", "homepage": "https://www.bugsnag.com/", "repository": { @@ -14,7 +22,11 @@ "files": [ "*.js" ], - "scripts": {}, + "scripts": { + "build": "npm run build:npm", + "build:npm": "rollup --config rollup.config.npm.mjs", + "clean": "rm -rf dist/*" + }, "author": "Bugsnag", "license": "MIT", "devDependencies": { diff --git a/packages/plugin-interaction-breadcrumbs/rollup.config.npm.mjs b/packages/plugin-interaction-breadcrumbs/rollup.config.npm.mjs new file mode 100644 index 0000000000..5683a04647 --- /dev/null +++ b/packages/plugin-interaction-breadcrumbs/rollup.config.npm.mjs @@ -0,0 +1,5 @@ +import createRollupConfig from '../../.rollup/index.mjs' + +export default createRollupConfig({ + input: 'src/interaction-breadcrumbs.ts' +}) diff --git a/packages/plugin-interaction-breadcrumbs/interaction-breadcrumbs.js b/packages/plugin-interaction-breadcrumbs/src/interaction-breadcrumbs.ts similarity index 78% rename from packages/plugin-interaction-breadcrumbs/interaction-breadcrumbs.js rename to packages/plugin-interaction-breadcrumbs/src/interaction-breadcrumbs.ts index 86c7b03086..d910565175 100644 --- a/packages/plugin-interaction-breadcrumbs/interaction-breadcrumbs.js +++ b/packages/plugin-interaction-breadcrumbs/src/interaction-breadcrumbs.ts @@ -1,10 +1,13 @@ +import { Plugin } from '@bugsnag/core' +import type ClientWithInternals from 'packages/core/client' + /* * Leaves breadcrumbs when the user interacts with the DOM */ -module.exports = (win = window) => ({ +export default (win = window): Plugin => ({ load: (client) => { if (!('addEventListener' in win)) return - if (!client._isBreadcrumbTypeEnabled('user')) return + if (!(client as ClientWithInternals)._isBreadcrumbTypeEnabled('user')) return win.addEventListener('click', (event) => { let targetText, targetSelector @@ -13,8 +16,8 @@ module.exports = (win = window) => ({ targetSelector = getNodeSelector(event.target, win) } catch (e) { targetText = '[hidden]' - targetSelector = '[hidden]' - client._logger.error('Cross domain error when tracking click event. See docs: https://tinyurl.com/yy3rn63z') + targetSelector = '[hidden]'; + (client as ClientWithInternals)._logger.error('Cross domain error when tracking click event. See docs: https://tinyurl.com/yy3rn63z') } client.leaveBreadcrumb('UI click', { targetText, targetSelector }, 'user') }, true) @@ -23,7 +26,8 @@ module.exports = (win = window) => ({ const trim = /^\s*([^\s][\s\S]{0,139}[^\s])?\s*/ -function getNodeText (el) { +// TODO: Fix Type +function getNodeText (el: any) { let text = el.textContent || el.innerText || '' if (!text && (el.type === 'submit' || el.type === 'button')) { @@ -40,7 +44,8 @@ function getNodeText (el) { } // Create a label from tagname, id and css class of the element -function getNodeSelector (el, win) { +// TODO: Fix Type +function getNodeSelector (el: any, win: Window): string { const parts = [el.tagName] if (el.id) parts.push('#' + el.id) if (el.className && el.className.length) parts.push(`.${el.className.split(' ').join('.')}`) diff --git a/packages/plugin-interaction-breadcrumbs/test/interaction-breadcrumbs.test.ts b/packages/plugin-interaction-breadcrumbs/test/interaction-breadcrumbs.test.ts index e2c198dec5..8ce1f00285 100644 --- a/packages/plugin-interaction-breadcrumbs/test/interaction-breadcrumbs.test.ts +++ b/packages/plugin-interaction-breadcrumbs/test/interaction-breadcrumbs.test.ts @@ -1,4 +1,4 @@ -import plugin from '../' +import plugin from '../src/interaction-breadcrumbs' import Client from '@bugsnag/core/client' import Breadcrumb from '@bugsnag/core/breadcrumb' diff --git a/packages/plugin-interaction-breadcrumbs/tsconfig.json b/packages/plugin-interaction-breadcrumbs/tsconfig.json new file mode 100644 index 0000000000..09758ceb4c --- /dev/null +++ b/packages/plugin-interaction-breadcrumbs/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "../../tsconfig.json", + "include": ["src/**/*.ts"] +} + \ No newline at end of file diff --git a/packages/plugin-navigation-breadcrumbs/package.json b/packages/plugin-navigation-breadcrumbs/package.json index 29d32cf7e9..2561c83511 100644 --- a/packages/plugin-navigation-breadcrumbs/package.json +++ b/packages/plugin-navigation-breadcrumbs/package.json @@ -1,7 +1,15 @@ { "name": "@bugsnag/plugin-navigation-breadcrumbs", "version": "8.1.1", - "main": "navigation-breadcrumbs.js", + "main": "dist/navigation-breadcrumbs.js", + "types": "dist/types/navigation-breadcrumbs.d.ts", + "exports": { + ".": { + "types": "./dist/types/navigation-breadcrumbs.d.ts", + "default": "./dist/navigation-breadcrumbs.js", + "import": "./dist/navigation-breadcrumbs.mjs" + } + }, "description": "@bugsnag/js plugin to record browser navigation as breadcrumbs", "homepage": "https://www.bugsnag.com/", "repository": { @@ -14,6 +22,11 @@ "files": [ "*.js" ], + "scripts": { + "build": "npm run build:npm", + "build:npm": "rollup --config rollup.config.npm.mjs", + "clean": "rm -rf dist/*" + }, "author": "Bugsnag", "license": "MIT", "devDependencies": { diff --git a/packages/plugin-navigation-breadcrumbs/rollup.config.npm.mjs b/packages/plugin-navigation-breadcrumbs/rollup.config.npm.mjs new file mode 100644 index 0000000000..e74dd35c57 --- /dev/null +++ b/packages/plugin-navigation-breadcrumbs/rollup.config.npm.mjs @@ -0,0 +1,5 @@ +import createRollupConfig from '../../.rollup/index.mjs' + +export default createRollupConfig({ + input: 'src/navigation-breadcrumbs.ts' +}) diff --git a/packages/plugin-navigation-breadcrumbs/navigation-breadcrumbs.js b/packages/plugin-navigation-breadcrumbs/src/navigation-breadcrumbs.ts similarity index 59% rename from packages/plugin-navigation-breadcrumbs/navigation-breadcrumbs.js rename to packages/plugin-navigation-breadcrumbs/src/navigation-breadcrumbs.ts index 873215dd83..10559b8053 100644 --- a/packages/plugin-navigation-breadcrumbs/navigation-breadcrumbs.js +++ b/packages/plugin-navigation-breadcrumbs/src/navigation-breadcrumbs.ts @@ -1,14 +1,29 @@ +import { Client, Plugin } from 'packages/core/types' + +interface PluginClient extends Client { + _isBreadcrumbTypeEnabled: (type: string) => boolean +} + +type ExtendedHistory = History & { + replaceState: History['replaceState'] & { _restore?: () => void } + pushState: History['pushState'] & { _restore?: () => void } +} + +type ExtendedWindow = Window & { + history: ExtendedHistory +} + /* * Leaves breadcrumbs when navigation methods are called or events are emitted */ -module.exports = (win = window) => { - const plugin = { +export default (win = window): Plugin => { + const plugin: Plugin = { load: (client) => { if (!('addEventListener' in win)) return - if (!client._isBreadcrumbTypeEnabled('navigation')) return + if (!(client as PluginClient)._isBreadcrumbTypeEnabled('navigation')) return // returns a function that will drop a breadcrumb with a given name - const drop = name => () => client.leaveBreadcrumb(name, {}, 'navigation') + const drop = (name: string) => () => client.leaveBreadcrumb(name, {}, 'navigation') // simple drops – just names, no meta win.addEventListener('pagehide', drop('Page hidden'), true) @@ -27,15 +42,15 @@ module.exports = (win = window) => { }, true) // the only way to know about replaceState/pushState is to wrap them… >_< - if (win.history.pushState) wrapHistoryFn(client, win.history, 'pushState', win, true) - if (win.history.replaceState) wrapHistoryFn(client, win.history, 'replaceState', win) + if (typeof win.history.pushState === 'function') wrapHistoryFn(client, win.history, 'pushState', win, true) + if (typeof win.history.replaceState === 'function') wrapHistoryFn(client, win.history, 'replaceState', win) } } if (process.env.NODE_ENV !== 'production') { - plugin.destroy = (win = window) => { - win.history.replaceState._restore() - win.history.pushState._restore() + plugin.destroy = (win: ExtendedWindow = window) => { + if (win.history.replaceState._restore) win.history.replaceState._restore() + if (win.history.pushState._restore) win.history.pushState._restore() } } @@ -43,26 +58,27 @@ module.exports = (win = window) => { } if (process.env.NODE_ENV !== 'production') { - exports.destroy = (win = window) => { - win.history.replaceState._restore() - win.history.pushState._restore() + exports.destroy = (win: ExtendedWindow = window) => { + if (win.history.replaceState._restore) win.history.replaceState._restore() + if (win.history.pushState._restore) win.history.pushState._restore() } } // takes a full url like http://foo.com:1234/pages/01.html?yes=no#section-2 and returns // just the path and hash parts, e.g. /pages/01.html?yes=no#section-2 -const relativeLocation = (url, win) => { - const a = win.document.createElement('A') +const relativeLocation = (url: string, win: Window) => { + const a = win.document.createElement('a') a.href = url return `${a.pathname}${a.search}${a.hash}` } -const stateChangeToMetadata = (win, state, title, url) => { +const stateChangeToMetadata = (win: Window, state: string, title: string, url?: string | URL | null) => { const currentPath = relativeLocation(win.location.href, win) return { title, state, prevState: getCurrentState(win), to: url || currentPath, from: currentPath } } -const wrapHistoryFn = (client, target, fn, win, resetEventCount = false) => { +type HistoryMethods = 'pushState' | 'replaceState' +const wrapHistoryFn = (client: Client, target: ExtendedHistory, fn: HistoryMethods, win: Window, resetEventCount = false) => { const orig = target[fn] target[fn] = (state, title, url) => { client.leaveBreadcrumb(`History ${fn}`, stateChangeToMetadata(win, state, title, url), 'navigation') @@ -70,14 +86,14 @@ const wrapHistoryFn = (client, target, fn, win, resetEventCount = false) => { if (resetEventCount && typeof client.resetEventCount === 'function') client.resetEventCount() // Internet Explorer will convert `undefined` to a string when passed, causing an unintended redirect // to '/undefined'. therefore we only pass the url if it's not undefined. - orig.apply(target, [state, title].concat(url !== undefined ? url : [])) + orig.apply(target, [state, title].concat(url !== undefined ? url : []) as Parameters) } if (process.env.NODE_ENV !== 'production') { target[fn]._restore = () => { target[fn] = orig } } } -const getCurrentState = (win) => { +const getCurrentState = (win: Window) => { try { return win.history.state } catch (e) {} diff --git a/packages/plugin-navigation-breadcrumbs/test/navigation-breadcrumbs.test.ts b/packages/plugin-navigation-breadcrumbs/test/navigation-breadcrumbs.test.ts index 1b05070d53..0d2c34b9de 100644 --- a/packages/plugin-navigation-breadcrumbs/test/navigation-breadcrumbs.test.ts +++ b/packages/plugin-navigation-breadcrumbs/test/navigation-breadcrumbs.test.ts @@ -1,4 +1,4 @@ -import plugin from '../navigation-breadcrumbs' +import plugin from '../src/navigation-breadcrumbs' import Client from '@bugsnag/core/client' diff --git a/packages/plugin-navigation-breadcrumbs/tsconfig.json b/packages/plugin-navigation-breadcrumbs/tsconfig.json new file mode 100644 index 0000000000..a4cc3029ff --- /dev/null +++ b/packages/plugin-navigation-breadcrumbs/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": { + "types": ["node"] + } +} + \ No newline at end of file diff --git a/packages/plugin-simple-throttle/rollup.config.npm.mjs b/packages/plugin-simple-throttle/rollup.config.npm.mjs index 17c25ef1a6..bb2a0d724e 100644 --- a/packages/plugin-simple-throttle/rollup.config.npm.mjs +++ b/packages/plugin-simple-throttle/rollup.config.npm.mjs @@ -1,5 +1,6 @@ -import createRollupConfig from "../../.rollup/index.mjs"; +import createRollupConfig from '../../.rollup/index.mjs' export default createRollupConfig({ - input: "src/throttle.ts" -}); + input: 'src/throttle.ts', + external: ['@bugsnag/core/lib/validators/int-range'] +}) diff --git a/packages/plugin-simple-throttle/src/throttle.ts b/packages/plugin-simple-throttle/src/throttle.ts index b2aa3e3b81..234f9102b9 100644 --- a/packages/plugin-simple-throttle/src/throttle.ts +++ b/packages/plugin-simple-throttle/src/throttle.ts @@ -1,10 +1,26 @@ -import { Plugin } from '@bugsnag/core' import intRange from '@bugsnag/core/lib/validators/int-range' +import { Client, Config, Logger, Plugin } from '@bugsnag/core' + +interface ThrottlePlugin extends Plugin { + configSchema: { + [key: string]: { + defaultValue: () => unknown + message: string + validate: (value: unknown) => boolean + } + } +} + +interface InternalClient extends Client { + _config: Config & { maxEvents: number } + _logger: Logger +} + /* * Throttles and dedupes events */ -const plugin: Plugin = { +const plugin: ThrottlePlugin = { load: (client) => { // track sent events for each init of the plugin let n = 0 @@ -12,10 +28,8 @@ const plugin: Plugin = { // add onError hook client.addOnError((event) => { // have max events been sent already? - // @ts-expect-error _config is private API - if (n >= client._config.maxEvents) { - // @ts-expect-error _config is private API - client._logger.warn(`Cancelling event send due to maxEvents per session limit of ${client._config.maxEvents} being reached`) + if (n >= (client as InternalClient)._config.maxEvents) { + (client as InternalClient)._logger.warn(`Cancelling event send due to maxEvents per session limit of ${(client as InternalClient)._config.maxEvents} being reached`) return false } n++ @@ -23,7 +37,6 @@ const plugin: Plugin = { client.resetEventCount = () => { n = 0 } }, - // @ts-expect-error _config is private API configSchema: { maxEvents: { defaultValue: () => 10,