Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert @bugsnag/plugin-browser-device #2227

Merged
merged 5 commits into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 20 additions & 7 deletions .rollup/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,31 @@ const defaultOptions = () => ({
output: undefined
})

const sharedOutput = {
dir: 'dist',
generatedCode: {
preset: 'es2015',
}
}

function createRollupConfig (options = defaultOptions()) {
const packageJson = JSON.parse(fs.readFileSync(`${process.cwd()}/package.json`))

return {
input: options.input || 'src/index.ts',
output: options.output || {
dir: 'dist',
format: 'esm',
preserveModules: true,
generatedCode: {
preset: 'es2015',
output: options.output || [
{
...sharedOutput,
entryFileNames: '[name].js',
format: 'cjs'
},
{
...sharedOutput,
preserveModules: true,
entryFileNames: '[name].mjs',
format: 'esm'
}
},
],
external: ['@bugsnag/core'].concat(options.external),
plugins: [
replace({
Expand All @@ -37,6 +49,7 @@ function createRollupConfig (options = defaultOptions()) {
}
}),
typescript({
removeComments: true,
// don't output anything if there's a TS error
noEmitOnError: true,
// turn on declaration files and declaration maps
Expand Down
22 changes: 1 addition & 21 deletions packages/plugin-app-duration/rollup.config.npm.mjs
Original file line number Diff line number Diff line change
@@ -1,25 +1,5 @@
import createRollupConfig from '../../.rollup/index.mjs'

export default createRollupConfig({
input: 'src/app-duration.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',
}
}
]
input: 'src/app-duration.ts'
})
15 changes: 14 additions & 1 deletion packages/plugin-browser-device/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
{
"name": "@bugsnag/plugin-browser-device",
"version": "8.0.0",
"main": "device.js",
"main": "dist/device.js",
"types": "dist/types/device.d.ts",
"exports": {
".": {
"types": "./dist/types/device.d.ts",
"default": "./dist/device.js",
"import": "./dist/device.mjs"
}
},
"description": "@bugsnag/js plugin to set device info in browsers",
"homepage": "https://www.bugsnag.com/",
"repository": {
Expand All @@ -24,5 +32,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/*"
}
}
6 changes: 6 additions & 0 deletions packages/plugin-browser-device/rollup.config.npm.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import createRollupConfig from '../../.rollup/index.mjs'

export default createRollupConfig({
input: 'src/device.ts',
external: ['@bugsnag/cuid'],
})
Original file line number Diff line number Diff line change
@@ -1,35 +1,24 @@
const assign = require('@bugsnag/core/lib/es-utils/assign')
const BUGSNAG_ANONYMOUS_ID_KEY = 'bugsnag-anonymous-id'
import type { Device, Plugin } from '@bugsnag/core'
import assign from '@bugsnag/core/lib/es-utils/assign'
import setDefaultUserId from './set-default-user-id'
import getDeviceId from './get-device-id'

const getDeviceId = (win) => {
try {
const storage = win.localStorage

let id = storage.getItem(BUGSNAG_ANONYMOUS_ID_KEY)

// If we get an ID, make sure it looks like a valid cuid. The length can
// fluctuate slightly, so some leeway is built in
if (id && /^c[a-z0-9]{20,32}$/.test(id)) {
return id
}

const cuid = require('@bugsnag/cuid')
id = cuid()

storage.setItem(BUGSNAG_ANONYMOUS_ID_KEY, id)

return id
} catch (err) {
// If localStorage is not available (e.g. because it's disabled) then give up
// Declare deprecated navigator values
declare global {
interface Navigator {
browserLanguage?: string
systemLanguage?: string
userLanguage?: string
}
}

/*
* Automatically detects browser device details
*/
module.exports = (nav = navigator, win = window) => ({
export default (nav = navigator, win = window): Plugin => ({
name: 'device',
load: (client) => {
const device = {
const device: Device = {
locale: nav.browserLanguage || nav.systemLanguage || nav.userLanguage || nav.language,
userAgent: nav.userAgent
}
Expand All @@ -43,13 +32,15 @@ module.exports = (nav = navigator, win = window) => ({
: 'portrait'
}

// @ts-expect-error _config is private API
if (client._config.generateAnonymousId) {
device.id = getDeviceId(win)
}

client.addOnSession(session => {
session.device = assign({}, session.device, device)
// only set device id if collectUserIp is false
// @ts-expect-error _config is private API
if (!client._config.collectUserIp) setDefaultUserId(session)
})

Expand All @@ -60,22 +51,17 @@ module.exports = (nav = navigator, win = window) => ({
device,
{ time: new Date() }
)
// @ts-expect-error _config is private API
if (!client._config.collectUserIp) setDefaultUserId(event)
// @ts-expect-error second parameter is private API
}, true)
},
// @ts-expect-error _config is private API
configSchema: {
generateAnonymousId: {
validate: value => value === true || value === false,
validate: (value: unknown): value is boolean => value === true || value === false,
defaultValue: () => true,
message: 'should be true|false'
}
}
})

const setDefaultUserId = (eventOrSession) => {
// device id is also used to populate the user id field, if it's not already set
const user = eventOrSession.getUser()
if (!user || !user.id) {
eventOrSession.setUser(eventOrSession.device.id)
}
}
27 changes: 27 additions & 0 deletions packages/plugin-browser-device/src/get-device-id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import cuid from '@bugsnag/cuid'

const BUGSNAG_ANONYMOUS_ID_KEY = 'bugsnag-anonymous-id'

const getDeviceId = (win: Window) => {
try {
const storage = win.localStorage

let id = storage.getItem(BUGSNAG_ANONYMOUS_ID_KEY)

// If we get an ID, make sure it looks like a valid cuid. The length can
// fluctuate slightly, so some leeway is built in
if (id && /^c[a-z0-9]{20,32}$/.test(id)) {
return id
}

id = cuid()

storage.setItem(BUGSNAG_ANONYMOUS_ID_KEY, id)

return id
} catch (err) {
// If localStorage is not available (e.g. because it's disabled) then give up
}
}

export default getDeviceId
11 changes: 11 additions & 0 deletions packages/plugin-browser-device/src/set-default-user-id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { Event, Session } from '@bugsnag/core'

const setDefaultUserId = (eventOrSession: Event | Session) => {
// device id is also used to populate the user id field, if it's not already set
const user = eventOrSession.getUser()
if ((!user || !user.id) && eventOrSession.device) {
eventOrSession.setUser(eventOrSession.device.id)
}
}

export default setDefaultUserId
2 changes: 1 addition & 1 deletion packages/plugin-browser-device/test/device.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import plugin from '../device'
import plugin from '../src/device'

import Client, {
SessionDeliveryPayload,
Expand Down
8 changes: 8 additions & 0 deletions packages/plugin-browser-device/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "../../tsconfig.json",
"include": ["src/**/*.ts"],
"compilerOptions": {
"target": "ES2020"
}
}

22 changes: 1 addition & 21 deletions packages/plugin-window-onerror/rollup.config.npm.mjs
Original file line number Diff line number Diff line change
@@ -1,25 +1,5 @@
import createRollupConfig from '../../.rollup/index.mjs'

export default createRollupConfig({
input: 'src/onerror.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',
}
}
]
input: 'src/onerror.ts'
})
22 changes: 1 addition & 21 deletions packages/plugin-window-unhandled-rejection/rollup.config.npm.mjs
Original file line number Diff line number Diff line change
@@ -1,25 +1,5 @@
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',
}
}
]
input: 'src/unhandled-rejection.ts'
})
4 changes: 1 addition & 3 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@
"packages/in-flight",
"packages/plugin-aws-lambda",
"packages/plugin-browser-context",
"packages/plugin-browser-device",
"packages/plugin-contextualize",
"packages/plugin-navigation-breadcrumbs",
"packages/plugin-network-breadcrumbs",
Expand Down Expand Up @@ -96,7 +95,6 @@
"packages/browser"
],
"exclude": [
"packages/react-native/src/NativeBugsnag.ts",
"packages/**/dist/**/*.js"
"packages/react-native/src/NativeBugsnag.ts"
]
}
Loading