@workleap/logrocket 1.0.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/LICENSE +201 -0
  3. package/README.md +13 -0
  4. package/dist/HasExecutedGuard.d.ts +6 -0
  5. package/dist/HasExecutedGuard.js +21 -0
  6. package/dist/HasExecutedGuard.js.map +1 -0
  7. package/dist/applyTransformers.d.ts +9 -0
  8. package/dist/applyTransformers.js +10 -0
  9. package/dist/applyTransformers.js.map +1 -0
  10. package/dist/assertions.d.ts +1 -0
  11. package/dist/assertions.js +9 -0
  12. package/dist/assertions.js.map +1 -0
  13. package/dist/createDefaultUserTraits.d.ts +109 -0
  14. package/dist/createDefaultUserTraits.js +102 -0
  15. package/dist/createDefaultUserTraits.js.map +1 -0
  16. package/dist/createRequestSanitizer.d.ts +3 -0
  17. package/dist/createRequestSanitizer.js +18 -0
  18. package/dist/createRequestSanitizer.js.map +1 -0
  19. package/dist/createResponseSanitizer.d.ts +3 -0
  20. package/dist/createResponseSanitizer.js +15 -0
  21. package/dist/createResponseSanitizer.js.map +1 -0
  22. package/dist/createUrlSanitizer.d.ts +1 -0
  23. package/dist/createUrlSanitizer.js +15 -0
  24. package/dist/createUrlSanitizer.js.map +1 -0
  25. package/dist/index.d.ts +4 -0
  26. package/dist/index.js +14 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/logRocketTypes.d.ts +24 -0
  29. package/dist/logRocketTypes.js +7 -0
  30. package/dist/logRocketTypes.js.map +1 -0
  31. package/dist/registerLogRocketInstrumentation.d.ts +20 -0
  32. package/dist/registerLogRocketInstrumentation.js +146 -0
  33. package/dist/registerLogRocketInstrumentation.js.map +1 -0
  34. package/package.json +55 -0
  35. package/src/HasExecutedGuard.ts +19 -0
  36. package/src/applyTransformers.ts +17 -0
  37. package/src/assertions.ts +3 -0
  38. package/src/createDefaultUserTraits.ts +151 -0
  39. package/src/createRequestSanitizer.ts +19 -0
  40. package/src/createResponseSanitizer.ts +15 -0
  41. package/src/createUrlSanitizer.ts +11 -0
  42. package/src/index.ts +5 -0
  43. package/src/logRocketTypes.ts +30 -0
  44. package/src/registerLogRocketInstrumentation.ts +152 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["webpack://@workleap/logrocket/./src/index.ts"],"sourcesContent":["export type { LogRocketSdkOptionsTransformer } from \"./applyTransformers.ts\";\nexport { createDefaultUserTraits, type LogRocketIdentification, type LogRocketUserTraits } from \"./createDefaultUserTraits.ts\";\nexport type * from \"./logRocketTypes.ts\";\nexport { registerLogRocketInstrumentation } from \"./registerLogRocketInstrumentation.ts\";\n\n"],"names":["createDefaultUserTraits","registerLogRocketInstrumentation"],"mappings":";;;;;;;;AAC+H;AAEtC"}
