@nosto/nosto-react 0.2.1 → 0.4.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/src/types.ts CHANGED
@@ -1,3 +1,67 @@
1
+ declare global {
2
+ interface Window {
3
+ nosto?: {
4
+ reload(settings: unknown): void;
5
+ };
6
+ nostojs: {
7
+ (callback: (api: NostoClient) => void): void;
8
+ q?: unknown[];
9
+ };
10
+ }
11
+ }
12
+
13
+ /**
14
+ * @group Types
15
+ */
16
+ export interface NostoClient {
17
+ addOrder(order: { purchase: Purchase }): NostoClient;
18
+ defaultSession(): NostoClient;
19
+ setAutoLoad(autoload: boolean): NostoClient;
20
+ setCart(cart?: Cart): NostoClient;
21
+ setCustomer(customer?: Customer): NostoClient;
22
+ setPlacements(placements: string[]): NostoClient;
23
+ setResponseMode(mode: string): NostoClient;
24
+ setVariation(variation: string): NostoClient;
25
+ viewCategory(category: string): NostoClient;
26
+ viewProduct(product: string): NostoClient;
27
+ viewFrontPage(): NostoClient;
28
+ viewNotFound(): NostoClient;
29
+ viewOther(): NostoClient;
30
+ viewSearch(query: string): NostoClient;
31
+ viewCart(): NostoClient;
32
+ load(): Promise<{
33
+ affinities: Record<
34
+ string,
35
+ {
36
+ name: string;
37
+ score: number;
38
+ }[]
39
+ >;
40
+ geo_location?: string[];
41
+ page_views: number;
42
+ recommendations: Recommendation[];
43
+ }>;
44
+ placements: {
45
+ getPlacements(): string[];
46
+ };
47
+ }
48
+
49
+ /**
50
+ * @group Types
51
+ */
52
+ export interface Recommendation {
53
+ result_id: string;
54
+ products: Product[];
55
+ result_type: string;
56
+ title: string;
57
+ div_id: string;
58
+ source_product_ids: string[];
59
+ params: unknown;
60
+ }
61
+
62
+ /**
63
+ * @group Types
64
+ */
1
65
  export interface Item {
2
66
  name: string;
3
67
  price_currency_code: string;
@@ -7,10 +71,16 @@ export interface Item {
7
71
  unit_price: number;
8
72
  }
9
73
 
74
+ /**
75
+ * @group Types
76
+ */
10
77
  export interface Cart {
11
78
  items: Item[];
12
79
  }
13
80
 
81
+ /**
82
+ * @group Types
83
+ */
14
84
  export interface Customer {
15
85
  customer_reference: string;
16
86
  email: string;
@@ -19,6 +89,9 @@ export interface Customer {
19
89
  newsletter: boolean;
20
90
  }
21
91
 
92
+ /**
93
+ * @group Types
94
+ */
22
95
  export interface Buyer {
23
96
  first_name: string;
24
97
  last_name: string;
@@ -27,12 +100,18 @@ export interface Buyer {
27
100
  newsletter: boolean;
28
101
  }
29
102
 
103
+ /**
104
+ * @group Types
105
+ */
30
106
  export interface Purchase {
31
107
  number: string;
32
108
  info: Buyer;
33
109
  items: Item[];
34
110
  }
35
111
 
112
+ /**
113
+ * @group Types
114
+ */
36
115
  export interface SKU {
37
116
  id: string;
38
117
  name: string;
@@ -41,13 +120,16 @@ export interface SKU {
41
120
  url: URL;
42
121
  imageUrl: URL;
43
122
  gtin?: string;
44
- availability: 'InStock' | 'OutOfStock';
123
+ availability: "InStock" | "OutOfStock";
45
124
  customFields?: { [key: string]: string };
46
125
  }
47
126
 
127
+ /**
128
+ * @group Types
129
+ */
48
130
  export interface Product {
49
131
  alternateImageUrls?: URL[];
50
- availability: 'InStock' | 'OutOfStock';
132
+ availability: "InStock" | "OutOfStock";
51
133
  brand?: string;
52
134
  category: string[];
53
135
  categoryIds?: string[];
@@ -0,0 +1,30 @@
1
+ import { isPlainObject } from "./object";
2
+
3
+ export function deepCompare(a: unknown, b: unknown): boolean {
4
+ if (a === b) {
5
+ return true;
6
+ }
7
+
8
+ if (a instanceof Date && b instanceof Date) {
9
+ return a.getTime() === b.getTime();
10
+ }
11
+
12
+ if (a instanceof Array && b instanceof Array) {
13
+ if (a.length !== b.length) {
14
+ return false;
15
+ }
16
+
17
+ return a.every((v, i) => deepCompare(v, b[i]));
18
+ }
19
+
20
+ if (isPlainObject(a) && isPlainObject(b)) {
21
+ const entriesA = Object.entries(a);
22
+
23
+ if (entriesA.length !== Object.keys(b).length) {
24
+ return false;
25
+ }
26
+ return entriesA.every(([k, v]) => deepCompare(v, b[k]));
27
+ }
28
+
29
+ return false;
30
+ }
@@ -0,0 +1,21 @@
1
+ import { useEffect, useRef, useMemo } from "react";
2
+ import { deepCompare } from "./compare";
3
+
4
+ export function useDeepCompareEffect(
5
+ callback: Parameters<typeof useEffect>[0],
6
+ dependencies: Parameters<typeof useEffect>[1]
7
+ ): ReturnType<typeof useEffect> {
8
+ return useEffect(callback, useDeepCompareMemoize(dependencies));
9
+ }
10
+
11
+ function useDeepCompareMemoize<T>(value: T) {
12
+ const ref = useRef<T>(value);
13
+ const signalRef = useRef<number>(0);
14
+
15
+ if (!deepCompare(value, ref.current)) {
16
+ ref.current = value;
17
+ signalRef.current += 1;
18
+ }
19
+
20
+ return useMemo(() => ref.current, [signalRef.current]);
21
+ }
@@ -0,0 +1,20 @@
1
+ export function isPlainObject<T = Record<keyof any, unknown>>(
2
+ value: unknown
3
+ ): value is T {
4
+ const isObject = (v: unknown): v is object => String(v) === "[object Object]";
5
+
6
+ if (!isObject(value)) return false;
7
+
8
+ const constructor = value.constructor;
9
+ if (constructor === undefined) return true;
10
+
11
+ const prototype = constructor.prototype;
12
+ if (!isObject(prototype)) return false;
13
+
14
+ // Checks if it is not a class
15
+ if (!prototype.hasOwnProperty("isPrototypeOf")) {
16
+ return false;
17
+ }
18
+
19
+ return true;
20
+ }
@@ -0,0 +1,28 @@
1
+ export function snakeize<T>(obj: T): T {
2
+ if (!obj || typeof obj !== "object") {
3
+ return obj;
4
+ }
5
+ if (isDate(obj) || isRegex(obj)) {
6
+ return obj;
7
+ }
8
+ if (Array.isArray(obj)) {
9
+ return obj.map(snakeize) as T;
10
+ }
11
+ return Object.keys(obj).reduce((acc, key) => {
12
+ var camel =
13
+ key[0].toLowerCase() +
14
+ key.slice(1).replace(/([A-Z]+)/g, (_, x) => {
15
+ return "_" + x.toLowerCase();
16
+ });
17
+ acc[camel as keyof typeof acc] = snakeize(obj[key as keyof typeof acc]);
18
+ return acc;
19
+ }, {} as T);
20
+ }
21
+
22
+ function isDate(obj: unknown) {
23
+ return Object.prototype.toString.call(obj) === "[object Date]";
24
+ }
25
+
26
+ function isRegex(obj: unknown) {
27
+ return Object.prototype.toString.call(obj) === "[object RegExp]";
28
+ }
package/src/snakeize.d.ts DELETED
@@ -1 +0,0 @@
1
- declare module "snakeize";
@@ -1,16 +0,0 @@
1
- export default function stringinate(obj: {
2
- [key: string]: any;
3
- }): { [key: string]: any } {
4
- Object.keys(obj).forEach((property) => {
5
- if (obj[property] instanceof URL) {
6
- obj[property] = obj[property].toString();
7
- }
8
- if (typeof obj[property] === "object") {
9
- stringinate(obj[property]);
10
- }
11
-
12
- obj[property] = obj[property];
13
- });
14
-
15
- return obj;
16
- }