@codaco/analytics 0.4.0-alpha → 0.5.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,5 +1,5 @@
1
1
 
2
- > @codaco/analytics@0.4.0-alpha build /Users/buckhalt/Code/complexdatacollective/error-analytics-microservice/packages/analytics
2
+ > @codaco/analytics@0.5.0-alpha build /Users/buckhalt/Code/complexdatacollective/error-analytics-microservice/packages/analytics
3
3
  > tsup src/index.ts --format esm --dts --minify --clean --sourcemap
4
4
 
5
5
  CLI Building entry: src/index.ts
@@ -8,9 +8,9 @@ CLI tsup v7.2.0
8
8
  CLI Target: es2022
9
9
  CLI Cleaning output folder
10
10
  ESM Build start
11
- ESM dist/index.mjs 1.84 KB
12
- ESM dist/index.mjs.map 6.61 KB
13
- ESM ⚡️ Build success in 43ms
11
+ ESM dist/index.mjs 1.73 KB
12
+ ESM dist/index.mjs.map 6.35 KB
13
+ ESM ⚡️ Build success in 16ms
14
14
  DTS Build start
15
- DTS ⚡️ Build success in 738ms
15
+ DTS ⚡️ Build success in 733ms
16
16
  DTS dist/index.d.mts 1.49 KB
@@ -1,5 +1,5 @@
1
1
 
2
- > @codaco/analytics@0.4.0-alpha lint /Users/buckhalt/Code/complexdatacollective/error-analytics-microservice/packages/analytics
2
+ > @codaco/analytics@0.5.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.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{queue as s}from"async";var o=class{platformUrl="https://analytics.networkcanvas.dev";installationId=null;dispatchQueue;enabled=!0;constructor(e){e.platformUrl&&(this.platformUrl=e.platformUrl),this.dispatchQueue=s(this.processEvent,1),this.dispatchQueue.pause()}createRouteHandler=e=>async t=>{let n=(t.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 r=await e.country(n);return new Response(r?.country?.isoCode,{headers:{"Content-Type":"application/json"}})}catch(r){return console.error("Error getting country code",r),new Response(null,{status:500})}};processEvent=async e=>{try{let t=await fetch("api/analytics/geolocate");t.ok||console.error("Geolocation request failed");let n=await t.text(),r={...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(r)})).ok){console.info(`\u{1F6AB} Event "${r.type}" failed to send to analytics microservice.`);return}console.info(`\u{1F680} Event "${r.type}" successfully sent to analytics microservice`)}catch(t){console.error("Error sending event to analytics microservice",t);return}};trackEvent(e){console.info(`\u{1F560} Event ${e.type} queued for dispatch...`),this.dispatchQueue.push(e)}setInstallationId(e){if(this.enabled)try{this.installationId=e,this.dispatchQueue.resume(),console.info("\u{1F4C8} Analytics queue resumed")}catch(t){console.error("Error setting installation ID",t)}}disable(){console.info("\u{1F4C8} Analytics disabled"),this.enabled=!1,this.dispatchQueue.pause()}get isEnabled(){return this.enabled}};export{o as AnalyticsClient};
1
+ import{queue as o}from"async";var s=class{platformUrl="https://analytics.networkcanvas.dev";installationId=null;dispatchQueue;enabled=!0;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.enabled&&(this.installationId=e),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
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +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 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 = true;\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 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 if (this.enabled) {\n try {\n this.installationId = installationId;\n this.dispatchQueue.resume();\n console.info(\"📈 Analytics queue resumed\");\n } catch (error) {\n console.error(\"Error setting installation ID\", error);\n }\n }\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,QA+C5B,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,CAK7D,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,GAAI,KAAK,QACP,GAAI,CACF,KAAK,eAAiBA,EACtB,KAAK,cAAc,OAAO,EAC1B,QAAQ,KAAK,mCAA4B,CAC3C,OAASL,EAAO,CACd,QAAQ,MAAM,gCAAiCA,CAAK,CACtD,CAEJ,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"]}
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 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 = true;\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 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 if (this.enabled) {\n this.installationId = installationId;\n }\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,QA+C5B,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,CAK7D,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,CAC3C,KAAK,UACP,KAAK,eAAiBA,GAExB,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,6 +1,6 @@
1
1
  {
2
2
  "name": "@codaco/analytics",
3
- "version": "0.4.0-alpha",
3
+ "version": "0.5.0-alpha",
4
4
  "module": "./dist/index.mjs",
5
5
  "types": "./dist/index.d.mts",
6
6
  "author": "Complex Data Collective <developers@coda.co>",
package/src/index.ts CHANGED
@@ -152,14 +152,9 @@ export class AnalyticsClient {
152
152
 
153
153
  public setInstallationId(installationId: string) {
154
154
  if (this.enabled) {
155
- try {
156
- this.installationId = installationId;
157
- this.dispatchQueue.resume();
158
- console.info("📈 Analytics queue resumed");
159
- } catch (error) {
160
- console.error("Error setting installation ID", error);
161
- }
155
+ this.installationId = installationId;
162
156
  }
157
+ this.dispatchQueue.resume();
163
158
  }
164
159
 
165
160
  public disable() {