@codaco/analytics 0.0.1 → 0.1.0-alpha

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,18 +1,16 @@
1
1
 
2
- > @codaco/analytics@0.0.1 build /Users/buckhalt/Code/complexdatacollective/error-analytics-microservice/packages/analytics
3
- > tsup src/index.ts --format cjs,esm --dts
2
+ > @codaco/analytics@0.1.0-alpha build /Users/buckhalt/Code/complexdatacollective/error-analytics-microservice/packages/analytics
3
+ > tsup src/index.ts --format esm --dts --minify --clean --sourcemap
4
4
 
5
5
  CLI Building entry: src/index.ts
6
6
  CLI Using tsconfig: tsconfig.json
7
7
  CLI tsup v7.2.0
8
8
  CLI Target: es2022
9
- CJS Build start
9
+ CLI Cleaning output folder
10
10
  ESM Build start
11
- ESM dist/index.mjs 958.00 B
12
- ESM ⚡️ Build success in 33ms
13
- CJS dist/index.js 1.95 KB
14
- CJS ⚡️ Build success in 34ms
11
+ ESM dist/index.mjs 1.89 KB
12
+ ESM dist/index.mjs.map 6.66 KB
13
+ ESM ⚡️ Build success in 17ms
15
14
  DTS Build start
16
- DTS ⚡️ Build success in 578ms
17
- DTS dist/index.d.ts 583.00 B
18
- DTS dist/index.d.mts 583.00 B
15
+ DTS ⚡️ Build success in 938ms
16
+ DTS dist/index.d.mts 1.54 KB
@@ -1,5 +1,5 @@
1
1
 
2
- > @codaco/analytics@0.0.1 lint /Users/buckhalt/Code/complexdatacollective/error-analytics-microservice/packages/analytics
2
+ > @codaco/analytics@0.1.0-alpha lint /Users/buckhalt/Code/complexdatacollective/error-analytics-microservice/packages/analytics
3
3
  > eslint .
4
4
 
5
5
  Pages directory cannot be found at /Users/buckhalt/Code/complexdatacollective/error-analytics-microservice/packages/analytics/pages or /Users/buckhalt/Code/complexdatacollective/error-analytics-microservice/packages/analytics/src/pages. If using a custom path, please configure with the `no-html-link-for-pages` rule in your eslint config file.
