@ohbug/browser 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,35 +0,0 @@
1
- import { getGlobal, getOhbugObject, getSelector } from '@ohbug/utils'
2
-
3
- const global = getGlobal<Window>()
4
-
5
- function listener(e: MouseEvent) {
6
- if (e.target) {
7
- const { client } = getOhbugObject<Window>()
8
- const { tagName, id, className, name, src, outerHTML, nodeType }
9
- = e.target as any
10
- const selector = getSelector(e)
11
-
12
- client.addAction(
13
- 'click node',
14
- {
15
- tagName,
16
- id,
17
- className,
18
- name,
19
- src,
20
- outerHTML,
21
- nodeType,
22
- selector,
23
- },
24
- 'click',
25
- )
26
- }
27
- }
28
-
29
- export function captureClick() {
30
- global?.document?.addEventListener?.('click', listener)
31
- }
32
-
33
- export function removeCaptureClick() {
34
- global?.document?.removeEventListener?.('click', listener)
35
- }
@@ -1,100 +0,0 @@
1
- import { getGlobal, getOhbugObject, parseUrl, replace } from '@ohbug/utils'
2
-
3
- const global = getGlobal<Window>()
4
- let lastHref: string | undefined
5
-
6
- function handleUrlChange(from?: string, to?: string) {
7
- const { client } = getOhbugObject<Window>()
8
- const parsedHref = parseUrl(global?.location?.href)
9
- let parsedFrom = parseUrl(from as string)
10
- const parsedTo = parseUrl(to as string)
11
-
12
- if (!parsedFrom.path)
13
- parsedFrom = parsedHref
14
-
15
- lastHref = to
16
-
17
- let targetFrom = from
18
- let targetTo = to
19
-
20
- if (
21
- parsedHref.protocol === parsedTo.protocol
22
- && parsedHref.host === parsedTo.host
23
- )
24
- targetTo = parsedTo.relative
25
-
26
- if (
27
- parsedHref.protocol === parsedFrom.protocol
28
- && parsedHref.host === parsedFrom.host
29
- )
30
- targetFrom = parsedFrom.relative
31
-
32
- if (targetFrom === targetTo) return
33
-
34
- client.addAction(
35
- `navigation to ${to}`,
36
- {
37
- from,
38
- to,
39
- },
40
- 'navigation',
41
- )
42
- }
43
-
44
- function historyReplacement(original: (data: any, title: string, url?: string) => void) {
45
- return function call(data: any, title: string, url?: string) {
46
- if (url)
47
- handleUrlChange(lastHref, String(url))
48
-
49
- return original.apply(this, [data, title, url])
50
- }
51
- }
52
-
53
- const historyOriginal = {
54
- pushState: global?.history?.pushState,
55
- replaceState: global?.history?.replaceState,
56
- onpopstate: global?.onpopstate,
57
- }
58
- function historyListener() {
59
- historyOriginal.pushState = replace(
60
- global?.history,
61
- 'pushState',
62
- historyReplacement,
63
- )
64
- historyOriginal.replaceState = replace(
65
- global?.history,
66
- 'replaceState',
67
- historyReplacement,
68
- )
69
- historyOriginal.onpopstate = replace(
70
- global,
71
- 'onpopstate',
72
- origin =>
73
- function call(...args: any[]) {
74
- const current = global?.location?.href
75
- handleUrlChange(lastHref, current)
76
- return origin?.apply(this, args)
77
- },
78
- )
79
- }
80
-
81
- function hashListener(e: Event) {
82
- const { oldURL, newURL } = e as HashChangeEvent
83
- handleUrlChange(oldURL, newURL)
84
- }
85
-
86
- export function captureUrlChange() {
87
- // history
88
- historyListener()
89
- // hash
90
- global?.addEventListener?.('hashchange', hashListener, true)
91
- }
92
-
93
- export function removeCaptureUrlChange() {
94
- // history
95
- global.history.pushState = historyOriginal.pushState
96
- global.history.replaceState = historyOriginal.replaceState
97
- global.onpopstate = historyOriginal.onpopstate
98
- // hash
99
- global?.removeEventListener?.('hashchange', hashListener, true)
100
- }
@@ -1,45 +0,0 @@
1
- /* eslint-disable no-console */
2
-
3
- import { getOhbugObject, replace } from '@ohbug/utils'
4
-
5
- type Level = 'log' | 'info' | 'warn' | 'error'
6
- const levels: Level[] = ['log', 'info', 'warn', 'error']
7
- const consoleOriginal = Object.keys(levels).reduce<Record<Level, any>>(
8
- (acc, cur: string) => ({
9
- ...acc,
10
- // @ts-expect-error 修改了原生的console
11
- [cur]: console[cur],
12
- }),
13
- {
14
- log: null,
15
- info: null,
16
- warn: null,
17
- error: null,
18
- },
19
- )
20
-
21
- export function captureConsole() {
22
- const { client } = getOhbugObject<Window>()
23
- levels.forEach((level) => {
24
- consoleOriginal[level] = replace(
25
- console,
26
- level,
27
- origin =>
28
- function call(...args: any[]) {
29
- const isOhbugConsole = args.some(arg => typeof arg === 'string' && arg.includes('Ohbug'))
30
- if (!isOhbugConsole)
31
- client.addAction(`console.${level}`, args, 'console')
32
-
33
- return origin.apply(this, args)
34
- },
35
- )
36
- })
37
- }
38
-
39
- export function removeCaptureConsole() {
40
- if (console) {
41
- levels.forEach((level) => {
42
- console[level] = consoleOriginal[level]
43
- })
44
- }
45
- }
@@ -1,64 +0,0 @@
1
- import { getGlobal } from '@ohbug/utils'
2
- import {
3
- captureUrlChange,
4
- removeCaptureUrlChange,
5
- } from './action/captureUrlChange'
6
- import { captureClick, removeCaptureClick } from './action/captureClick'
7
- import { captureConsole, removeCaptureConsole } from './console/captureConsole'
8
- import {
9
- captureAjaxError,
10
- removeCaptureAjaxError,
11
- } from './network/captureAjaxError'
12
- import {
13
- captureFetchError,
14
- removeCaptureFetchError,
15
- } from './network/captureFetchError'
16
- import { captureWebSocketError } from './network/captureWebSocketError'
17
- import {
18
- captureUncaughtError,
19
- removeCaptureUncaughtError,
20
- } from './script/captureUncaughtError'
21
- import {
22
- captureUnhandledrejectionError,
23
- removeCaptureUnhandledrejectionError,
24
- } from './script/captureUnhandledrejectionError'
25
-
26
- export function captureAction() {
27
- captureUrlChange()
28
- captureClick()
29
- }
30
- export function removeCaptureAction() {
31
- removeCaptureUrlChange()
32
- removeCaptureClick()
33
- }
34
-
35
- export { captureConsole, removeCaptureConsole }
36
-
37
- export function captureNetwork() {
38
- captureAjaxError()
39
- captureFetchError()
40
- captureWebSocketError()
41
- }
42
- export function removeCaptureNetwork() {
43
- removeCaptureAjaxError()
44
- removeCaptureFetchError()
45
- }
46
-
47
- export function captureScript() {
48
- const global = getGlobal<Window>()
49
- if (!global.addEventListener) return
50
-
51
- captureUncaughtError()
52
- captureUnhandledrejectionError()
53
- }
54
- export function removeCaptureScript() {
55
- removeCaptureUncaughtError()
56
- removeCaptureUnhandledrejectionError()
57
- }
58
-
59
- export function handleCapture() {
60
- captureScript()
61
- captureNetwork()
62
- captureAction()
63
- captureConsole()
64
- }
@@ -1,81 +0,0 @@
1
- import { getGlobal, getOhbugObject, replace } from '@ohbug/utils'
2
- import { EventTypes } from '@ohbug/core'
3
-
4
- import { networkDispatcher } from '../../dispatch'
5
- import type { AjaxErrorDetail } from '../../handle'
6
-
7
- const global = getGlobal<Window>()
8
- const access = 'XMLHttpRequest' in global
9
- const xhrOriginal = access
10
- ? {
11
- open: XMLHttpRequest.prototype.open,
12
- send: XMLHttpRequest.prototype.send,
13
- }
14
- : {}
15
-
16
- /**
17
- * capture AJAX_ERROR
18
- */
19
- export function captureAjaxError() {
20
- if (!access) return
21
-
22
- const { client } = getOhbugObject<Window>()
23
-
24
- const desc = {
25
- method: '',
26
- url: '',
27
- }
28
-
29
- const xhrProto = XMLHttpRequest?.prototype
30
-
31
- xhrOriginal.open = replace(
32
- xhrProto,
33
- 'open',
34
- origin =>
35
- function call(...args: any[]) {
36
- const [method, url] = args
37
- desc.method = method
38
- desc.url = url
39
- return origin.apply(this, args)
40
- },
41
- )
42
-
43
- xhrOriginal.send = replace(
44
- xhrProto,
45
- 'send',
46
- origin =>
47
- function call(...args: any[]) {
48
- this.addEventListener('readystatechange', function handle() {
49
- if (this.readyState === 4) {
50
- if (desc.url !== client.__config.endpoint) {
51
- const detail: AjaxErrorDetail = {
52
- req: {
53
- url: desc.url,
54
- method: desc.method,
55
- data: args[0] || {},
56
- },
57
- res: {
58
- status: this.status,
59
- statusText: this.statusText,
60
- response: this.response,
61
- },
62
- }
63
-
64
- client.addAction('ajax', detail, 'ajax')
65
- if (!this.status || this.status >= 400)
66
- networkDispatcher(EventTypes.AJAX_ERROR, detail)
67
- }
68
- }
69
- })
70
- return origin.apply(this, args)
71
- },
72
- )
73
- }
74
-
75
- export function removeCaptureAjaxError() {
76
- if (access && xhrOriginal.open && xhrOriginal.send) {
77
- const xhrProto = XMLHttpRequest?.prototype
78
- xhrProto.open = xhrOriginal.open
79
- xhrProto.send = xhrOriginal.send
80
- }
81
- }
@@ -1,69 +0,0 @@
1
- import { getGlobal, getOhbugObject, replace } from '@ohbug/utils'
2
- import { EventTypes } from '@ohbug/core'
3
-
4
- import { networkDispatcher } from '../../dispatch'
5
- import type { FetchErrorDetail } from '../../handle'
6
-
7
- const global = getGlobal<Window>()
8
- const access = 'fetch' in global
9
-
10
- let fetchOriginal = access ? global.fetch : null
11
- /**
12
- * capture FETCH_ERROR
13
- */
14
- export function captureFetchError() {
15
- if (!access) return
16
-
17
- const { client } = getOhbugObject<Window>()
18
-
19
- fetchOriginal = replace(
20
- global,
21
- 'fetch',
22
- origin =>
23
- function call(...args: any[]) {
24
- return origin.apply(this, args).then(
25
- (res: Response) => {
26
- const [url, conf] = args
27
- const detail: FetchErrorDetail = {
28
- req: {
29
- url,
30
- method: conf && conf.method,
31
- data: (conf && conf.body) || {},
32
- },
33
- res: {
34
- status: res.status,
35
- statusText: res.statusText,
36
- },
37
- }
38
- client.addAction('fetch', detail, 'fetch')
39
-
40
- if (!res.status || res.status >= 400)
41
- networkDispatcher(EventTypes.FETCH_ERROR, detail)
42
-
43
- return res
44
- },
45
- (err: Error) => {
46
- const [url, conf] = args
47
- const detail: FetchErrorDetail = {
48
- req: {
49
- url,
50
- method: conf && conf.method,
51
- data: (conf && conf.body) || {},
52
- },
53
- res: {
54
- status: 400,
55
- statusText: 'unknownError',
56
- },
57
- }
58
- networkDispatcher(EventTypes.FETCH_ERROR, detail)
59
- throw err
60
- },
61
- )
62
- },
63
- )
64
- }
65
-
66
- export function removeCaptureFetchError() {
67
- if (access && fetchOriginal)
68
- global.fetch = fetchOriginal
69
- }
@@ -1,51 +0,0 @@
1
- import { getGlobal } from '@ohbug/utils'
2
- import { EventTypes } from '@ohbug/core'
3
-
4
- import { networkDispatcher } from '../../dispatch'
5
- import type { WebsocketErrorDetail } from '../../handle'
6
-
7
- const global = getGlobal<Window>()
8
-
9
- /**
10
- * capture WEBSOCKET_ERROR
11
- */
12
- export function captureWebSocketError() {
13
- if (!('WebSocket' in global)) return
14
-
15
- const wsProto = WebSocket?.prototype
16
-
17
- const backup = Object.getOwnPropertyDescriptor(wsProto, 'onerror')
18
-
19
- // eslint-disable-next-line accessor-pairs
20
- Object.defineProperty(wsProto, 'onerror', {
21
- set() {
22
- // eslint-disable-next-line prefer-rest-params
23
- const args = arguments
24
- const arg = args[0]
25
- backup?.set?.call(this, function call(e: any) {
26
- const {
27
- target: {
28
- url,
29
- readyState,
30
- protocol,
31
- extensions,
32
- binaryType,
33
- bufferedAmount,
34
- },
35
- timeStamp,
36
- } = e
37
- const detail: WebsocketErrorDetail = {
38
- url,
39
- timeStamp,
40
- readyState,
41
- protocol,
42
- extensions,
43
- binaryType,
44
- bufferedAmount,
45
- }
46
- networkDispatcher(EventTypes.WEBSOCKET_ERROR, detail)
47
- arg.apply(this, args)
48
- })
49
- },
50
- })
51
- }
@@ -1,20 +0,0 @@
1
- import { getGlobal } from '@ohbug/utils'
2
-
3
- import { scriptDispatcher } from '../../dispatch'
4
-
5
- const global = getGlobal<Window>()
6
-
7
- function listener(e: ErrorEvent) {
8
- scriptDispatcher(e)
9
- }
10
-
11
- /**
12
- * capture UNCAUGHT_ERROR RESOURCE_ERROR
13
- */
14
- export function captureUncaughtError() {
15
- global?.addEventListener?.('error', listener, true)
16
- }
17
-
18
- export function removeCaptureUncaughtError() {
19
- global?.removeEventListener?.('error', listener, true)
20
- }
@@ -1,20 +0,0 @@
1
- import { getGlobal } from '@ohbug/utils'
2
-
3
- import { scriptDispatcher } from '../../dispatch'
4
-
5
- const global = getGlobal<Window>()
6
-
7
- function listener(e: PromiseRejectionEvent) {
8
- scriptDispatcher(e)
9
- }
10
-
11
- /**
12
- * capture UNHANDLEDREJECTION_ERROR
13
- */
14
- export function captureUnhandledrejectionError() {
15
- global?.addEventListener?.('unhandledrejection', listener, true)
16
- }
17
-
18
- export function removeCaptureUnhandledrejectionError() {
19
- global?.removeEventListener?.('unhandledrejection', listener, true)
20
- }
package/src/client.ts DELETED
@@ -1,46 +0,0 @@
1
- import type { OhbugClient, OhbugConfig, OhbugSDK } from '@ohbug/types'
2
- import { Client } from '@ohbug/core'
3
-
4
- import { getGlobal } from '@ohbug/utils'
5
-
6
- import { device } from './device'
7
- import { version } from './version'
8
- import { extension } from './extension'
9
- import { notifier } from './notifier'
10
-
11
- interface OhbugBrowserClient {
12
- __client: OhbugClient | null
13
- setup: (config: OhbugConfig) => OhbugClient
14
- }
15
-
16
- function createClient(config: OhbugConfig) {
17
- const global = getGlobal<Window>()
18
-
19
- const sdk: OhbugSDK = {
20
- platform: 'ohbug-browser',
21
- version,
22
- }
23
- const client = new Client({ sdk, config, device, notifier })
24
- global.__OHBUG__ = { client }
25
- client.use(extension)
26
- client.__logger.info(
27
- `%c @ohbug/browser %c Detected Ohbug v${version} %c`,
28
- 'background:#333; padding: 2px 1px; color: #FFF',
29
- 'background:#FF6F61; padding: 2px 1px; color: #FFF',
30
- 'background:transparent',
31
- )
32
- return client
33
- }
34
-
35
- export const BrowserClient: OhbugBrowserClient = {
36
- __client: null,
37
- setup(config: OhbugConfig) {
38
- if (BrowserClient.__client) {
39
- BrowserClient.__client.__logger?.warn('init() has been called. Ignored.')
40
- return BrowserClient.__client
41
- }
42
-
43
- BrowserClient.__client = createClient(config)
44
- return BrowserClient.__client
45
- },
46
- }
package/src/destroy.ts DELETED
@@ -1,22 +0,0 @@
1
- import { getGlobal } from '@ohbug/utils'
2
- import {
3
- removeCaptureAction,
4
- removeCaptureConsole,
5
- removeCaptureNetwork,
6
- removeCaptureScript,
7
- } from './capture'
8
-
9
- const global = getGlobal<Window>()
10
-
11
- export function handleDestroy() {
12
- global?.addEventListener?.(
13
- 'unload',
14
- () => {
15
- removeCaptureScript()
16
- removeCaptureNetwork()
17
- removeCaptureAction()
18
- removeCaptureConsole()
19
- },
20
- true,
21
- )
22
- }
package/src/device.ts DELETED
@@ -1,19 +0,0 @@
1
- import type { OhbugDevice, OhbugGetDevice } from '@ohbug/types'
2
-
3
- export const device: OhbugGetDevice = () => {
4
- const ohbugDevice: OhbugDevice = {}
5
- if (navigator) {
6
- const { language, userAgent } = navigator
7
- ohbugDevice.language = language
8
- ohbugDevice.userAgent = userAgent
9
- }
10
- if (document) {
11
- const { title } = document
12
- ohbugDevice.title = title
13
- }
14
- if (window.location) {
15
- const { href: url } = window.location
16
- ohbugDevice.url = url
17
- }
18
- return ohbugDevice
19
- }
@@ -1,2 +0,0 @@
1
- export * from './scriptDispatcher'
2
- export * from './networkDispatcher'
@@ -1,29 +0,0 @@
1
- import { EventTypes } from '@ohbug/core'
2
-
3
- import {
4
- ajaxErrorHandler,
5
- fetchErrorHandler,
6
- unknownErrorHandler,
7
- websocketErrorHandler,
8
- } from '../handle'
9
-
10
- export function networkDispatcher(type: string, detail: any) {
11
- try {
12
- switch (type) {
13
- case EventTypes.AJAX_ERROR:
14
- ajaxErrorHandler(detail)
15
- break
16
- case EventTypes.FETCH_ERROR:
17
- fetchErrorHandler(detail)
18
- break
19
- case EventTypes.WEBSOCKET_ERROR:
20
- websocketErrorHandler(detail)
21
- break
22
- default:
23
- break
24
- }
25
- }
26
- catch (error) {
27
- unknownErrorHandler(error)
28
- }
29
- }
@@ -1,30 +0,0 @@
1
- import {
2
- resourceErrorHandler,
3
- uncaughtErrorHandler,
4
- unhandledrejectionErrorHandler,
5
- unknownErrorHandler,
6
- } from '../handle'
7
-
8
- export function scriptDispatcher(e: ErrorEvent | PromiseRejectionEvent) {
9
- try {
10
- const { type } = e
11
- if (type === 'error') {
12
- const targetEvent = e as ErrorEvent
13
- const { message, error } = targetEvent
14
- const immutableTarget = e.target || e.srcElement
15
- if (message && error)
16
- uncaughtErrorHandler(targetEvent)
17
- else if (immutableTarget)
18
- resourceErrorHandler(targetEvent)
19
- }
20
- else if (type === 'unhandledrejection') {
21
- unhandledrejectionErrorHandler(e as PromiseRejectionEvent)
22
- }
23
- else {
24
- unknownErrorHandler(e)
25
- }
26
- }
27
- catch (error) {
28
- unknownErrorHandler(error)
29
- }
30
- }
package/src/extension.ts DELETED
@@ -1,12 +0,0 @@
1
- import { defineExtension } from '@ohbug/core'
2
-
3
- import { handleCapture } from './capture'
4
- import { handleDestroy } from './destroy'
5
-
6
- export const extension = defineExtension({
7
- name: 'OhbugBrowser',
8
- setup: () => {
9
- handleCapture()
10
- handleDestroy()
11
- },
12
- })
@@ -1,26 +0,0 @@
1
- import { getOhbugObject } from '@ohbug/utils'
2
- import type { OhbugBaseDetail } from '@ohbug/types'
3
- import { EventTypes } from '@ohbug/core'
4
-
5
- export interface AjaxErrorDetail extends OhbugBaseDetail {
6
- req: {
7
- url: string
8
- method: string
9
- data: string | {}
10
- }
11
- res: {
12
- response: string
13
- status: number
14
- statusText: string
15
- }
16
- }
17
-
18
- export function ajaxErrorHandler(detail: AjaxErrorDetail) {
19
- const { client } = getOhbugObject<Window>()
20
- const event = client.createEvent<AjaxErrorDetail>({
21
- category: 'error',
22
- type: EventTypes.AJAX_ERROR,
23
- detail,
24
- })
25
- client.notify(event)
26
- }