@@ -0,0 +1,24 @@
1
+ import type LogRocket from "logrocket";
2
+ export type LogRocketSdkOptions = NonNullable<Parameters<(typeof LogRocket)["init"]>[1]>;
3
+ export interface LogRocketRequest {
4
+ reqId: string;
5
+ url: string;
6
+ headers: {
7
+ [key: string]: string | null | undefined;
8
+ };
9
+ body?: string;
10
+ method: string;
11
+ referrer?: string;
12
+ mode?: string;
13
+ credentials?: string;
14
+ }
15
+ export interface LogRocketResponse {
16
+ reqId: string;
17
+ status?: number;
18
+ headers: {
19
+ [key: string]: string | null | undefined;
20
+ };
21
+ body?: string;
22
+ method: string;
23
+ url?: string;
24
+ }
@@ -0,0 +1,7 @@
1
+
2
+ ;// CONCATENATED MODULE: ./src/logRocketTypes.ts
3
+ // Typings are not exposed by the library, copied from the LogRocket package.
4
+
5
+
6
+
7
+ //# sourceMappingURL=logRocketTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logRocketTypes.js","sources":["webpack://@workleap/logrocket/./src/logRocketTypes.ts"],"sourcesContent":["import type LogRocket from \"logrocket\";\n\n// Typings are not exposed by the library.\nexport type LogRocketSdkOptions = NonNullable<Parameters<(typeof LogRocket)[\"init\"]>[1]>;\n\n// Typings are not exposed by the library, copied from the LogRocket package.\nexport interface LogRocketRequest {\n reqId: string;\n url: string;\n headers: {\n [key: string]: string | null | undefined;\n };\n body?: string;\n method: string;\n referrer?: string;\n mode?: string;\n credentials?: string;\n}\n\n// Typings are not exposed by the library, copied from the LogRocket package.\nexport interface LogRocketResponse {\n reqId: string;\n status?: number;\n headers: {\n [key: string]: string | null | undefined;\n };\n body?: string;\n method: string;\n url?: string;\n}\n"],"names":[],"mappings":";;AAmBA,6EAA6E;AAU5E"}
@@ -0,0 +1,20 @@
1
+ import { type LogRocketSdkOptionsTransformer } from "./applyTransformers.ts";
2
+ import type { LogRocketSdkOptions } from "./logRocketTypes.ts";
3
+ export declare const IsRegisteredFunctionName = "__WLP_LOGROCKET_INSTRUMENTATION_IS_REGISTERED__";
4
+ export declare const RegisterGetSessionUrlFunctionName = "__WLP_LOGROCKET_INSTRUMENTATION_REGISTER_GET_SESSION_URL_LISTENER__";
5
+ /**
6
+ * @see https://workleap.github.io/wl-telemetry
7
+ */
8
+ export interface RegisterLogRocketInstrumentationOptions {
9
+ rootHostname?: LogRocketSdkOptions["rootHostname"];
10
+ privateFieldNames?: string[];
11
+ privateQueryParameterNames?: string[];
12
+ verbose?: boolean;
13
+ transformers?: LogRocketSdkOptionsTransformer[];
14
+ }
15
+ export declare function getLogRocketSdkOptions(options: RegisterLogRocketInstrumentationOptions): LogRocketSdkOptions;
16
+ export declare function __resetRegistrationGuard(): void;
17
+ /**
18
+ * @see https://workleap.github.io/wl-telemetry
19
+ */
20
+ export declare function registerLogRocketInstrumentation(appId: string, options?: RegisterLogRocketInstrumentationOptions): void;
@@ -0,0 +1,146 @@
1
+ import { getBootstrappingStore, getTelemetryContext } from "@workleap/telemetry";
2
+ import logrocket from "logrocket";
3
+ import logrocket_fuzzy_search_sanitizer from "logrocket-fuzzy-search-sanitizer";
4
+ import { applyTransformers } from "./applyTransformers.js";
5
+ import { DeviceIdTrait, TelemetryIdTrait } from "./createDefaultUserTraits.js";
6
+ import { createRequestSanitizer } from "./createRequestSanitizer.js";
7
+ import { createResponseSanitizer } from "./createResponseSanitizer.js";
8
+ import { createUrlSanitizer } from "./createUrlSanitizer.js";
9
+ import { HasExecutedGuard } from "./HasExecutedGuard.js";
10
+
11
+ ;// CONCATENATED MODULE: external "@workleap/telemetry"
12
+
13
+ ;// CONCATENATED MODULE: external "logrocket"
14
+
15
+ ;// CONCATENATED MODULE: external "logrocket-fuzzy-search-sanitizer"
16
+
17
+ ;// CONCATENATED MODULE: external "./applyTransformers.js"
18
+
19
+ ;// CONCATENATED MODULE: external "./createDefaultUserTraits.js"
20
+
21
+ ;// CONCATENATED MODULE: external "./createRequestSanitizer.js"
22
+
23
+ ;// CONCATENATED MODULE: external "./createResponseSanitizer.js"
24
+
25
+ ;// CONCATENATED MODULE: external "./createUrlSanitizer.js"
26
+
27
+ ;// CONCATENATED MODULE: external "./HasExecutedGuard.js"
28
+
29
+ ;// CONCATENATED MODULE: ./src/registerLogRocketInstrumentation.ts
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+ const IsRegisteredFunctionName = "__WLP_LOGROCKET_INSTRUMENTATION_IS_REGISTERED__";
40
+ const RegisterGetSessionUrlFunctionName = "__WLP_LOGROCKET_INSTRUMENTATION_REGISTER_GET_SESSION_URL_LISTENER__";
41
+ const DefaultPrivateFieldNames = [
42
+ "email",
43
+ "personalEmail",
44
+ "phoneNumber",
45
+ "password",
46
+ "firstName",
47
+ "lastName",
48
+ "givenName",
49
+ "fullName",
50
+ "gender",
51
+ "timeZone",
52
+ "birthday"
53
+ ];
54
+ const DefaultPrivateQueryParameterNames = [
55
+ "token",
56
+ "email",
57
+ "password"
58
+ ];
59
+ // The function return type is mandatory, otherwise we got an error TS4058.
60
+ function getLogRocketSdkOptions(options) {
61
+ const { rootHostname = "workleap.com", privateFieldNames = [], privateQueryParameterNames = [], verbose = false, transformers = [] } = options;
62
+ const mergedPrivateFieldNames = DefaultPrivateFieldNames.concat(privateFieldNames);
63
+ const mergedPrivateQueryParameterNames = DefaultPrivateQueryParameterNames.concat(privateQueryParameterNames);
64
+ // The "LogrocketFuzzySearch.setup" code is awkward. For now, we prefer to play it safe and call it once here, then forward the sanitize functions
65
+ // to the appropriate factories.
66
+ // No clue why the "setup" method is not available. This package is shady.
67
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
68
+ // @ts-ignore
69
+ const { requestSanitizer: fuzzyRequestSanitizer, responseSanitizer: fuzzyResponseSanitizer } = logrocket_fuzzy_search_sanitizer.setup(mergedPrivateFieldNames);
70
+ const sdkOptions = {
71
+ console: {
72
+ isEnabled: false
73
+ },
74
+ rootHostname,
75
+ dom: {
76
+ textSanitizer: true,
77
+ inputSanitizer: true
78
+ },
79
+ network: {
80
+ requestSanitizer: createRequestSanitizer(fuzzyRequestSanitizer),
81
+ responseSanitizer: createResponseSanitizer(fuzzyResponseSanitizer)
82
+ },
83
+ browser: {
84
+ urlSanitizer: createUrlSanitizer(mergedPrivateQueryParameterNames)
85
+ },
86
+ shouldDebugLog: verbose
87
+ };
88
+ return applyTransformers(sdkOptions, transformers, {
89
+ verbose
90
+ });
91
+ }
92
+ const registrationGuard = new HasExecutedGuard();
93
+ // This function should only be used by tests.
94
+ function __resetRegistrationGuard() {
95
+ registrationGuard.reset();
96
+ }
97
+ /**
98
+ * @see https://workleap.github.io/wl-telemetry
99
+ */ function registerLogRocketInstrumentation(appId, options = {}) {
100
+ const { verbose = false } = options;
101
+ registrationGuard.throw("[logrocket] The LogRocket instrumentation has already been registered. Did you call the \"registerLogRocketInstrumentation\" function twice?");
102
+ const sdkOptions = getLogRocketSdkOptions(options);
103
+ // Session starts anonymously when LogRocket.init() is called.
104
+ logrocket.init(appId, sdkOptions);
105
+ const telemetryContext = getTelemetryContext({
106
+ verbose
107
+ });
108
+ // LogRocket maintains the same session even if the user starts as anonymous and later becomes identified via LogRocket.identify().
109
+ // If LogRocket.identify is called multiple times during a recording, you can search for any of the identified users in the session.
110
+ logrocket.identify(telemetryContext.deviceId, {
111
+ [DeviceIdTrait]: telemetryContext.deviceId,
112
+ [TelemetryIdTrait]: telemetryContext.telemetryId
113
+ });
114
+ if (verbose) {
115
+ logrocket.getSessionURL((url)=>{
116
+ console.log("[logrocket] Session replay URL is now available:", url);
117
+ });
118
+ }
119
+ // Indicates to the host applications that logrocket has been initialized.
120
+ // It's useful in cases where an "add-on", like the platform widgets needs
121
+ // to know whether or not the host application is using LogRocket.
122
+ // While there are ways that the host application could tell to an "add-on" if
123
+ // it's using LogRocket or not, doing it this way is transparent for the consumer,
124
+ // which is great for DX.
125
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
126
+ // @ts-ignore
127
+ globalThis[IsRegisteredFunctionName] = true;
128
+ // While consumers could directly call LogRocket.getSessionURL, by doing it this way,
129
+ // it allow consumers to not take a direct dependency on the "logrocket" package.
130
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
131
+ // @ts-ignore
132
+ globalThis[RegisterGetSessionUrlFunctionName] = (listener)=>{
133
+ logrocket.getSessionURL(listener);
134
+ };
135
+ // Let the other telemetry libraries know that LogRocket instrumentation is ready.
136
+ getBootstrappingStore().dispatch({
137
+ type: "logrocket-ready"
138
+ });
139
+ if (verbose) {
140
+ console.log("[logrocket] LogRocket instrumentation is registered.");
141
+ }
142
+ }
143
+
144
+ export { IsRegisteredFunctionName, RegisterGetSessionUrlFunctionName, __resetRegistrationGuard, getLogRocketSdkOptions, registerLogRocketInstrumentation };
145
+
146
+ //# sourceMappingURL=registerLogRocketInstrumentation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registerLogRocketInstrumentation.js","sources":["webpack://@workleap/logrocket/./src/registerLogRocketInstrumentation.ts"],"sourcesContent":["import { getBootstrappingStore, getTelemetryContext } from \"@workleap/telemetry\";\nimport LogRocket from \"logrocket\";\nimport LogrocketFuzzySanitizer from \"logrocket-fuzzy-search-sanitizer\";\nimport { applyTransformers, type LogRocketSdkOptionsTransformer } from \"./applyTransformers.ts\";\nimport { DeviceIdTrait, TelemetryIdTrait } from \"./createDefaultUserTraits.ts\";\nimport { createRequestSanitizer } from \"./createRequestSanitizer.ts\";\nimport { createResponseSanitizer } from \"./createResponseSanitizer.ts\";\nimport { createUrlSanitizer } from \"./createUrlSanitizer.ts\";\nimport { HasExecutedGuard } from \"./HasExecutedGuard.ts\";\nimport type { LogRocketSdkOptions } from \"./logRocketTypes.ts\";\n\nexport const IsRegisteredFunctionName = \"__WLP_LOGROCKET_INSTRUMENTATION_IS_REGISTERED__\";\nexport const RegisterGetSessionUrlFunctionName = \"__WLP_LOGROCKET_INSTRUMENTATION_REGISTER_GET_SESSION_URL_LISTENER__\";\n\nconst DefaultPrivateFieldNames = [\n \"email\",\n \"personalEmail\",\n \"phoneNumber\",\n \"password\",\n \"firstName\",\n \"lastName\",\n \"givenName\",\n \"fullName\",\n \"gender\",\n \"timeZone\",\n \"birthday\"\n];\n\nconst DefaultPrivateQueryParameterNames = [\n \"token\",\n \"email\",\n \"password\"\n];\n\n/**\n * @see https://workleap.github.io/wl-telemetry\n */\nexport interface RegisterLogRocketInstrumentationOptions {\n // Set to capture traffic from all subdomains under one session: https://docs.logrocket.com/reference/roothostname.\n rootHostname?: LogRocketSdkOptions[\"rootHostname\"];\n privateFieldNames?: string[];\n privateQueryParameterNames?: string[];\n verbose?: boolean;\n transformers?: LogRocketSdkOptionsTransformer[];\n}\n\n// The function return type is mandatory, otherwise we got an error TS4058.\nexport function getLogRocketSdkOptions(options: RegisterLogRocketInstrumentationOptions): LogRocketSdkOptions {\n const {\n rootHostname = \"workleap.com\",\n privateFieldNames = [],\n privateQueryParameterNames = [],\n verbose = false,\n transformers = []\n } = options;\n\n const mergedPrivateFieldNames = DefaultPrivateFieldNames.concat(privateFieldNames);\n const mergedPrivateQueryParameterNames = DefaultPrivateQueryParameterNames.concat(privateQueryParameterNames);\n\n // The \"LogrocketFuzzySearch.setup\" code is awkward. For now, we prefer to play it safe and call it once here, then forward the sanitize functions\n // to the appropriate factories.\n // No clue why the \"setup\" method is not available. This package is shady.\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n const { requestSanitizer: fuzzyRequestSanitizer, responseSanitizer: fuzzyResponseSanitizer } = LogrocketFuzzySanitizer.setup(mergedPrivateFieldNames);\n\n const sdkOptions = {\n console: {\n isEnabled: false\n },\n rootHostname,\n dom: {\n textSanitizer: true,\n inputSanitizer: true\n },\n network: {\n requestSanitizer: createRequestSanitizer(fuzzyRequestSanitizer),\n responseSanitizer: createResponseSanitizer(fuzzyResponseSanitizer)\n },\n browser: {\n urlSanitizer: createUrlSanitizer(mergedPrivateQueryParameterNames)\n },\n shouldDebugLog: verbose\n } satisfies LogRocketSdkOptions;\n\n return applyTransformers(sdkOptions, transformers, {\n verbose\n });\n}\n\nconst registrationGuard = new HasExecutedGuard();\n\n// This function should only be used by tests.\nexport function __resetRegistrationGuard() {\n registrationGuard.reset();\n}\n\n/**\n * @see https://workleap.github.io/wl-telemetry\n */\nexport function registerLogRocketInstrumentation(appId: string, options: RegisterLogRocketInstrumentationOptions = {}) {\n const {\n verbose = false\n } = options;\n\n registrationGuard.throw(\"[logrocket] The LogRocket instrumentation has already been registered. Did you call the \\\"registerLogRocketInstrumentation\\\" function twice?\");\n\n const sdkOptions = getLogRocketSdkOptions(options);\n\n // Session starts anonymously when LogRocket.init() is called.\n LogRocket.init(appId, sdkOptions);\n\n const telemetryContext = getTelemetryContext({ verbose });\n\n // LogRocket maintains the same session even if the user starts as anonymous and later becomes identified via LogRocket.identify().\n // If LogRocket.identify is called multiple times during a recording, you can search for any of the identified users in the session.\n LogRocket.identify(telemetryContext.deviceId, {\n [DeviceIdTrait]: telemetryContext.deviceId,\n [TelemetryIdTrait]: telemetryContext.telemetryId\n });\n\n if (verbose) {\n LogRocket.getSessionURL(url => {\n console.log(\"[logrocket] Session replay URL is now available:\", url);\n });\n }\n\n // Indicates to the host applications that logrocket has been initialized.\n // It's useful in cases where an \"add-on\", like the platform widgets needs\n // to know whether or not the host application is using LogRocket.\n // While there are ways that the host application could tell to an \"add-on\" if\n // it's using LogRocket or not, doing it this way is transparent for the consumer,\n // which is great for DX.\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n globalThis[IsRegisteredFunctionName] = true;\n\n // While consumers could directly call LogRocket.getSessionURL, by doing it this way,\n // it allow consumers to not take a direct dependency on the \"logrocket\" package.\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n globalThis[RegisterGetSessionUrlFunctionName] = listener => {\n LogRocket.getSessionURL(listener);\n };\n\n // Let the other telemetry libraries know that LogRocket instrumentation is ready.\n getBootstrappingStore().dispatch({ type: \"logrocket-ready\" });\n\n if (verbose) {\n console.log(\"[logrocket] LogRocket instrumentation is registered.\");\n }\n}\n"],"names":["getBootstrappingStore","getTelemetryContext","LogRocket","LogrocketFuzzySanitizer","applyTransformers","DeviceIdTrait","TelemetryIdTrait","createRequestSanitizer","createResponseSanitizer","createUrlSanitizer","HasExecutedGuard","IsRegisteredFunctionName","RegisterGetSessionUrlFunctionName","DefaultPrivateFieldNames","DefaultPrivateQueryParameterNames","getLogRocketSdkOptions","options","rootHostname","privateFieldNames","privateQueryParameterNames","verbose","transformers","mergedPrivateFieldNames","mergedPrivateQueryParameterNames","fuzzyRequestSanitizer","fuzzyResponseSanitizer","sdkOptions","registrationGuard","__resetRegistrationGuard","registerLogRocketInstrumentation","appId","telemetryContext","url","console","globalThis","listener"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAiF;AAC/C;AACqC;AACyB;AACjB;AACV;AACE;AACV;AACJ;AAGlD,MAAMW,2BAA2B,kDAAkD;AACnF,MAAMC,oCAAoC,sEAAsE;AAEvH,MAAMC,2BAA2B;IAC7B;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACH;AAED,MAAMC,oCAAoC;IACtC;IACA;IACA;CACH;AAcD,2EAA2E;AACpE,SAASC,uBAAuBC,OAAgD;IACnF,MAAM,EACFC,eAAe,cAAc,EAC7BC,oBAAoB,EAAE,EACtBC,6BAA6B,EAAE,EAC/BC,UAAU,KAAK,EACfC,eAAe,EAAE,EACpB,GAAGL;IAEJ,MAAMM,0BAA0BT,yBAAyB,MAAM,CAACK;IAChE,MAAMK,mCAAmCT,kCAAkC,MAAM,CAACK;IAElF,kJAAkJ;IAClJ,gCAAgC;IAChC,0EAA0E;IAC1E,6DAA6D;IAC7D,aAAa;IACb,MAAM,EAAE,kBAAkBK,qBAAqB,EAAE,mBAAmBC,sBAAsB,EAAE,GAAGtB,sCAA6B,CAACmB;IAE7H,MAAMI,aAAa;QACf,SAAS;YACL,WAAW;QACf;QACAT;QACA,KAAK;YACD,eAAe;YACf,gBAAgB;QACpB;QACA,SAAS;YACL,kBAAkBV,sBAAsBA,CAACiB;YACzC,mBAAmBhB,uBAAuBA,CAACiB;QAC/C;QACA,SAAS;YACL,cAAchB,kBAAkBA,CAACc;QACrC;QACA,gBAAgBH;IACpB;IAEA,OAAOhB,iBAAiBA,CAACsB,YAAYL,cAAc;QAC/CD;IACJ;AACJ;AAEA,MAAMO,oBAAoB,IAAIjB,gBAAgBA;AAE9C,8CAA8C;AACvC,SAASkB;IACZD,kBAAkB,KAAK;AAC3B;AAEA;;CAEC,GACM,SAASE,iCAAiCC,KAAa,EAAEd,UAAmD,CAAC,CAAC;IACjH,MAAM,EACFI,UAAU,KAAK,EAClB,GAAGJ;IAEJW,kBAAkB,KAAK,CAAC;IAExB,MAAMD,aAAaX,uBAAuBC;IAE1C,8DAA8D;IAC9Dd,cAAc,CAAC4B,OAAOJ;IAEtB,MAAMK,mBAAmB9B,mBAAmBA,CAAC;QAAEmB;IAAQ;IAEvD,mIAAmI;IACnI,oIAAoI;IACpIlB,kBAAkB,CAAC6B,iBAAiB,QAAQ,EAAE;QAC1C,CAAC1B,aAAaA,CAAC,EAAE0B,iBAAiB,QAAQ;QAC1C,CAACzB,gBAAgBA,CAAC,EAAEyB,iBAAiB,WAAW;IACpD;IAEA,IAAIX,SAAS;QACTlB,uBAAuB,CAAC8B,CAAAA;YACpBC,QAAQ,GAAG,CAAC,oDAAoDD;QACpE;IACJ;IAEA,0EAA0E;IAC1E,0EAA0E;IAC1E,kEAAkE;IAClE,8EAA8E;IAC9E,kFAAkF;IAClF,yBAAyB;IACzB,6DAA6D;IAC7D,aAAa;IACbE,UAAU,CAACvB,yBAAyB,GAAG;IAEvC,qFAAqF;IACrF,iFAAiF;IACjF,6DAA6D;IAC7D,aAAa;IACbuB,UAAU,CAACtB,kCAAkC,GAAGuB,CAAAA;QAC5CjC,uBAAuB,CAACiC;IAC5B;IAEA,kFAAkF;IAClFnC,qBAAqBA,GAAG,QAAQ,CAAC;QAAE,MAAM;IAAkB;IAE3D,IAAIoB,SAAS;QACTa,QAAQ,GAAG,CAAC;IAChB;AACJ"}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@workleap/logrocket",
3
+ "author": "Workleap",
4
+ "version": "1.0.0",
5
+ "description": "A package containing utilities for LogRocket.",
6
+ "license": "Apache-2.0",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/workleap/wl-telemetry.git",
10
+ "directory": "packages/logrocket"
11
+ },
12
+ "type": "module",
13
+ "publishConfig": {
14
+ "access": "public",
15
+ "provenance": true
16
+ },
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/index.d.ts",
20
+ "import": "./dist/index.js",
21
+ "default": "./dist/index.js"
22
+ }
23
+ },
24
+ "files": [
25
+ "src",
26
+ "dist",
27
+ "CHANGELOG.md",
28
+ "README.md"
29
+ ],
30
+ "peerDependencies": {
31
+ "logrocket": "^10.1.0",
32
+ "@workleap/telemetry": "1.0.0"
33
+ },
34
+ "dependencies": {
35
+ "logrocket-fuzzy-search-sanitizer": "0.0.2"
36
+ },
37
+ "devDependencies": {
38
+ "@rsbuild/core": "1.4.6",
39
+ "@rslib/core": "0.10.5",
40
+ "@workleap/eslint-plugin": "3.4.2",
41
+ "@workleap/rslib-configs": "1.0.6",
42
+ "@workleap/typescript-configs": "3.0.4",
43
+ "eslint": "8.57.1",
44
+ "happy-dom": "18.0.1",
45
+ "typescript": "5.8.3",
46
+ "vitest": "3.2.4"
47
+ },
48
+ "sideEffects": false,
49
+ "scripts": {
50
+ "build": "rslib build --config ./rslib.build.ts",
51
+ "eslint": "eslint . --max-warnings=-0 --cache --cache-location node_modules/.cache/eslint",
52
+ "typecheck": "tsc",
53
+ "test": "vitest --config vitest.config.ts --no-watch"
54
+ }
55
+ }
@@ -0,0 +1,19 @@
1
+ export class HasExecutedGuard {
2
+ #hasExecuted: boolean = false;
3
+
4
+ throw(message: string) {
5
+ if (this.#hasExecuted) {
6
+ throw new Error(message);
7
+ }
8
+
9
+ this.#hasExecuted = true;
10
+ }
11
+
12
+ get hasExecuted() {
13
+ return this.#hasExecuted;
14
+ }
15
+
16
+ reset() {
17
+ this.#hasExecuted = false;
18
+ }
19
+ }
@@ -0,0 +1,17 @@
1
+ import type { LogRocketSdkOptions } from "./logRocketTypes.ts";
2
+
3
+ /**
4
+ * @see https://workleap.github.io/wl-telemetry
5
+ */
6
+ export interface LogRocketSdkOptionsTransformerContext {
7
+ verbose: boolean;
8
+ }
9
+
10
+ export type LogRocketSdkOptionsTransformer = (options: LogRocketSdkOptions, context: LogRocketSdkOptionsTransformerContext) => LogRocketSdkOptions;
11
+
12
+ // The function return type is mandatory, otherwise we got an error TS4058.
13
+ export function applyTransformers(options: LogRocketSdkOptions, transformers: LogRocketSdkOptionsTransformer[], context: LogRocketSdkOptionsTransformerContext): LogRocketSdkOptions {
14
+ return transformers.reduce((acc, transformer) => transformer(acc, context), options);
15
+ }
16
+
17
+
@@ -0,0 +1,3 @@
1
+ export function isDefined(value: unknown) {
2
+ return typeof value !== "undefined" && value !== undefined;
3
+ }
@@ -0,0 +1,151 @@
1
+ import { getTelemetryContext } from "@workleap/telemetry";
2
+ import { isDefined } from "./assertions.ts";
3
+
4
+ /**
5
+ * @see https://workleap.github.io/wl-telemetry
6
+ */
7
+ export interface LogRocketIdentification {
8
+ userId: string;
9
+ organizationId: string;
10
+ organizationName: string;
11
+ isMigratedToWorkleap: boolean;
12
+ isAdmin: boolean;
13
+ isOrganizationCreator?: boolean;
14
+ isExecutive?: {
15
+ wov?: boolean;
16
+ lms?: boolean;
17
+ onb?: boolean;
18
+ sks?: boolean;
19
+ wpm?: boolean;
20
+ pbd?: boolean;
21
+ };
22
+ isCollaborator?: {
23
+ wov?: boolean;
24
+ lms?: boolean;
25
+ onb?: boolean;
26
+ sks?: boolean;
27
+ wpm?: boolean;
28
+ pbd?: boolean;
29
+ };
30
+ isReportingManager?: boolean;
31
+ isTeamManager?: boolean;
32
+ planCode?: {
33
+ wov?: string;
34
+ lms?: string;
35
+ onb?: string;
36
+ sks?: string;
37
+ wpm?: string;
38
+ pbd?: string;
39
+ };
40
+ }
41
+
42
+ /**
43
+ * @see https://workleap.github.io/wl-telemetry
44
+ */
45
+ export interface LogRocketUserTraits extends Record<string, unknown> {
46
+ "User Id": string;
47
+ "Organization Id": string;
48
+ "Organization Name": string;
49
+ "Is Migrated To Workleap": boolean;
50
+ "Is Admin": boolean;
51
+ "Device Id": string;
52
+ "Telemetry Id": string;
53
+ "Is Organization Creator"?: boolean;
54
+ "Is Executive"?: boolean;
55
+ "Is Executive - Officevibe"?: boolean;
56
+ "Is Executive - LMS"?: boolean;
57
+ "Is Executive - Onboarding"?: boolean;
58
+ "Is Executive - Skills"?: boolean;
59
+ "Is Executive - Performance"?: boolean;
60
+ "Is Executive - Pingboard"?: boolean;
61
+ "Is Collaborator"?: boolean;
62
+ "Is Collaborator - Officevibe"?: boolean;
63
+ "Is Collaborator - LMS"?: boolean;
64
+ "Is Collaborator - Onboarding"?: boolean;
65
+ "Is Collaborator - Skills"?: boolean;
66
+ "Is Collaborator - Performance"?: boolean;
67
+ "Is Collaborator - Pingboard"?: boolean;
68
+ "Is Reporting Manager"?: boolean;
69
+ "Is Team Manager"?: boolean;
70
+ "Plan Code - Officevibe"?: string;
71
+ "Plan Code - LMS"?: string;
72
+ "Plan Code - Onboarding"?: string;
73
+ "Plan Code - Skills"?: string;
74
+ "Plan Code - Performance"?: string;
75
+ "Plan Code - Pingboard"?: string;
76
+ }
77
+
78
+ export const DeviceIdTrait = "Device Id";
79
+ export const TelemetryIdTrait = "Telemetry Id";
80
+
81
+ /**
82
+ * @see https://workleap.github.io/wl-telemetry
83
+ */
84
+ export function createDefaultUserTraits(identification: LogRocketIdentification) {
85
+ const {
86
+ userId,
87
+ organizationId,
88
+ organizationName,
89
+ isMigratedToWorkleap,
90
+ isOrganizationCreator,
91
+ isAdmin,
92
+ isExecutive,
93
+ isCollaborator,
94
+ isReportingManager,
95
+ isTeamManager,
96
+ planCode
97
+ } = identification;
98
+
99
+ const isExecutiveInAnyProduct = Boolean(
100
+ isExecutive?.wov ||
101
+ isExecutive?.lms ||
102
+ isExecutive?.onb ||
103
+ isExecutive?.sks ||
104
+ isExecutive?.wpm ||
105
+ isExecutive?.pbd
106
+ );
107
+
108
+ const isCollaboratorInAnyProduct = Boolean(
109
+ isCollaborator?.wov ||
110
+ isCollaborator?.lms ||
111
+ isCollaborator?.onb ||
112
+ isCollaborator?.sks ||
113
+ isCollaborator?.wpm ||
114
+ isCollaborator?.pbd
115
+ );
116
+
117
+ const telemetryContext = getTelemetryContext();
118
+
119
+ return {
120
+ "User Id": userId,
121
+ "Organization Id": organizationId,
122
+ "Organization Name": organizationName,
123
+ "Is Migrated To Workleap": isMigratedToWorkleap,
124
+ "Is Admin": isAdmin,
125
+ [DeviceIdTrait]: telemetryContext ? telemetryContext.deviceId : "N/A",
126
+ [TelemetryIdTrait]: telemetryContext ? telemetryContext.telemetryId : "N/A",
127
+ ...(isDefined(isOrganizationCreator) && { "Is Organization Creator": isOrganizationCreator }),
128
+ ...(isExecutiveInAnyProduct && { "Is Executive": true }),
129
+ ...(isDefined(isExecutive?.wov) && { "Is Executive - Officevibe": isExecutive.wov }),
130
+ ...(isDefined(isExecutive?.lms) && { "Is Executive - LMS": isExecutive.lms }),
131
+ ...(isDefined(isExecutive?.onb) && { "Is Executive - Onboarding": isExecutive.onb }),
132
+ ...(isDefined(isExecutive?.sks) && { "Is Executive - Skills": isExecutive.sks }),
133
+ ...(isDefined(isExecutive?.wpm) && { "Is Executive - Performance": isExecutive.wpm }),
134
+ ...(isDefined(isExecutive?.pbd) && { "Is Executive - Pingboard": isExecutive.pbd }),
135
+ ...(isCollaboratorInAnyProduct && { "Is Collaborator": isCollaboratorInAnyProduct }),
136
+ ...(isDefined(isCollaborator?.wov) && { "Is Collaborator - Officevibe": isCollaborator.wov }),
137
+ ...(isDefined(isCollaborator?.lms) && { "Is Collaborator - LMS": isCollaborator.lms }),
138
+ ...(isDefined(isCollaborator?.onb) && { "Is Collaborator - Onboarding": isCollaborator.onb }),
139
+ ...(isDefined(isCollaborator?.sks) && { "Is Collaborator - Skills": isCollaborator.sks }),
140
+ ...(isDefined(isCollaborator?.wpm) && { "Is Collaborator - Performance": isCollaborator.wpm }),
141
+ ...(isDefined(isCollaborator?.pbd) && { "Is Collaborator - Pingboard": isCollaborator.pbd }),
142
+ ...(isDefined(isReportingManager) && { "Is Reporting Manager": isReportingManager }),
143
+ ...(isDefined(isTeamManager) && { "Is Team Manager": isTeamManager }),
144
+ ...(isDefined(planCode?.wov) && { "Plan Code - Officevibe": planCode.wov }),
145
+ ...(isDefined(planCode?.lms) && { "Plan Code - LMS": planCode.lms }),
146
+ ...(isDefined(planCode?.onb) && { "Plan Code - Onboarding": planCode.onb }),
147
+ ...(isDefined(planCode?.sks) && { "Plan Code - Skills": planCode.sks }),
148
+ ...(isDefined(planCode?.wpm) && { "Plan Code - Performance": planCode.wpm }),
149
+ ...(isDefined(planCode?.pbd) && { "Plan Code - Pingboard": planCode.pbd })
150
+ } satisfies LogRocketUserTraits;
151
+ }
@@ -0,0 +1,19 @@
1
+ import type { LogRocketRequest } from "./logRocketTypes.ts";
2
+
3
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
+ export type RequestSanitizerFunction = (req: LogRocketRequest) => any;
5
+
6
+ export function createRequestSanitizer(fuzzyRequestSanitizer: RequestSanitizerFunction) {
7
+ return (req: LogRocketRequest) => {
8
+ if (req.headers["Authorization"]) {
9
+ req.headers["Authorization"] = "**redacted**";
10
+ }
11
+
12
+ if (req.body) {
13
+ // Do not return the request body, which could contain sensitive information.
14
+ req.body = "**redacted**";
15
+ }
16
+
17
+ return fuzzyRequestSanitizer(req);
18
+ };
19
+ }
@@ -0,0 +1,15 @@
1
+ import type { LogRocketResponse } from "./logRocketTypes.ts";
2
+
3
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
+ export type ResponseSanitizerFunction = (res: LogRocketResponse) => any;
5
+
6
+ export function createResponseSanitizer(fuzzyResponseSanitizer: ResponseSanitizerFunction) {
7
+ return (res: LogRocketResponse) => {
8
+ if (res.body) {
9
+ // Do not return the response body, which could contain sensitive information.
10
+ res.body = "**redacted**";
11
+ }
12
+
13
+ return fuzzyResponseSanitizer(res);
14
+ };
15
+ }
@@ -0,0 +1,11 @@
1
+ export function createUrlSanitizer(queryParametersToRemove: string[]) {
2
+ return (url: string) => {
3
+ let sanitizedUrl = url;
4
+
5
+ for (const x of queryParametersToRemove) {
6
+ sanitizedUrl = sanitizedUrl.replace(new RegExp(`${x}=([^&]*)`, "i"), `${x}=**redacted**`);
7
+ }
8
+
9
+ return sanitizedUrl;
10
+ };
11
+ }
package/src/index.ts ADDED
@@ -0,0 +1,5 @@
1
+ export type { LogRocketSdkOptionsTransformer } from "./applyTransformers.ts";
2
+ export { createDefaultUserTraits, type LogRocketIdentification, type LogRocketUserTraits } from "./createDefaultUserTraits.ts";
3
+ export type * from "./logRocketTypes.ts";
4
+ export { registerLogRocketInstrumentation } from "./registerLogRocketInstrumentation.ts";
5
+
@@ -0,0 +1,30 @@
1
+ import type LogRocket from "logrocket";
2
+
3
+ // Typings are not exposed by the library.
4
+ export type LogRocketSdkOptions = NonNullable<Parameters<(typeof LogRocket)["init"]>[1]>;
5
+
6
+ // Typings are not exposed by the library, copied from the LogRocket package.
7
+ export interface LogRocketRequest {
8
+ reqId: string;
9
+ url: string;
10
+ headers: {
11
+ [key: string]: string | null | undefined;
12
+ };
13
+ body?: string;
14
+ method: string;
15
+ referrer?: string;
16
+ mode?: string;
17
+ credentials?: string;
18
+ }
19
+
20
+ // Typings are not exposed by the library, copied from the LogRocket package.
21
+ export interface LogRocketResponse {
22
+ reqId: string;
23
+ status?: number;
24
+ headers: {
25
+ [key: string]: string | null | undefined;
26
+ };
27
+ body?: string;
28
+ method: string;
29
+ url?: string;
30
+ }