Skip to content

Commit 5aecc52

Browse files
authored
Merge pull request #111 from codex-team/nuxt-support
feat: nuxt, captureError method, perevent multiple sending
2 parents 0d2714a + 8ebc66c commit 5aecc52

File tree

13 files changed

+127
-26
lines changed

13 files changed

+127
-26
lines changed

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package.json

example/index.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,9 +223,10 @@ <h2>Test Vue integration: &lt;test-component&gt;</h2>
223223
})
224224
</script>
225225
</section>
226-
<script src="assets/hawk.js"></script>
227226
<script src="sample-errors.js"></script>
228-
<script>
227+
<script type="module">
228+
import HawkCatcher from '../src';
229+
229230
window.hawk = new HawkCatcher({
230231
token: 'eyJpbnRlZ3JhdGlvbklkIjoiNWU5OTE1MzItZTdiYy00ZjA0LTliY2UtYmIzZmE5ZTUwMTg3Iiwic2VjcmV0IjoiMTBlMTA4MjQtZTcyNC00YWFkLTkwMDQtMzExYTU1OWMzZTIxIn0=',
231232
// collectorEndpoint: 'ws://localhost:3000/ws',

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@hawk.so/javascript",
3-
"version": "3.0.10",
3+
"version": "3.1.0",
44
"description": "JavaScript errors tracking for Hawk.so",
55
"files": [
66
"dist"

src/catcher.ts

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import Socket from './modules/socket';
22
import Sanitizer from './modules/sanitizer';
3-
import log from './modules/logger';
3+
import log from './utils/log';
44
import StackParser from './modules/stackParser';
55
import type { CatcherMessage, HawkInitialSettings } from '@/types';
66
import { VueIntegration } from './integrations/vue';
7-
import { generateRandomId } from './utils';
7+
import { id } from './utils/id';
88
import type {
99
AffectedUser,
1010
EventContext,
@@ -15,6 +15,7 @@ import type {
1515
import type { JavaScriptCatcherIntegrations } from './types/integrations';
1616
import { EventRejectedError } from './errors';
1717
import type { HawkJavaScriptEvent } from './types';
18+
import { isErrorProcessed, markErrorAsProcessed } from './utils/event';
1819

1920
/**
2021
* Allow to use global VERSION, that will be overwritten by Webpack
@@ -153,7 +154,7 @@ export default class Catcher {
153154
if (storedId) {
154155
userId = storedId;
155156
} else {
156-
userId = generateRandomId();
157+
userId = id();
157158
localStorage.setItem(LOCAL_STORAGE_KEY, userId);
158159
}
159160

@@ -182,6 +183,18 @@ export default class Catcher {
182183
void this.formatAndSend(message, undefined, context);
183184
}
184185

186+
/**
187+
* Method for Frameworks SDK using own error handlers.
188+
* Allows to send errors to Hawk with additional Frameworks data (addons)
189+
*
190+
* @param error - error to send
191+
* @param [addons] - framework-specific data, can be undefined
192+
*/
193+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
194+
public captureError(error: Error | string, addons?: JavaScriptCatcherIntegrations): void {
195+
void this.formatAndSend(error, addons);
196+
}
197+
185198
/**
186199
* Add error handing to the passed Vue app
187200
*
@@ -245,13 +258,24 @@ export default class Catcher {
245258
context?: EventContext
246259
): Promise<void> {
247260
try {
261+
const isAlreadySentError = isErrorProcessed(error);
262+
263+
if (isAlreadySentError) {
264+
/**
265+
* @todo add debug build and log this case
266+
*/
267+
return;
268+
} else {
269+
markErrorAsProcessed(error);
270+
}
271+
248272
const errorFormatted = await this.prepareErrorFormatted(error, context);
249273

250274
/**
251275
* If this event caught by integration (Vue or other), it can pass extra addons
252276
*/
253277
if (integrationAddons) {
254-
this.appendIntegrationAddons(errorFormatted, integrationAddons);
278+
this.appendIntegrationAddons(errorFormatted, Sanitizer.sanitize(integrationAddons));
255279
}
256280

257281
this.sendErrorFormatted(errorFormatted);
@@ -263,7 +287,7 @@ export default class Catcher {
263287
return;
264288
}
265289

266-
log('Internal error ლ(´ڡ`ლ)', 'error', e);
290+
log('Unable to send error. Seems like it is Hawk internal bug. Please, report it here: https://github.com/codex-team/hawk.javascript/issues/new', 'warn', e);
267291
}
268292
}
269293

src/integrations/vue.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import Sanitizer from './../modules/sanitizer';
2-
import type { VueIntegrationAddons } from '@hawk.so/types';
1+
import type { JsonNode, VueIntegrationAddons } from '@hawk.so/types';
32

43
interface VueIntegrationOptions {
54
/**
@@ -102,7 +101,7 @@ export class VueIntegration {
102101
* Fill props
103102
*/
104103
if (vm.$options && vm.$options.propsData) {
105-
addons.props = Sanitizer.sanitize(vm.$options.propsData);
104+
addons.props = vm.$options.propsData;
106105
}
107106

108107
/**
@@ -112,7 +111,7 @@ export class VueIntegration {
112111
addons.data = {};
113112

114113
Object.entries(vm._data).forEach(([key, value]) => {
115-
addons.data![key] = Sanitizer.sanitize(value);
114+
addons.data![key] = value as JsonNode;
116115
});
117116
}
118117

@@ -124,7 +123,7 @@ export class VueIntegration {
124123

125124
Object.entries(vm._computedWatchers).forEach(([key, watcher]) => {
126125
// eslint-disable-next-line @typescript-eslint/no-explicit-any
127-
addons.computed![key] = Sanitizer.sanitize((watcher as {[key: string]: any}).value);
126+
addons.computed![key] = (watcher as {[key: string]: any}).value;
128127
});
129128
}
130129

src/modules/fetchTimer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import log from './logger';
1+
import log from '../utils/log';
22

33
/**
44
* Sends AJAX request and wait for some time.

src/modules/socket.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import log from './logger';
1+
import log from '../utils/log';
22
import type { CatcherMessage } from '@/types';
33

44
/**

src/modules/stackParser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { StackFrame } from 'error-stack-parser';
22
import ErrorStackParser from 'error-stack-parser';
33
import type { BacktraceFrame, SourceCodeLine } from '@hawk.so/types';
4-
import log from './logger';
4+
import log from '../utils/log';
55
import fetchTimer from './fetchTimer';
66

77
/**

src/types/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
import type { CatcherMessage } from './catcher-message';
22
import type { HawkInitialSettings } from './hawk-initial-settings';
33
import type { HawkJavaScriptEvent } from './event';
4+
import type { VueIntegrationData, NuxtIntegrationData, NuxtIntegrationAddons, JavaScriptCatcherIntegrations } from './integrations';
45

56
export type {
67
CatcherMessage,
78
HawkInitialSettings,
8-
HawkJavaScriptEvent
9+
HawkJavaScriptEvent,
10+
VueIntegrationData,
11+
NuxtIntegrationData,
12+
NuxtIntegrationAddons,
13+
JavaScriptCatcherIntegrations
914
};

src/types/integrations.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,36 @@ export type VueIntegrationData = {
77
vue: VueIntegrationAddons;
88
};
99

10+
/**
11+
* Useful info extracted from Nuxt app
12+
*/
13+
export type NuxtIntegrationAddons = {
14+
'Component': string | null;
15+
'Route': {
16+
path: string;
17+
fullPath: string;
18+
name?: string;
19+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
20+
redirectedFrom?: string | Record<string, any>;
21+
},
22+
'Props': {
23+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
24+
[key: string]: any;
25+
},
26+
'Source': string;
27+
};
28+
29+
/**
30+
* The Nuxt integration will append this data to the addons
31+
*/
32+
export type NuxtIntegrationData = {
33+
nuxt: NuxtIntegrationAddons;
34+
};
35+
1036
/**
1137
* Union Type for available integrations
1238
*/
1339
export type JavaScriptCatcherIntegrations =
1440
| VueIntegrationData
41+
| NuxtIntegrationData
1542
;

0 commit comments

Comments
 (0)