package/dist/index.d.mts CHANGED
@@ -1,20 +1,48 @@
1
- type EventPayload = {
1
+ import { WebServiceClient } from '@maxmind/geoip2-node';
2
+ import { NextRequest } from 'next/server';
3
+
4
+ type GeoLocation = {
5
+ countryCode: string;
6
+ };
7
+ type AnalyticsEventBase = {
8
+ type: "InterviewCompleted" | "InterviewStarted" | "ProtocolInstalled" | "AppSetup" | "Error";
9
+ };
10
+ type AnalyticsEvent = AnalyticsEventBase & {
2
11
  type: "InterviewCompleted" | "InterviewStarted" | "ProtocolInstalled" | "AppSetup";
3
- metadata?: string;
4
- timestamp?: string;
5
- isocode?: string;
6
- installationid: string;
12
+ metadata?: Record<string, unknown>;
13
+ };
14
+ type AnalyticsError = AnalyticsEventBase & {
15
+ type: "Error";
16
+ error: {
17
+ code: number;
18
+ message: string;
19
+ details: string;
20
+ stacktrace: string;
21
+ path: string;
22
+ };
23
+ };
24
+ type AnalyticsEventOrError = AnalyticsEvent | AnalyticsError;
25
+ type DispatchableAnalyticsEvent = AnalyticsEventOrError & {
26
+ installationId: string;
27
+ geolocation?: GeoLocation;
28
+ timestamp: Date;
7
29
  };
8
- type ErrorPayload = {
9
- code: number;
10
- message: string;
11
- details: string;
12
- stacktrace: string;
13
- installationid: string;
14
- timestamp?: string;
15
- path: string;
30
+ type AnalyticsClientConfiguration = {
31
+ platformUrl?: string;
16
32
  };
17
- declare function trackEvent(event: EventPayload): Promise<void>;
18
- declare function trackError(error: ErrorPayload): Promise<void>;
33
+ declare class AnalyticsClient {
34
+ private platformUrl?;
35
+ private installationId;
36
+ private dispatchQueue;
37
+ private enabled;
38
+ constructor(configuration: AnalyticsClientConfiguration);
39
+ createRouteHandler: (maxMindClient: WebServiceClient) => (req: NextRequest) => Promise<Response>;
40
+ private processEvent;
41
+ trackEvent(payload: AnalyticsEventOrError): void;
42
+ setInstallationId(installationId: string): void;
43
+ enable(): void;
44
+ disable(): void;
45
+ get isEnabled(): boolean;
46
+ }
19
47
 
20
- export { ErrorPayload, EventPayload, trackError, trackEvent };
48
+ export { AnalyticsClient, AnalyticsError, AnalyticsEvent, AnalyticsEventBase, AnalyticsEventOrError, DispatchableAnalyticsEvent };
package/dist/index.mjs CHANGED
@@ -1,39 +1,2 @@
1
- // src/index.ts
2
- async function trackEvent(event) {
3
- const endpoint = "localhost:3000/api/event";
4
- try {
5
- const response = await fetch(endpoint, {
6
- method: "POST",
7
- headers: {
8
- "Content-Type": "application/json"
9
- },
10
- body: JSON.stringify({ event })
11
- });
12
- if (!response.ok) {
13
- throw new Error(`HTTP error! Status: ${response.status}`);
14
- }
15
- } catch (error) {
16
- throw new Error("Failed to make the request");
17
- }
18
- }
19
- async function trackError(error) {
20
- const endpoint = "localhost:3000/api/error";
21
- try {
22
- const response = await fetch(endpoint, {
23
- method: "POST",
24
- headers: {
25
- "Content-Type": "application/json"
26
- },
27
- body: JSON.stringify({ errorPayload: error })
28
- });
29
- if (!response.ok) {
30
- throw new Error(`HTTP error! Status: ${response.status}`);
31
- }
32
- } catch (error2) {
33
- throw new Error("Failed to make the request");
34
- }
35
- }
36
- export {
37
- trackError,
38
- trackEvent
39
- };
1
+ import{queue as o}from"async";var s=class{platformUrl="https://analytics.networkcanvas.dev";installationId=null;dispatchQueue;enabled=!1;constructor(e){e.platformUrl&&(this.platformUrl=e.platformUrl),this.dispatchQueue=o(this.processEvent,1),this.dispatchQueue.pause()}createRouteHandler=e=>async r=>{let n=(r.headers.get("x-forwarded-for")??"127.0.0.1").split(",")[0];if(n==="::1")return new Response(null,{status:200});if(!n)return console.error("No IP address provided for geolocation"),new Response(null,{status:500});try{let t=await e.country(n);return new Response(t?.country?.isoCode,{headers:{"Content-Type":"application/json"}})}catch(t){return console.error("Error getting country code",t),new Response(null,{status:500})}};processEvent=async e=>{try{let r=await fetch("api/analytics/geolocate");r.ok||console.error("Geolocation request failed");let n=await r.text(),t={...e,installationId:this.installationId??"",timestamp:new Date,geolocation:{countryCode:n??""}};if(!(await fetch(`${this.platformUrl}/api/event`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})).ok){console.info(`\u{1F6AB} Event "${t.type}" failed to send to analytics microservice.`);return}console.info(`\u{1F680} Event "${t.type}" successfully sent to analytics microservice`)}catch(r){console.error("Error sending event to analytics microservice",r);return}};trackEvent(e){console.info(`\u{1F560} Event ${e.type} queued for dispatch...`),this.dispatchQueue.push(e)}setInstallationId(e){this.installationId=e}enable(){this.installationId||console.error("\u{1F6AB} An installation ID must be set before you can enable analytics"),console.info("\u{1F4C8} Analytics enabled"),this.enabled=!0,this.dispatchQueue.resume()}disable(){console.info("\u{1F4C8} Analytics disabled"),this.enabled=!1,this.dispatchQueue.pause()}get isEnabled(){return this.enabled}};export{s as AnalyticsClient};
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { WebServiceClient } from \"@maxmind/geoip2-node\";\nimport { QueueObject, queue } from \"async\";\nimport type { NextRequest } from \"next/server\";\n\ntype GeoLocation = {\n countryCode: string;\n};\n\nexport type AnalyticsEventBase = {\n type:\n | \"InterviewCompleted\"\n | \"InterviewStarted\"\n | \"ProtocolInstalled\"\n | \"AppSetup\"\n | \"Error\";\n};\n\nexport type AnalyticsEvent = AnalyticsEventBase & {\n type:\n | \"InterviewCompleted\"\n | \"InterviewStarted\"\n | \"ProtocolInstalled\"\n | \"AppSetup\";\n metadata?: Record<string, unknown>;\n};\n\nexport type AnalyticsError = AnalyticsEventBase & {\n type: \"Error\";\n error: {\n code: number;\n message: string;\n details: string;\n stacktrace: string;\n path: string;\n };\n};\n\nexport type AnalyticsEventOrError = AnalyticsEvent | AnalyticsError;\n\nexport type DispatchableAnalyticsEvent = AnalyticsEventOrError & {\n installationId: string;\n geolocation?: GeoLocation;\n timestamp: Date;\n};\n\ntype AnalyticsClientConfiguration = {\n platformUrl?: string;\n};\n\nexport class AnalyticsClient {\n private platformUrl?: string = \"https://analytics.networkcanvas.dev\";\n private installationId: string | null = null;\n\n private dispatchQueue: QueueObject<AnalyticsEventOrError>;\n\n private enabled: boolean = false;\n\n constructor(configuration: AnalyticsClientConfiguration) {\n if (configuration.platformUrl) {\n this.platformUrl = configuration.platformUrl;\n }\n\n this.dispatchQueue = queue(this.processEvent, 1);\n this.dispatchQueue.pause(); // Start the queue paused so we can set the installation ID\n }\n\n public createRouteHandler =\n (maxMindClient: WebServiceClient) =>\n async (req: NextRequest): Promise<Response> => {\n const ip = (req.headers.get(\"x-forwarded-for\") ?? \"127.0.0.1\").split(\n \",\"\n )[0];\n\n if (ip === \"::1\") {\n // This is a localhost request, so we can't geolocate it.\n return new Response(null, { status: 200 });\n }\n\n if (!ip) {\n console.error(\"No IP address provided for geolocation\");\n return new Response(null, { status: 500 });\n }\n\n try {\n const response = await maxMindClient.country(ip);\n\n return new Response(response?.country?.isoCode, {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(\"Error getting country code\", error);\n return new Response(null, { status: 500 });\n }\n };\n\n private processEvent = async (event: AnalyticsEventOrError) => {\n // Todo: we need to think about client vs server geolocation. If we want\n // client, does this get us that? If we want server, we can get it once,\n // and simply store it.\n // Todo: use fetchWithZod?\n\n try {\n const response = await fetch(\"api/analytics/geolocate\");\n if (!response.ok) {\n console.error(\"Geolocation request failed\");\n }\n\n const countryCode: string | null = await response.text();\n\n const eventWithRequiredProperties: DispatchableAnalyticsEvent = {\n ...event,\n installationId: this.installationId ?? \"\",\n timestamp: new Date(),\n geolocation: {\n countryCode: countryCode ?? \"\",\n },\n };\n\n // We could validate against a zod schema here.\n\n // Send event to microservice.\n\n const result = await fetch(`${this.platformUrl}/api/event`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(eventWithRequiredProperties),\n });\n\n if (!result.ok) {\n console.info(\n `🚫 Event \"${eventWithRequiredProperties.type}\" failed to send to analytics microservice.`\n );\n return;\n }\n\n console.info(\n `🚀 Event \"${eventWithRequiredProperties.type}\" successfully sent to analytics microservice`\n );\n } catch (error) {\n console.error(\"Error sending event to analytics microservice\", error);\n return;\n }\n };\n\n public trackEvent(payload: AnalyticsEventOrError) {\n console.info(`🕠 Event ${payload.type} queued for dispatch...`);\n this.dispatchQueue.push(payload);\n }\n\n public setInstallationId(installationId: string) {\n this.installationId = installationId;\n }\n\n public enable() {\n if (!this.installationId) {\n console.error(\n \"🚫 An installation ID must be set before you can enable analytics\"\n );\n }\n\n console.info(\"📈 Analytics enabled\");\n this.enabled = true;\n this.dispatchQueue.resume();\n }\n\n public disable() {\n console.info(\"📈 Analytics disabled\");\n this.enabled = false;\n this.dispatchQueue.pause();\n }\n\n get isEnabled() {\n return this.enabled;\n }\n}\n"],"mappings":"AACA,OAAsB,SAAAA,MAAa,QAgD5B,IAAMC,EAAN,KAAsB,CACnB,YAAuB,sCACvB,eAAgC,KAEhC,cAEA,QAAmB,GAE3B,YAAYC,EAA6C,CACnDA,EAAc,cAChB,KAAK,YAAcA,EAAc,aAGnC,KAAK,cAAgBF,EAAM,KAAK,aAAc,CAAC,EAC/C,KAAK,cAAc,MAAM,CAC3B,CAEO,mBACJG,GACD,MAAOC,GAAwC,CAC7C,IAAMC,GAAMD,EAAI,QAAQ,IAAI,iBAAiB,GAAK,aAAa,MAC7D,GACF,EAAE,CAAC,EAEH,GAAIC,IAAO,MAET,OAAO,IAAI,SAAS,KAAM,CAAE,OAAQ,GAAI,CAAC,EAG3C,GAAI,CAACA,EACH,eAAQ,MAAM,wCAAwC,EAC/C,IAAI,SAAS,KAAM,CAAE,OAAQ,GAAI,CAAC,EAG3C,GAAI,CACF,IAAMC,EAAW,MAAMH,EAAc,QAAQE,CAAE,EAE/C,OAAO,IAAI,SAASC,GAAU,SAAS,QAAS,CAC9C,QAAS,CACP,eAAgB,kBAClB,CACF,CAAC,CACH,OAASC,EAAO,CAEd,eAAQ,MAAM,6BAA8BA,CAAK,EAC1C,IAAI,SAAS,KAAM,CAAE,OAAQ,GAAI,CAAC,CAC3C,CACF,EAEM,aAAe,MAAOC,GAAiC,CAM7D,GAAI,CACF,IAAMF,EAAW,MAAM,MAAM,yBAAyB,EACjDA,EAAS,IACZ,QAAQ,MAAM,4BAA4B,EAG5C,IAAMG,EAA6B,MAAMH,EAAS,KAAK,EAEjDI,EAA0D,CAC9D,GAAGF,EACH,eAAgB,KAAK,gBAAkB,GACvC,UAAW,IAAI,KACf,YAAa,CACX,YAAaC,GAAe,EAC9B,CACF,EAcA,GAAI,EARW,MAAM,MAAM,GAAG,KAAK,WAAW,aAAc,CAC1D,OAAQ,OACR,QAAS,CACP,eAAgB,kBAClB,EACA,KAAM,KAAK,UAAUC,CAA2B,CAClD,CAAC,GAEW,GAAI,CACd,QAAQ,KACN,oBAAaA,EAA4B,IAAI,6CAC/C,EACA,MACF,CAEA,QAAQ,KACN,oBAAaA,EAA4B,IAAI,+CAC/C,CACF,OAASH,EAAO,CACd,QAAQ,MAAM,gDAAiDA,CAAK,EACpE,MACF,CACF,EAEO,WAAWI,EAAgC,CAChD,QAAQ,KAAK,mBAAYA,EAAQ,IAAI,yBAAyB,EAC9D,KAAK,cAAc,KAAKA,CAAO,CACjC,CAEO,kBAAkBC,EAAwB,CAC/C,KAAK,eAAiBA,CACxB,CAEO,QAAS,CACT,KAAK,gBACR,QAAQ,MACN,0EACF,EAGF,QAAQ,KAAK,6BAAsB,EACnC,KAAK,QAAU,GACf,KAAK,cAAc,OAAO,CAC5B,CAEO,SAAU,CACf,QAAQ,KAAK,8BAAuB,EACpC,KAAK,QAAU,GACf,KAAK,cAAc,MAAM,CAC3B,CAEA,IAAI,WAAY,CACd,OAAO,KAAK,OACd,CACF","names":["queue","AnalyticsClient","configuration","maxMindClient","req","ip","response","error","event","countryCode","eventWithRequiredProperties","payload","installationId"]}
package/package.json CHANGED
@@ -1,26 +1,33 @@
1
1
  {
2
2
  "name": "@codaco/analytics",
3
- "version": "0.0.1",
4
- "main": "./dist/index.js",
3
+ "version": "0.1.0-alpha",
5
4
  "module": "./dist/index.mjs",
6
- "types": "./dist/index.d.ts",
5
+ "types": "./dist/index.d.mts",
7
6
  "author": "Complex Data Collective <developers@coda.co>",
8
7
  "description": "Utilities for tracking analytics and error reporting in Fresco",
9
8
  "dependencies": {
10
- "tsup": "^7.2.0",
11
- "typescript": "latest"
9
+ "@maxmind/geoip2-node": "^5.0.0",
10
+ "async": "^3.2.5",
11
+ "zod-fetch": "^0.1.1"
12
+ },
13
+ "peerDependencies": {
14
+ "next": "14.0.1"
12
15
  },
13
16
  "devDependencies": {
17
+ "@types/async": "^3.2.24",
14
18
  "@types/node": "^20.5.2",
15
19
  "@types/react": "^18.2.0",
16
20
  "@types/react-dom": "^18.2.0",
17
21
  "react": "^18.2.0",
18
- "typescript": "^5.2.2",
22
+ "tsup": "^7.2.0",
23
+ "typescript": "^5.3.2",
24
+ "zod": "^3.22.4",
19
25
  "tsconfig": "0.0.0",
20
26
  "eslint-config-custom": "0.0.0"
21
27
  },
22
28
  "scripts": {
23
- "build": "tsup src/index.ts --format cjs,esm --dts",
24
- "lint": "eslint ."
29
+ "build": "tsup src/index.ts --format esm --dts --minify --clean --sourcemap",
30
+ "lint": "eslint .",
31
+ "dev": "npm run build -- --watch"
25
32
  }
26
33
  }
