diff --git a/packages/core/lib/iserror.d.ts b/packages/core/lib/iserror.d.ts new file mode 100644 index 0000000000..b0c8ab398d --- /dev/null +++ b/packages/core/lib/iserror.d.ts @@ -0,0 +1 @@ +export default function isError(maybeError: unknown): maybeError is Error diff --git a/packages/plugin-window-unhandled-rejection/package.json b/packages/plugin-window-unhandled-rejection/package.json index f0afa38985..8fba595d67 100644 --- a/packages/plugin-window-unhandled-rejection/package.json +++ b/packages/plugin-window-unhandled-rejection/package.json @@ -1,7 +1,15 @@ { "name": "@bugsnag/plugin-window-unhandled-rejection", "version": "8.0.0", - "main": "unhandled-rejection.js", + "main": "dist/unhandled-rejection.js", + "types": "dist/types/unhandled-rejection.d.ts", + "exports": { + ".": { + "types": "./dist/types/unhandled-rejection.d.ts", + "default": "./dist/unhandled-rejection.js", + "import": "./dist/unhandled-rejection.mjs" + } + }, "description": "@bugsnag/js plugin to report unhandled promise rejections in browsers", "homepage": "https://www.bugsnag.com/", "repository": { @@ -21,5 +29,10 @@ }, "peerDependencies": { "@bugsnag/core": "^8.0.0" + }, + "scripts": { + "build": "npm run build:npm", + "build:npm": "rollup --config rollup.config.npm.mjs", + "clean": "rm -rf dist/*" } } diff --git a/packages/plugin-window-unhandled-rejection/rollup.config.npm.mjs b/packages/plugin-window-unhandled-rejection/rollup.config.npm.mjs new file mode 100644 index 0000000000..6b32b19f98 --- /dev/null +++ b/packages/plugin-window-unhandled-rejection/rollup.config.npm.mjs @@ -0,0 +1,25 @@ +import createRollupConfig from '../../.rollup/index.mjs' + +export default createRollupConfig({ + input: 'src/unhandled-rejection.ts', + output: [ + { + dir: `dist`, + entryFileNames: '[name].js', + format: 'cjs', + preserveModules: true, + generatedCode: { + preset: 'es2015', + } + }, + { + dir: `dist`, + entryFileNames: '[name].mjs', + format: 'esm', + preserveModules: true, + generatedCode: { + preset: 'es2015', + } + } + ] +}) diff --git a/packages/plugin-window-unhandled-rejection/unhandled-rejection.js b/packages/plugin-window-unhandled-rejection/src/unhandled-rejection.ts similarity index 73% rename from packages/plugin-window-unhandled-rejection/unhandled-rejection.js rename to packages/plugin-window-unhandled-rejection/src/unhandled-rejection.ts index f766ab2707..85e0e287d3 100644 --- a/packages/plugin-window-unhandled-rejection/unhandled-rejection.js +++ b/packages/plugin-window-unhandled-rejection/src/unhandled-rejection.ts @@ -1,21 +1,28 @@ -const map = require('@bugsnag/core/lib/es-utils/map') -const isError = require('@bugsnag/core/lib/iserror') +import { Plugin, Stackframe } from '@bugsnag/core' +import map from '@bugsnag/core/lib/es-utils/map' +import isError from '@bugsnag/core/lib/iserror' + +type Listener = (evt: PromiseRejectionEvent) => void + +let _listener: Listener | null -let _listener /* * Automatically notifies Bugsnag when window.onunhandledrejection is called */ -module.exports = (win = window) => { - const plugin = { +export default (win = window): Plugin => { + const plugin: Plugin = { load: (client) => { + // @ts-expect-error _config is private API if (!client._config.autoDetectErrors || !client._config.enabledErrorTypes.unhandledRejections) return - const listener = evt => { + const listener = (evt: PromiseRejectionEvent) => { let error = evt.reason let isBluebird = false // accessing properties on evt.detail can throw errors (see #394) try { + // @ts-expect-error detail does not exist on type PromiseRejectionEvent if (evt.detail && evt.detail.reason) { + // @ts-expect-error detail does not exist on type PromiseRejectionEvent error = evt.detail.reason isBluebird = true } @@ -25,6 +32,7 @@ module.exports = (win = window) => { severity: 'error', unhandled: true, severityReason: { type: 'unhandledPromiseRejection' } + // @ts-expect-error _logger is private API }, 'unhandledrejection handler', 1, client._logger) if (isBluebird) { @@ -37,6 +45,7 @@ module.exports = (win = window) => { [Object.prototype.toString.call(event.originalError)]: { name: event.originalError.name, message: event.originalError.message, + // @ts-expect-error Property 'code' does not exist on type 'Error' code: event.originalError.code } }) @@ -46,7 +55,9 @@ module.exports = (win = window) => { if ('addEventListener' in win) { win.addEventListener('unhandledrejection', listener) } else { + // @ts-expect-error onunhandledrejection does not exist on type never win.onunhandledrejection = (reason, promise) => { + // @ts-expect-error detail does not exist on type PromiseRejectionEvent listener({ detail: { reason, promise } }) } } @@ -54,13 +65,14 @@ module.exports = (win = window) => { } } + // @ts-expect-error cannot find name 'process' if (process.env.NODE_ENV !== 'production') { plugin.destroy = (win = window) => { if (_listener) { if ('addEventListener' in win) { win.removeEventListener('unhandledrejection', _listener) } else { - win.onunhandledrejection = null + (win as Window).onunhandledrejection = null } } _listener = null @@ -88,7 +100,7 @@ module.exports = (win = window) => { // // Bluebird pads method names with spaces so trim that too… // https://github.com/petkaantonov/bluebird/blob/b7f21399816d02f979fe434585334ce901dcaf44/src/debuggability.js#L568-L571 -const fixBluebirdStacktrace = (error) => (frame) => { +const fixBluebirdStacktrace = (error: PromiseRejectionEvent['reason']) => (frame: Stackframe) => { if (frame.file === error.toString()) return if (frame.method) { frame.method = frame.method.replace(/^\s+/, '') diff --git a/packages/plugin-window-unhandled-rejection/test/unhandled-rejection.test.ts b/packages/plugin-window-unhandled-rejection/test/unhandled-rejection.test.ts index 9b5b6da1c5..3e6c99b89f 100644 --- a/packages/plugin-window-unhandled-rejection/test/unhandled-rejection.test.ts +++ b/packages/plugin-window-unhandled-rejection/test/unhandled-rejection.test.ts @@ -1,5 +1,5 @@ /* eslint-disable jest/no-commented-out-tests */ -import plugin from '../' +import plugin from '../src/unhandled-rejection' import Client from '@bugsnag/core/client' diff --git a/packages/plugin-window-unhandled-rejection/tsconfig.json b/packages/plugin-window-unhandled-rejection/tsconfig.json new file mode 100644 index 0000000000..c76cdab7cd --- /dev/null +++ b/packages/plugin-window-unhandled-rejection/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": { + "target": "ES2020" + } +} + \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 194cb11f2f..ba66910c52 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -81,7 +81,6 @@ "packages/plugin-restify", "packages/node", "packages/plugin-client-ip", - "packages/plugin-window-unhandled-rejection", "packages/plugin-strip-query-string", "packages/plugin-strip-project-root", "packages/plugin-interaction-breadcrumbs",