@defender-dev/sdk 0.1.0
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.
- package/dist/index.js +5656 -0
- package/dist/index.js.map +1 -0
- package/dist/src/__tests__/breadcrumbs.test.d.ts +1 -0
- package/dist/src/__tests__/browser-contract.test.d.ts +1 -0
- package/dist/src/__tests__/build.test.d.ts +1 -0
- package/dist/src/__tests__/config.test.d.ts +1 -0
- package/dist/src/__tests__/console.test.d.ts +1 -0
- package/dist/src/__tests__/contract.test.d.ts +1 -0
- package/dist/src/__tests__/core.test.d.ts +1 -0
- package/dist/src/__tests__/index.test.d.ts +1 -0
- package/dist/src/__tests__/network.test.d.ts +1 -0
- package/dist/src/__tests__/replay.test.d.ts +1 -0
- package/dist/src/__tests__/screenshots.test.d.ts +1 -0
- package/dist/src/__tests__/transport.test.d.ts +1 -0
- package/dist/src/__tests__/user.test.d.ts +1 -0
- package/dist/src/__tests__/vite-plugin.test.d.ts +1 -0
- package/dist/src/__tests__/vue.test.d.ts +1 -0
- package/dist/src/breadcrumbs.d.ts +4 -0
- package/dist/src/config.d.ts +39 -0
- package/dist/src/console.d.ts +2 -0
- package/dist/src/core.d.ts +16 -0
- package/dist/src/index.d.ts +15 -0
- package/dist/src/network.d.ts +4 -0
- package/dist/src/replay.d.ts +19 -0
- package/dist/src/screenshots.d.ts +18 -0
- package/dist/src/session.d.ts +3 -0
- package/dist/src/transport.d.ts +8 -0
- package/dist/src/vue.d.ts +9 -0
- package/dist/vite-plugin/index.d.ts +23 -0
- package/dist/vite-plugin.js +69 -0
- package/dist/vite-plugin.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface SdkConfig {
|
|
2
|
+
endpoint: string;
|
|
3
|
+
apiKey: string;
|
|
4
|
+
release: string;
|
|
5
|
+
maxBreadcrumbs: number;
|
|
6
|
+
breadcrumbMaxAge: number;
|
|
7
|
+
flushInterval: number;
|
|
8
|
+
maxBatchSize: number;
|
|
9
|
+
debug: boolean;
|
|
10
|
+
replayEnabled: boolean;
|
|
11
|
+
replayMaxEvents: number;
|
|
12
|
+
replayScreenshotEnabled: boolean;
|
|
13
|
+
replayScreenshotMaxCount: number;
|
|
14
|
+
replayScreenshotMaxBytes: number;
|
|
15
|
+
}
|
|
16
|
+
export interface ReplayScreenshotOptions {
|
|
17
|
+
enabled?: boolean;
|
|
18
|
+
maxCount?: number;
|
|
19
|
+
maxBytes?: number;
|
|
20
|
+
}
|
|
21
|
+
export interface ReplayInitOptions {
|
|
22
|
+
enabled?: boolean;
|
|
23
|
+
maxEvents?: number;
|
|
24
|
+
screenshots?: ReplayScreenshotOptions;
|
|
25
|
+
}
|
|
26
|
+
export interface SdkInitOptions {
|
|
27
|
+
apiKey: string;
|
|
28
|
+
endpoint?: string;
|
|
29
|
+
release?: string;
|
|
30
|
+
maxBreadcrumbs?: number;
|
|
31
|
+
breadcrumbMaxAge?: number;
|
|
32
|
+
flushInterval?: number;
|
|
33
|
+
maxBatchSize?: number;
|
|
34
|
+
debug?: boolean;
|
|
35
|
+
replay?: ReplayInitOptions;
|
|
36
|
+
}
|
|
37
|
+
export declare function loadConfig(options: SdkInitOptions): void;
|
|
38
|
+
export declare function getConfig(): SdkConfig;
|
|
39
|
+
export declare function resetConfig(): void;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ErrorEventPayload, Breadcrumb } from '@defender/shared';
|
|
2
|
+
interface UserIdentity {
|
|
3
|
+
id: string;
|
|
4
|
+
email?: string;
|
|
5
|
+
account?: {
|
|
6
|
+
id: string;
|
|
7
|
+
name?: string;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export declare function setUser(user: UserIdentity): void;
|
|
11
|
+
export declare function clearUser(): void;
|
|
12
|
+
export declare function buildPayload(errorType: string, errorMessage: string, stack: string, breadcrumb: Breadcrumb): ErrorEventPayload;
|
|
13
|
+
export declare function captureException(input: unknown): void;
|
|
14
|
+
export declare function installGlobalHandlers(): void;
|
|
15
|
+
export declare function uninstallGlobalHandlers(): void;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { SdkInitOptions } from './config';
|
|
2
|
+
import { captureException, setUser, clearUser } from './core';
|
|
3
|
+
export { defenderVuePlugin } from './vue';
|
|
4
|
+
export type { SdkInitOptions } from './config';
|
|
5
|
+
export { captureException, setUser, clearUser };
|
|
6
|
+
export declare function init(options: SdkInitOptions): void;
|
|
7
|
+
export declare function destroy(): void;
|
|
8
|
+
export declare const DefenderSDK: {
|
|
9
|
+
init: typeof init;
|
|
10
|
+
destroy: typeof destroy;
|
|
11
|
+
captureException: typeof captureException;
|
|
12
|
+
setUser: typeof setUser;
|
|
13
|
+
clearUser: typeof clearUser;
|
|
14
|
+
};
|
|
15
|
+
export { DefenderSDK as Defender };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type ReplayTriggerType = 'uncaught_error' | 'capture_exception';
|
|
2
|
+
interface ReplayEvent {
|
|
3
|
+
timestamp: string;
|
|
4
|
+
type: string;
|
|
5
|
+
data: Record<string, unknown>;
|
|
6
|
+
}
|
|
7
|
+
interface ReplayUploadInput {
|
|
8
|
+
triggerType: ReplayTriggerType;
|
|
9
|
+
errorType: string;
|
|
10
|
+
errorMessage: string;
|
|
11
|
+
eventId?: string;
|
|
12
|
+
errorGroupId?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function startReplayCapture(): void;
|
|
15
|
+
export declare function stopReplayCapture(): void;
|
|
16
|
+
export declare function uploadReplayForTrigger(input: ReplayUploadInput): Promise<void>;
|
|
17
|
+
export declare function _resetReplayState(): void;
|
|
18
|
+
export declare function _getReplayBuffer(): ReplayEvent[];
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface FocusRect {
|
|
2
|
+
x: number;
|
|
3
|
+
y: number;
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
}
|
|
7
|
+
export interface ReplayScreenshotArtifact {
|
|
8
|
+
kind: 'crash_viewport' | 'last_interaction_focus';
|
|
9
|
+
captured_at: string;
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
content_type: 'image/webp';
|
|
13
|
+
data_base64: string;
|
|
14
|
+
}
|
|
15
|
+
export interface CaptureReplayScreenshotOptions {
|
|
16
|
+
focusRect?: FocusRect;
|
|
17
|
+
}
|
|
18
|
+
export declare function captureReplayScreenshots(options?: CaptureReplayScreenshotOptions): Promise<ReplayScreenshotArtifact[]>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ErrorEventPayload } from '@defender/shared';
|
|
2
|
+
import { ReplayTriggerType } from './replay';
|
|
3
|
+
export declare function enqueueEvent(event: ErrorEventPayload, replayTrigger?: ReplayTriggerType): void;
|
|
4
|
+
export declare function flushEvents(): Promise<void>;
|
|
5
|
+
export declare function startTransport(): void;
|
|
6
|
+
export declare function stopTransport(): void;
|
|
7
|
+
export declare function getQueueLength(): number;
|
|
8
|
+
export declare function _resetQueue(): void;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface SourceMapPluginOptions {
|
|
2
|
+
endpoint: string;
|
|
3
|
+
apiKey: string;
|
|
4
|
+
release?: string;
|
|
5
|
+
}
|
|
6
|
+
interface BundleAsset {
|
|
7
|
+
type: string;
|
|
8
|
+
source?: string;
|
|
9
|
+
fileName: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function defenderSourceMapPlugin(options: SourceMapPluginOptions): {
|
|
12
|
+
name: string;
|
|
13
|
+
apply: "build";
|
|
14
|
+
enforce: "post";
|
|
15
|
+
config(): {
|
|
16
|
+
build: {
|
|
17
|
+
sourcemap: "hidden";
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
generateBundle(_outputOptions: unknown, bundle: Record<string, BundleAsset>): void;
|
|
21
|
+
closeBundle(): Promise<void>;
|
|
22
|
+
};
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
function f(o) {
|
|
2
|
+
const n = [];
|
|
3
|
+
return {
|
|
4
|
+
name: "defender-source-map",
|
|
5
|
+
apply: "build",
|
|
6
|
+
enforce: "post",
|
|
7
|
+
config() {
|
|
8
|
+
return {
|
|
9
|
+
build: {
|
|
10
|
+
sourcemap: "hidden"
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
},
|
|
14
|
+
generateBundle(a, e) {
|
|
15
|
+
const t = Object.keys(e).filter(
|
|
16
|
+
(r) => r.endsWith(".map")
|
|
17
|
+
);
|
|
18
|
+
for (const r of t) {
|
|
19
|
+
const s = e[r], c = typeof s.source == "string" ? s.source : String(s.source || "");
|
|
20
|
+
n.push({
|
|
21
|
+
file_path: i(s.fileName),
|
|
22
|
+
source_map: c
|
|
23
|
+
}), delete e[r];
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
async closeBundle() {
|
|
27
|
+
if (n.length === 0) return;
|
|
28
|
+
const a = o.release || p(n);
|
|
29
|
+
for (const e of n)
|
|
30
|
+
try {
|
|
31
|
+
const t = new FormData();
|
|
32
|
+
t.append("release", a), t.append("file", new Blob([e.source_map], { type: "application/json" }), e.file_path + ".map");
|
|
33
|
+
const r = await fetch(
|
|
34
|
+
`${o.endpoint}/api/v1/sourcemaps`,
|
|
35
|
+
{
|
|
36
|
+
method: "POST",
|
|
37
|
+
headers: {
|
|
38
|
+
"X-API-Key": o.apiKey
|
|
39
|
+
},
|
|
40
|
+
body: t
|
|
41
|
+
}
|
|
42
|
+
);
|
|
43
|
+
r.ok || console.warn(
|
|
44
|
+
`[defender] Source map upload failed for ${e.file_path}: ${r.status} ${r.statusText}`
|
|
45
|
+
);
|
|
46
|
+
} catch (t) {
|
|
47
|
+
console.warn(
|
|
48
|
+
`[defender] Source map upload failed for ${e.file_path}: ${t instanceof Error ? t.message : String(t)}`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function p(o) {
|
|
55
|
+
const n = o.map((e) => e.file_path).sort().join("|");
|
|
56
|
+
let a = 0;
|
|
57
|
+
for (let e = 0; e < n.length; e++) {
|
|
58
|
+
const t = n.charCodeAt(e);
|
|
59
|
+
a = (a << 5) - a + t | 0;
|
|
60
|
+
}
|
|
61
|
+
return Math.abs(a).toString(36);
|
|
62
|
+
}
|
|
63
|
+
function i(o) {
|
|
64
|
+
return o.endsWith(".map") ? o.slice(0, -4) : o;
|
|
65
|
+
}
|
|
66
|
+
export {
|
|
67
|
+
f as defenderSourceMapPlugin
|
|
68
|
+
};
|
|
69
|
+
//# sourceMappingURL=vite-plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vite-plugin.js","sources":["../vite-plugin/index.ts"],"sourcesContent":["export interface SourceMapPluginOptions {\n endpoint: string;\n apiKey: string;\n release?: string;\n}\n\ninterface BundleAsset {\n type: string;\n source?: string;\n fileName: string;\n}\n\ninterface CollectedMap {\n file_path: string;\n source_map: string;\n}\n\nexport function defenderSourceMapPlugin(options: SourceMapPluginOptions) {\n const collectedMaps: CollectedMap[] = [];\n\n return {\n name: 'defender-source-map',\n apply: 'build' as const,\n enforce: 'post' as const,\n\n config() {\n return {\n build: {\n sourcemap: 'hidden' as const,\n },\n };\n },\n\n generateBundle(\n _outputOptions: unknown,\n bundle: Record<string, BundleAsset>\n ): void {\n const mapKeys = Object.keys(bundle).filter((key) =>\n key.endsWith('.map')\n );\n\n for (const key of mapKeys) {\n const asset = bundle[key];\n const source =\n typeof asset.source === 'string'\n ? asset.source\n : String(asset.source || '');\n\n collectedMaps.push({\n file_path: stripMapSuffix(asset.fileName),\n source_map: source,\n });\n\n // Remove .map file from output so it is not deployed\n delete bundle[key];\n }\n },\n\n async closeBundle(): Promise<void> {\n if (collectedMaps.length === 0) return;\n\n const release = options.release || generateVersion(collectedMaps);\n\n for (const map of collectedMaps) {\n try {\n const formData = new FormData();\n formData.append('release', release);\n formData.append('file', new Blob([map.source_map], { type: 'application/json' }), map.file_path + '.map');\n\n const response = await fetch(\n `${options.endpoint}/api/v1/sourcemaps`,\n {\n method: 'POST',\n headers: {\n 'X-API-Key': options.apiKey,\n },\n body: formData,\n }\n );\n\n if (!response.ok) {\n console.warn(\n `[defender] Source map upload failed for ${map.file_path}: ${response.status} ${response.statusText}`\n );\n }\n } catch (error) {\n console.warn(\n `[defender] Source map upload failed for ${map.file_path}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n },\n };\n}\n\nfunction generateVersion(files: CollectedMap[]): string {\n const input = files.map((f) => f.file_path).sort().join('|');\n let hash = 0;\n for (let i = 0; i < input.length; i++) {\n const char = input.charCodeAt(i);\n hash = ((hash << 5) - hash + char) | 0;\n }\n return Math.abs(hash).toString(36);\n}\n\nfunction stripMapSuffix(filePath: string): string {\n return filePath.endsWith('.map') ? filePath.slice(0, -4) : filePath;\n}\n"],"names":["defenderSourceMapPlugin","options","collectedMaps","_outputOptions","bundle","mapKeys","key","asset","source","stripMapSuffix","release","generateVersion","map","formData","response","error","files","input","f","hash","i","char","filePath"],"mappings":"AAiBO,SAASA,EAAwBC,GAAiC;AACvE,QAAMC,IAAgC,CAAA;AAEtC,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SAAS;AAAA,IAET,SAAS;AACP,aAAO;AAAA,QACL,OAAO;AAAA,UACL,WAAW;AAAA,QAAA;AAAA,MACb;AAAA,IAEJ;AAAA,IAEA,eACEC,GACAC,GACM;AACN,YAAMC,IAAU,OAAO,KAAKD,CAAM,EAAE;AAAA,QAAO,CAACE,MAC1CA,EAAI,SAAS,MAAM;AAAA,MAAA;AAGrB,iBAAWA,KAAOD,GAAS;AACzB,cAAME,IAAQH,EAAOE,CAAG,GAClBE,IACJ,OAAOD,EAAM,UAAW,WACpBA,EAAM,SACN,OAAOA,EAAM,UAAU,EAAE;AAE/B,QAAAL,EAAc,KAAK;AAAA,UACjB,WAAWO,EAAeF,EAAM,QAAQ;AAAA,UACxC,YAAYC;AAAA,QAAA,CACb,GAGD,OAAOJ,EAAOE,CAAG;AAAA,MACnB;AAAA,IACF;AAAA,IAEA,MAAM,cAA6B;AACjC,UAAIJ,EAAc,WAAW,EAAG;AAEhC,YAAMQ,IAAUT,EAAQ,WAAWU,EAAgBT,CAAa;AAEhE,iBAAWU,KAAOV;AAChB,YAAI;AACF,gBAAMW,IAAW,IAAI,SAAA;AACrB,UAAAA,EAAS,OAAO,WAAWH,CAAO,GAClCG,EAAS,OAAO,QAAQ,IAAI,KAAK,CAACD,EAAI,UAAU,GAAG,EAAE,MAAM,mBAAA,CAAoB,GAAGA,EAAI,YAAY,MAAM;AAExG,gBAAME,IAAW,MAAM;AAAA,YACrB,GAAGb,EAAQ,QAAQ;AAAA,YACnB;AAAA,cACE,QAAQ;AAAA,cACR,SAAS;AAAA,gBACP,aAAaA,EAAQ;AAAA,cAAA;AAAA,cAEvB,MAAMY;AAAA,YAAA;AAAA,UACR;AAGF,UAAKC,EAAS,MACZ,QAAQ;AAAA,YACN,2CAA2CF,EAAI,SAAS,KAAKE,EAAS,MAAM,IAAIA,EAAS,UAAU;AAAA,UAAA;AAAA,QAGzG,SAASC,GAAO;AACd,kBAAQ;AAAA,YACN,2CAA2CH,EAAI,SAAS,KAAKG,aAAiB,QAAQA,EAAM,UAAU,OAAOA,CAAK,CAAC;AAAA,UAAA;AAAA,QAEvH;AAAA,IAEJ;AAAA,EAAA;AAEJ;AAEA,SAASJ,EAAgBK,GAA+B;AACtD,QAAMC,IAAQD,EAAM,IAAI,CAACE,MAAMA,EAAE,SAAS,EAAE,OAAO,KAAK,GAAG;AAC3D,MAAIC,IAAO;AACX,WAASC,IAAI,GAAGA,IAAIH,EAAM,QAAQG,KAAK;AACrC,UAAMC,IAAOJ,EAAM,WAAWG,CAAC;AAC/B,IAAAD,KAASA,KAAQ,KAAKA,IAAOE,IAAQ;AAAA,EACvC;AACA,SAAO,KAAK,IAAIF,CAAI,EAAE,SAAS,EAAE;AACnC;AAEA,SAASV,EAAea,GAA0B;AAChD,SAAOA,EAAS,SAAS,MAAM,IAAIA,EAAS,MAAM,GAAG,EAAE,IAAIA;AAC7D;"}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@defender-dev/sdk",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Browser error monitoring SDK for Defender",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/opslane/defender.git",
|
|
10
|
+
"directory": "packages/sdk"
|
|
11
|
+
},
|
|
12
|
+
"main": "dist/index.js",
|
|
13
|
+
"module": "dist/index.js",
|
|
14
|
+
"types": "dist/index.d.ts",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"import": "./dist/index.js",
|
|
18
|
+
"types": "./dist/index.d.ts"
|
|
19
|
+
},
|
|
20
|
+
"./vite-plugin": {
|
|
21
|
+
"import": "./dist/vite-plugin.js",
|
|
22
|
+
"types": "./dist/vite-plugin.d.ts"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist"
|
|
27
|
+
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "vite build",
|
|
30
|
+
"test": "vitest run",
|
|
31
|
+
"test:watch": "vitest",
|
|
32
|
+
"prepublishOnly": "vite build"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"html2canvas": "^1.4.1"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@defender/shared": "workspace:*",
|
|
39
|
+
"@playwright/test": "^1.40.0",
|
|
40
|
+
"jsdom": "^28.0.0",
|
|
41
|
+
"typescript": "^5.4.0",
|
|
42
|
+
"vite": "^6.0.0",
|
|
43
|
+
"vite-plugin-dts": "^4.0.0",
|
|
44
|
+
"vitest": "^3.0.0"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"vite": "^6.0.0",
|
|
48
|
+
"vue": "^3.0.0"
|
|
49
|
+
},
|
|
50
|
+
"peerDependenciesMeta": {
|
|
51
|
+
"vue": {
|
|
52
|
+
"optional": true
|
|
53
|
+
},
|
|
54
|
+
"vite": {
|
|
55
|
+
"optional": true
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|