@pack/packlytics 0.1.0-ab-beta.0 → 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.
@@ -1,5 +1,4 @@
1
- import { Pack } from "./packlytics.types";
2
- export declare function usePacklytics(request: Request, pack: Pack, params: {
1
+ export declare function packlytics(request: Request, session: any, params: {
3
2
  storeFrontId: string;
4
3
  sessionSecret: string;
5
4
  }): Promise<Response | undefined>;
@@ -1 +1 @@
1
- {"version":3,"file":"packlytics.d.ts","sourceRoot":"","sources":["../src/packlytics.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,IAAI,EAAQ,MAAM,oBAAoB,CAAC;AAEhD,wBAAsB,aAAa,CACjC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,IAAI,EACV,MAAM,EAAE;IACN,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB,iCAoCF"}
1
+ {"version":3,"file":"packlytics.d.ts","sourceRoot":"","sources":["../src/packlytics.ts"],"names":[],"mappings":"AAOA,wBAAsB,UAAU,CAC9B,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,GAAG,EACZ,MAAM,EAAE;IACN,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB,iCAiDF"}
@@ -1,16 +1,26 @@
1
- import { getClientIPAddress } from "./utils/get-client-ip-address";
2
1
  import { getPacklyticsId } from "./utils/get-packlytics-id";
3
2
  import { getClientLocales } from "./utils/get-client-locales";
4
3
  import { trackPageHit } from "./utils/page-hit";
5
4
  import { getDevice } from "./utils/get-client-device";
6
- export async function usePacklytics(request, pack, params) {
5
+ import { getStorefrontHeaders } from "@shopify/remix-oxygen";
6
+ import { getClientLocation } from "./utils/get-client-location";
7
+ export async function packlytics(request, session, params) {
8
+ if (process.env.NODE_ENV === "development") {
9
+ return;
10
+ }
11
+ // Preview enabled
12
+ if (!!session.get("previewEnabled")) {
13
+ return;
14
+ }
7
15
  const url = new URL(request.url);
8
- const ipaddress = getClientIPAddress(request) || "";
16
+ const ipaddress = getStorefrontHeaders(request)["buyerIp"] || "";
9
17
  const dataToHash = `${request.headers.get("user-agent")}${ipaddress}${url.hostname}`;
10
18
  const packlyticsId = getPacklyticsId(dataToHash, params.sessionSecret);
11
- const testSession = pack.session.get("test");
19
+ const testSession = session.get("test");
20
+ const locale = getClientLocales(request) || ["en-US"];
21
+ const location = getClientLocation(locale[0]);
12
22
  return trackPageHit(params.storeFrontId, packlyticsId)({
13
- "pack-session-id": pack.session.id, // This session ID is saved on the __pack cookie
23
+ "pack-session-id": session.id, // This session ID is saved on the __pack cookie
14
24
  "user-agent": request.headers.get("user-agent") || "",
15
25
  pathname: url.pathname,
16
26
  query: url.search,
@@ -18,15 +28,16 @@ export async function usePacklytics(request, pack, params) {
18
28
  referrer: request.referrer,
19
29
  ipaddress: ipaddress,
20
30
  language: getClientLocales(request) || "",
21
- locale: request.headers.get("accept-language") || "",
31
+ locale: locale[0],
32
+ location: location,
22
33
  connection: request.headers.get("connection") || "",
23
34
  href: request.url,
24
35
  ...getDevice(request.headers.get("user-agent") || ""),
25
36
  test: {
26
37
  "test-id": testSession?.data?.id || "",
27
38
  "test-handle": testSession?.data?.handle || "",
28
- "test-variant-id": testSession?.data?.TestVariant?.id || "",
29
- "test-variant-handle": testSession?.data?.TestVariant?.handle || "",
39
+ "test-variant-id": testSession?.data?.testVariant?.id || "",
40
+ "test-variant-handle": testSession?.data?.testVariant?.handle || "",
30
41
  },
31
42
  });
32
43
  }
@@ -10,34 +10,9 @@ interface JSONArray extends Array<JSONValue> {
10
10
  interface JSONObject {
11
11
  [x: string]: JSONValue;
12
12
  }
13
- export interface Pack {
14
- session: any;
15
- }
16
- export interface Test {
17
- id: string;
18
- handle: string;
19
- TestVariant: {
20
- id: string;
21
- handle: string;
22
- };
23
- }
24
13
  export type PackData = {
25
14
  version: string;
26
15
  };
27
- export type BrowserData = {
28
- "user-agent": string;
29
- pathname: string;
30
- query: string;
31
- screen: string;
32
- referrer: string;
33
- hostname: string;
34
- language: string;
35
- locale: string;
36
- location: string;
37
- connection: string;
38
- deviceCategory: string;
39
- href: string;
40
- };
41
16
  export type EventDataPayload = JSONObject;
42
17
  export type EventData = PackData & {
43
18
  timestamp: string;
@@ -1 +1 @@
1
- {"version":3,"file":"packlytics.types.d.ts","sourceRoot":"","sources":["../src/packlytics.types.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,WAAW,EAAE,GAAG,CAAC;QACjB,OAAO,EAAE,GAAG,CAAC;KACd;CACF;AAED,KAAK,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;AAEpE,UAAU,SAAU,SAAQ,KAAK,CAAC,SAAS,CAAC;CAAG;AAE/C,UAAU,UAAU;IAClB,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACxB;AAED,MAAM,WAAW,IAAI;IACnB,OAAO,EAAE,GAAG,CAAC;CACd;AAED,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE;QACX,EAAE,EAAE,MAAM,CAAC;QACX,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAC;AAE1C,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,gBAAgB,CAAC"}
1
+ {"version":3,"file":"packlytics.types.d.ts","sourceRoot":"","sources":["../src/packlytics.types.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,WAAW,EAAE,GAAG,CAAC;QACjB,OAAO,EAAE,GAAG,CAAC;KACd;CACF;AAED,KAAK,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;AAEpE,UAAU,SAAU,SAAQ,KAAK,CAAC,SAAS,CAAC;CAAG;AAE/C,UAAU,UAAU;IAClB,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACxB;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAC;AAE1C,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,gBAAgB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function getClientLocation(locale: string): string;
2
+ //# sourceMappingURL=get-client-location.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-client-location.d.ts","sourceRoot":"","sources":["../../src/utils/get-client-location.ts"],"names":[],"mappings":"AAAA,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,UAI/C"}
@@ -0,0 +1,4 @@
1
+ export function getClientLocation(locale) {
2
+ const localeSplit = locale.split("-");
3
+ return localeSplit.length > 1 ? localeSplit[1].toLowerCase() : "";
4
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"get-packlytics-id.d.ts","sourceRoot":"","sources":["../../src/utils/get-packlytics-id.ts"],"names":[],"mappings":"AA4BA;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAO3D"}
1
+ {"version":3,"file":"get-packlytics-id.d.ts","sourceRoot":"","sources":["../../src/utils/get-packlytics-id.ts"],"names":[],"mappings":"AAuHA;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAO3D"}
@@ -1,23 +1,105 @@
1
- import crypto from "crypto";
2
- function generateUUIDFromHash(hash) {
3
- const crypto = require("crypto");
4
- const bytes = crypto.createHash("sha1").update(hash).digest();
5
- bytes[6] = (bytes[6] & 0x0f) | 0x50; // Set version to 5 (version 5 UUID)
6
- bytes[8] = (bytes[8] & 0x3f) | 0x80; // Set variant to RFC 4122
7
- const uuid = bytes.toString("hex", 0, 16);
1
+ function sha256(ascii) {
2
+ function rightRotate(value, amount) {
3
+ return (value >>> amount) | (value << (32 - amount));
4
+ }
5
+ const mathPow = Math.pow;
6
+ const maxWord = mathPow(2, 32);
7
+ const lengthProperty = "length";
8
+ let i, j; // Used as a counter across the whole file
9
+ let result = "";
10
+ const words = [];
11
+ const asciiBitLength = ascii[lengthProperty] * 8;
12
+ //* caching results is optional - remove/add slash from front of this line to toggle
13
+ // Initial hash value: first 32 bits of the fractional parts of the square roots of the first 8 primes
14
+ // (we actually calculate the first 64, but extra values are just ignored)
15
+ // @ts-ignore
16
+ let hash = (sha256.h = sha256.h || []);
17
+ // Round constants: first 32 bits of the fractional parts of the cube roots of the first 64 primes
18
+ // @ts-ignore
19
+ const k = (sha256.k = sha256.k || []);
20
+ let primeCounter = k[lengthProperty];
21
+ /*/
22
+ var hash = [], k = [];
23
+ var primeCounter = 0;
24
+ //*/
25
+ const isComposite = {};
26
+ for (let candidate = 2; primeCounter < 64; candidate++) {
27
+ // @ts-ignore
28
+ if (!isComposite[candidate]) {
29
+ for (i = 0; i < 313; i += candidate) {
30
+ // @ts-ignore
31
+ isComposite[i] = candidate;
32
+ }
33
+ hash[primeCounter] = (mathPow(candidate, 0.5) * maxWord) | 0;
34
+ k[primeCounter++] = (mathPow(candidate, 1 / 3) * maxWord) | 0;
35
+ }
36
+ }
37
+ ascii += "\x80"; // Append Ƈ' bit (plus zero padding)
38
+ while ((ascii[lengthProperty] % 64) - 56)
39
+ ascii += "\x00"; // More zero padding
40
+ for (i = 0; i < ascii[lengthProperty]; i++) {
41
+ j = ascii.charCodeAt(i);
42
+ if (j >> 8)
43
+ return; // ASCII check: only accept characters in range 0-255
44
+ words[i >> 2] |= j << (((3 - i) % 4) * 8);
45
+ }
46
+ words[words[lengthProperty]] = (asciiBitLength / maxWord) | 0;
47
+ words[words[lengthProperty]] = asciiBitLength;
48
+ // process each chunk
49
+ for (j = 0; j < words[lengthProperty];) {
50
+ const w = words.slice(j, (j += 16)); // The message is expanded into 64 words as part of the iteration
51
+ const oldHash = hash;
52
+ // This is now the undefinedworking hash", often labelled as variables a...g
53
+ // (we have to truncate as well, otherwise extra entries at the end accumulate
54
+ hash = hash.slice(0, 8);
55
+ for (i = 0; i < 64; i++) {
56
+ const i2 = i + j;
57
+ // Expand the message into 64 words
58
+ // Used below if
59
+ const w15 = w[i - 15], w2 = w[i - 2];
60
+ // Iterate
61
+ const a = hash[0], e = hash[4];
62
+ const temp1 = hash[7] +
63
+ (rightRotate(e, 6) ^ rightRotate(e, 11) ^ rightRotate(e, 25)) + // S1
64
+ ((e & hash[5]) ^ (~e & hash[6])) + // ch
65
+ k[i] +
66
+ // Expand the message schedule if needed
67
+ (w[i] =
68
+ i < 16
69
+ ? w[i]
70
+ : (w[i - 16] +
71
+ (rightRotate(w15, 7) ^ rightRotate(w15, 18) ^ (w15 >>> 3)) + // s0
72
+ w[i - 7] +
73
+ (rightRotate(w2, 17) ^ rightRotate(w2, 19) ^ (w2 >>> 10))) | // s1
74
+ 0);
75
+ // This is only used once, so *could* be moved below, but it only saves 4 bytes and makes things unreadble
76
+ const temp2 = (rightRotate(a, 2) ^ rightRotate(a, 13) ^ rightRotate(a, 22)) + // S0
77
+ ((a & hash[1]) ^ (a & hash[2]) ^ (hash[1] & hash[2])); // maj
78
+ hash = [(temp1 + temp2) | 0].concat(hash); // We don't bother trimming off the extra ones, they're harmless as long as we're truncating when we do the slice()
79
+ hash[4] = (hash[4] + temp1) | 0;
80
+ }
81
+ for (i = 0; i < 8; i++) {
82
+ hash[i] = (hash[i] + oldHash[i]) | 0;
83
+ }
84
+ }
85
+ for (i = 0; i < 8; i++) {
86
+ for (j = 3; j + 1; j--) {
87
+ const b = (hash[i] >> (j * 8)) & 255;
88
+ result += (b < 16 ? 0 : "") + b.toString(16);
89
+ }
90
+ }
91
+ return result;
92
+ }
93
+ function createHash(data) {
94
+ const hash = sha256(data);
8
95
  return [
9
- uuid.substring(0, 8),
10
- uuid.substring(8, 12),
11
- uuid.substring(12, 16),
12
- uuid.substring(16, 20),
13
- uuid.substring(20),
96
+ hash?.substring(0, 8),
97
+ hash?.substring(8, 12),
98
+ hash?.substring(12, 16),
99
+ hash?.substring(16, 20),
100
+ hash?.substring(20, 32),
14
101
  ].join("-");
15
102
  }
16
- function createHash(data, algorithm = "sha256") {
17
- const hash = crypto.createHash(algorithm);
18
- hash.update(data);
19
- return generateUUIDFromHash(hash.digest("hex"));
20
- }
21
103
  /**
22
104
  * Generates a UUID from the user data, such as user-agent and IP Address + Salt
23
105
  * The salt is generated on the currante date + a Secret from the StoreFront,
@@ -31,6 +113,6 @@ function createHash(data, algorithm = "sha256") {
31
113
  export function getPacklyticsId(data, secret) {
32
114
  const currentDate = new Date();
33
115
  const formattedDate = currentDate.toLocaleDateString("en-US");
34
- const salt = createHash(formattedDate + secret);
116
+ const salt = sha256(formattedDate + secret);
35
117
  return createHash(data + salt);
36
118
  }
@@ -15,12 +15,12 @@ const getPacklyticsMetadata = async () => {
15
15
  metadata = await response.json();
16
16
  }
17
17
  else {
18
- console.error("Error to get packlytics metadata:", response.statusText);
18
+ console.error("Error getting Packlytics metadata:", response.statusText);
19
19
  }
20
20
  }
21
21
  catch (error) {
22
22
  // @ts-ignore
23
- console.error("Error to get packlytics metadata:", error.message);
23
+ console.error("Error getting Packlytics metadata:", error.message);
24
24
  }
25
25
  };
26
26
  export const sendEvent = (storefrontId, sessionId) => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pack/packlytics",
3
3
  "description": "Packlytics",
4
- "version": "0.1.0-ab-beta.0",
4
+ "version": "1.0.0",
5
5
  "exports": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
7
7
  "engines": {