@nosto/nosto-react 2.2.2 → 2.3.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.
@@ -3,6 +3,7 @@ import { NostoContext, RecommendationComponent } from "../context"
3
3
  import type { ReactNode } from "react"
4
4
  import { ScriptLoadOptions } from "../hooks/scriptLoader"
5
5
  import { useLoadClientScript } from "../hooks/useLoadClientScript"
6
+ import { nostojs } from "@nosto/nosto-js"
6
7
 
7
8
  /**
8
9
  * @group Components
@@ -88,7 +89,7 @@ export function NostoProvider(props: NostoProviderProps) {
88
89
  const { clientScriptLoaded } = useLoadClientScript(props)
89
90
 
90
91
  if (clientScriptLoaded) {
91
- window.nostojs(api => {
92
+ nostojs(api => {
92
93
  api.defaultSession().setVariation(currentVariation!).setResponseMode(responseMode)
93
94
  })
94
95
  }
package/src/context.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { createContext, ReactElement } from "react"
2
- import { Recommendation, RenderMode } from "./types"
2
+ import { Recommendation } from "./types"
3
+ import { RenderMode } from "@nosto/nosto-js/client"
3
4
 
4
5
  type AnyFunction = (...args: unknown[]) => unknown
5
6
 
@@ -1,8 +1,8 @@
1
1
  import { useState, useEffect } from "react"
2
- import { isNostoLoaded } from "../components/helpers"
3
- import type { NostoClient } from "../types"
4
2
  import type { NostoProviderProps } from "../components/NostoProvider"
5
3
  import scriptLoaderFn from "./scriptLoader"
4
+ import { init, initNostoStub, isNostoLoaded, nostojs } from "@nosto/nosto-js"
5
+ import { reloadNosto } from "@nosto/nosto-js/testing"
6
6
 
7
7
  type NostoScriptProps = Pick<NostoProviderProps, "account" | "host" | "shopifyMarkets" | "loadScript" | "scriptLoader">
8
8
 
@@ -20,7 +20,7 @@ export function useLoadClientScript(props: NostoScriptProps) {
20
20
  function scriptOnload() {
21
21
  // Override for production scripts to work in unit tests
22
22
  if ("nostoReactTest" in window) {
23
- window.nosto?.reload({
23
+ reloadNosto({
24
24
  site: "localhost"
25
25
  })
26
26
  }
@@ -60,23 +60,27 @@ export function useLoadClientScript(props: NostoScriptProps) {
60
60
  }
61
61
  }
62
62
 
63
- // Load Nosto API stub
64
- if (!window.nostojs) {
65
- window.nostojs = (cb: (api: NostoClient) => void) => {
66
- (window.nostojs.q = window.nostojs.q || []).push(cb)
67
- }
68
- window.nostojs(api => api.setAutoLoad(false))
69
- }
63
+ initNostoStub()
70
64
 
71
65
  if (!loadScript) {
72
- window.nosto ? scriptOnload() : window.nostojs(scriptOnload)
66
+ nostojs(scriptOnload)
73
67
  return
74
68
  }
75
69
 
70
+ async function initClientScript() {
71
+ await init({
72
+ merchantId: account,
73
+ options: {
74
+ attributes: { "nosto-client-script": ""}
75
+ },
76
+ scriptLoader
77
+ })
78
+ scriptOnload()
79
+ }
80
+
76
81
  // Load Nosto client script if not already loaded externally
77
82
  if (!isNostoLoaded() && !shopifyMarkets) {
78
- const urlPartial = `/include/${account}`
79
- injectScriptElement(urlPartial)
83
+ initClientScript()
80
84
  }
81
85
 
82
86
  // Load Shopify Markets scripts
@@ -1,15 +1,16 @@
1
1
  import { DependencyList, useEffect } from "react"
2
2
  import { useNostoContext } from "./useNostoContext"
3
- import { NostoClient } from "../types"
4
3
  import { useDeepCompareEffect } from "./useDeepCompareEffect"
4
+ import { nostojs } from "@nosto/nosto-js"
5
+ import { API } from "@nosto/nosto-js/client"
5
6
 
6
- export function useNostoApi(cb: (api: NostoClient) => void, deps?: DependencyList, flags?: { deep?: boolean }): void {
7
+ export function useNostoApi(cb: (api: API) => void, deps?: DependencyList, flags?: { deep?: boolean }): void {
7
8
  const { clientScriptLoaded } = useNostoContext()
8
9
  const useEffectFn = flags?.deep ? useDeepCompareEffect : useEffect
9
10
 
10
11
  useEffectFn(() => {
11
12
  if (clientScriptLoaded) {
12
- window.nostojs(cb)
13
+ nostojs(cb)
13
14
  }
14
15
  }, [clientScriptLoaded, ...(deps ?? [])])
15
16
  }
@@ -1,8 +1,8 @@
1
1
  import { snakeize } from "../utils/snakeize"
2
- import { Order } from "../types"
3
2
  import { useRenderCampaigns } from "./useRenderCampaigns"
4
3
  import { useNostoApi } from "./useNostoApi"
5
4
  import { ToCamelCase } from "../utils/types"
5
+ import { WebsiteOrder as Order } from "@nosto/nosto-js/client"
6
6
 
7
7
  /**
8
8
  * @group Hooks
@@ -1,12 +1,13 @@
1
- import { Product } from "../types"
2
1
  import { useNostoApi } from "./useNostoApi"
3
2
  import { useRenderCampaigns } from "./useRenderCampaigns"
3
+ import { Product } from "@nosto/nosto-js/client"
4
4
 
5
5
  /**
6
6
  * @group Hooks
7
7
  */