package/src/index.ts CHANGED
@@ -1,59 +1,180 @@
1
- export type EventPayload = {
1
+ import { WebServiceClient } from "@maxmind/geoip2-node";
2
+ import { QueueObject, queue } from "async";
3
+ import type { NextRequest } from "next/server";
4
+
5
+ type GeoLocation = {
6
+ countryCode: string;
7
+ };
8
+
9
+ export type AnalyticsEventBase = {
10
+ type:
11
+ | "InterviewCompleted"
12
+ | "InterviewStarted"
13
+ | "ProtocolInstalled"
14
+ | "AppSetup"
15
+ | "Error";
16
+ };
17
+
18
+ export type AnalyticsEvent = AnalyticsEventBase & {
2
19
  type:
3
20
  | "InterviewCompleted"
4
21
  | "InterviewStarted"
5
22
  | "ProtocolInstalled"
6
23
  | "AppSetup";
7
- metadata?: string;
8
- timestamp?: string;
9
- isocode?: string;
10
- installationid: string;
24
+ metadata?: Record<string, unknown>;
25
+ };
26
+
27
+ export type AnalyticsError = AnalyticsEventBase & {
28
+ type: "Error";
29
+ error: {
30
+ code: number;
31
+ message: string;
32
+ details: string;
33
+ stacktrace: string;
34
+ path: string;
35
+ };
11
36
  };
12
37
 
13
- export type ErrorPayload = {
14
- code: number;
15
- message: string;
16
- details: string;
17
- stacktrace: string;
18
- installationid: string;
19
- timestamp?: string;
20
- path: string;
38
+ export type AnalyticsEventOrError = AnalyticsEvent | AnalyticsError;
39
+
40
+ export type DispatchableAnalyticsEvent = AnalyticsEventOrError & {
41
+ installationId: string;
42
+ geolocation?: GeoLocation;
43
+ timestamp: Date;
44
+ };
45
+
46
+ type AnalyticsClientConfiguration = {
47
+ platformUrl?: string;
21
48
  };
22
49
 
23
- export async function trackEvent(event: EventPayload) {
24
- const endpoint = "localhost:3000/api/event";
25
- try {
26
- const response = await fetch(endpoint, {
27
- method: "POST",
28
- headers: {
29
- "Content-Type": "application/json",
30
- },
31
- body: JSON.stringify({ event: event }),
32
- });
33
-
34
- if (!response.ok) {
35
- throw new Error(`HTTP error! Status: ${response.status}`);
50
+ export class AnalyticsClient {
51
+ private platformUrl?: string = "https://analytics.networkcanvas.dev";
52
+ private installationId: string | null = null;
53
+
54
+ private dispatchQueue: QueueObject<AnalyticsEventOrError>;
55
+
56
+ private enabled: boolean = false;
57
+
58
+ constructor(configuration: AnalyticsClientConfiguration) {
59
+ if (configuration.platformUrl) {
60
+ this.platformUrl = configuration.platformUrl;
36
61
  }
37
- } catch (error) {
38
- throw new Error("Failed to make the request");
62
+
63
+ this.dispatchQueue = queue(this.processEvent, 1);
64
+ this.dispatchQueue.pause(); // Start the queue paused so we can set the installation ID
39
65
  }
40
- }
41
66
 
42
- export async function trackError(error: ErrorPayload) {
43
- const endpoint = "localhost:3000/api/error";
44
- try {
45
- const response = await fetch(endpoint, {
46
- method: "POST",
47
- headers: {
48
- "Content-Type": "application/json",
49
- },
50
- body: JSON.stringify({ errorPayload: error }),
51
- });
52
-
53
- if (!response.ok) {
54
- throw new Error(`HTTP error! Status: ${response.status}`);
67
+ public createRouteHandler =
68
+ (maxMindClient: WebServiceClient) =>
69
+ async (req: NextRequest): Promise<Response> => {
70
+ const ip = (req.headers.get("x-forwarded-for") ?? "127.0.0.1").split(
71
+ ","
72
+ )[0];
73
+
74
+ if (ip === "::1") {
75
+ // This is a localhost request, so we can't geolocate it.
76
+ return new Response(null, { status: 200 });
77
+ }
78
+
79
+ if (!ip) {
80
+ console.error("No IP address provided for geolocation");
81
+ return new Response(null, { status: 500 });
82
+ }
83
+
84
+ try {
85
+ const response = await maxMindClient.country(ip);
86
+
87
+ return new Response(response?.country?.isoCode, {
88
+ headers: {
89
+ "Content-Type": "application/json",
90
+ },
91
+ });
92
+ } catch (error) {
93
+ // eslint-disable-next-line no-console
94
+ console.error("Error getting country code", error);
95
+ return new Response(null, { status: 500 });
96
+ }
97
+ };
98
+
99
+ private processEvent = async (event: AnalyticsEventOrError) => {
100
+ // Todo: we need to think about client vs server geolocation. If we want
101
+ // client, does this get us that? If we want server, we can get it once,
102
+ // and simply store it.
103
+ // Todo: use fetchWithZod?
104
+
105
+ try {
106
+ const response = await fetch("api/analytics/geolocate");
107
+ if (!response.ok) {
108
+ console.error("Geolocation request failed");
109
+ }
110
+
111
+ const countryCode: string | null = await response.text();
112
+
113
+ const eventWithRequiredProperties: DispatchableAnalyticsEvent = {
114
+ ...event,
115
+ installationId: this.installationId ?? "",
116
+ timestamp: new Date(),
117
+ geolocation: {
118
+ countryCode: countryCode ?? "",
119
+ },
120
+ };
121
+
122
+ // We could validate against a zod schema here.
123
+
124
+ // Send event to microservice.
125
+
126
+ const result = await fetch(`${this.platformUrl}/api/event`, {
127
+ method: "POST",
128
+ headers: {
129
+ "Content-Type": "application/json",
130
+ },
131
+ body: JSON.stringify(eventWithRequiredProperties),
132
+ });
133
+
134
+ if (!result.ok) {
135
+ console.info(
136
+ `🚫 Event "${eventWithRequiredProperties.type}" failed to send to analytics microservice.`
137
+ );
138
+ return;
139
+ }
140
+
141
+ console.info(
142
+ `🚀 Event "${eventWithRequiredProperties.type}" successfully sent to analytics microservice`
143
+ );
144
+ } catch (error) {
145
+ console.error("Error sending event to analytics microservice", error);
146
+ return;
55
147
  }
56
- } catch (error) {
57
- throw new Error("Failed to make the request");
148
+ };
149
+
150
+ public trackEvent(payload: AnalyticsEventOrError) {
151
+ console.info(`🕠 Event ${payload.type} queued for dispatch...`);
152
+ this.dispatchQueue.push(payload);
153
+ }
154
+
155
+ public setInstallationId(installationId: string) {
156
+ this.installationId = installationId;
157
+ }
158
+
159
+ public enable() {
160
+ if (!this.installationId) {
161
+ console.error(
162
+ "🚫 An installation ID must be set before you can enable analytics"
163
+ );
164
+ }
165
+
166
+ console.info("📈 Analytics enabled");
167
+ this.enabled = true;
168
+ this.dispatchQueue.resume();
169
+ }
170
+
171
+ public disable() {
172
+ console.info("📈 Analytics disabled");
173
+ this.enabled = false;
174
+ this.dispatchQueue.pause();
175
+ }
176
+
177
+ get isEnabled() {
178
+ return this.enabled;
58
179
  }
59
180
  }
package/dist/index.d.ts DELETED
@@ -1,20 +0,0 @@
1
- type EventPayload = {
2
- type: "InterviewCompleted" | "InterviewStarted" | "ProtocolInstalled" | "AppSetup";
3
- metadata?: string;
4
- timestamp?: string;
5
- isocode?: string;
6
- installationid: string;
7
- };
8
- type ErrorPayload = {
9
- code: number;
10
- message: string;
11
- details: string;
12
- stacktrace: string;
13
- installationid: string;
14
- timestamp?: string;
15
- path: string;
16
- };
17
- declare function trackEvent(event: EventPayload): Promise<void>;
18
- declare function trackError(error: ErrorPayload): Promise<void>;
19
-
20
- export { ErrorPayload, EventPayload, trackError, trackEvent };
package/dist/index.js DELETED
@@ -1,65 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/index.ts
21
- var src_exports = {};
22
- __export(src_exports, {
23
- trackError: () => trackError,
24
- trackEvent: () => trackEvent
25
- });
26
- module.exports = __toCommonJS(src_exports);
27
- async function trackEvent(event) {
28
- const endpoint = "localhost:3000/api/event";
29
- try {
30
- const response = await fetch(endpoint, {
31
- method: "POST",
32
- headers: {
33
- "Content-Type": "application/json"
34
- },
35
- body: JSON.stringify({ event })
36
- });
37
- if (!response.ok) {
38
- throw new Error(`HTTP error! Status: ${response.status}`);
39
- }
40
- } catch (error) {
41
- throw new Error("Failed to make the request");
42
- }
43
- }
44
- async function trackError(error) {
45
- const endpoint = "localhost:3000/api/error";
46
- try {
47
- const response = await fetch(endpoint, {
48
- method: "POST",
49
- headers: {
50
- "Content-Type": "application/json"
51
- },
52
- body: JSON.stringify({ errorPayload: error })
53
- });
54
- if (!response.ok) {
55
- throw new Error(`HTTP error! Status: ${response.status}`);
56
- }
57
- } catch (error2) {
58
- throw new Error("Failed to make the request");
59
- }
60
- }
61
- // Annotate the CommonJS export names for ESM import in node:
62
- 0 && (module.exports = {
63
- trackError,
64
- trackEvent
65
- });