8
8
  export type NostoProductProps = {
9
9
  product: string
10
+ reference?: string
10
11
  tagging?: Product
11
12
  placements?: string[]
12
13
  }
@@ -16,22 +17,27 @@ export type NostoProductProps = {
16
17
  *
17
18
  * @group Hooks
18
19
  */
19
- export function useNostoProduct({ product, tagging, placements }: NostoProductProps) {
20
+ export function useNostoProduct({ product, tagging, placements, reference }: NostoProductProps) {
20
21
  const { renderCampaigns } = useRenderCampaigns()
21
22
 
22
23
  if (tagging && !tagging.product_id) {
23
24
  throw new Error("The product object must contain a product_id property")
24
25
  }
25
26
 
27
+ const productId = tagging?.product_id ?? product
28
+
26
29
  useNostoApi(
27
30
  async api => {
28
- const data = await api
31
+ const action = api
29
32
  .defaultSession()
30
33
  .viewProduct(tagging ?? product)
31
34
  .setPlacements(placements || api.placements.getPlacements())
32
- .load()
35
+ if (reference) {
36
+ action.setRef(productId, reference)
37
+ }
38
+ const data = await action.load()
33
39
  renderCampaigns(data)
34
40
  },
35
- [product, tagging?.selected_sku_id]
41
+ [productId, tagging?.selected_sku_id]
36
42
  )
37
43
  }
@@ -1,8 +1,9 @@
1
1
  import { snakeize } from "../utils/snakeize"
2
- import { Cart as CartSnakeCase, Customer as CustomerSnakeCase } from "../types"
2
+ import { PushedCustomer as CustomerSnakeCase, Cart as CartSnakeCase } from "@nosto/nosto-js/client"
3
3
  import { ToCamelCase } from "../utils/types"
4
4
  import { useNostoContext } from "./useNostoContext"
5
5
  import { useDeepCompareEffect } from "./useDeepCompareEffect"
6
+ import { nostojs } from "@nosto/nosto-js"
6
7
 
7
8
  /**
8
9
  * @group Hooks
@@ -25,7 +26,7 @@ export function useNostoSession({ cart, customer }: NostoSessionProps = {}) {
25
26
  const currentCustomer = customer ? snakeize(customer) : undefined
26
27
 
27
28
  if (clientScriptLoaded) {
28
- window.nostojs(api => {
29
+ nostojs(api => {
29
30
  api.defaultSession().setCart(currentCart).setCustomer(currentCustomer).viewOther().load({ skipPageViews: true })
30
31
  })
31
32
  }
@@ -1,8 +1,10 @@
1
1
  import { cloneElement, useRef } from "react"
2
2
  import { createRoot, Root } from "react-dom/client"
3
- import { ActionResponse, Recommendation } from "../types"
3
+ import { Recommendation } from "../types"
4
4
  import { useNostoContext } from "./useNostoContext"
5
5
  import { RecommendationComponent } from "../context"
6
+ import { ActionResponse, API } from "@nosto/nosto-js/client"
7
+ import { nostojs } from "@nosto/nosto-js"
6
8
 
7
9
  type CampaignData = Pick<ActionResponse, "campaigns" | "recommendations">
8
10
 
@@ -18,11 +20,12 @@ function RecommendationComponentWrapper(props: {
18
20
  }
19
21
 
20
22
  function injectCampaigns(data: CampaignData) {
23
+ // @ts-expect-error not defined
21
24
  if (!window.nostojs) {
22
25
  throw new Error("Nosto has not yet been initialized")
23
26
  }
24
- window.nostojs(api => {
25
- api.placements.injectCampaigns(data.recommendations)
27
+ nostojs(api => {
28
+ api.placements.injectCampaigns(data.recommendations as Parameters<API['placements']['injectCampaigns']>[0])
26
29
  })
27
30
  }
28
31
 
package/src/index.ts CHANGED
@@ -1,4 +1,5 @@
1
- export type { Cart, Customer, Product, Order, Recommendation } from "./types"
1
+ export type { Product, PushedCustomer as Customer, Cart, WebsiteOrder as Order } from "@nosto/nosto-js/client"
2
+ export type { Recommendation } from "./types"
2
3
  export { type ScriptLoadOptions } from "./hooks/scriptLoader"
3
4
  export { NostoContext, type NostoContextType } from "./context"
4
5
  export { useNostoContext } from "./hooks/useNostoContext"