Saltar al contenido principal

SDK Helper

Las apps NubeSDK se ejecutan dentro de un web worker aislado, sin acceso directo al DOM. Todo lo que hace la app: leer el estado, renderizar componentes, navegar y almacenar datos pasa por la instancia del SDK que el runtime entrega al punto de entrada App(nube).

En la práctica, esa instancia nube termina pasando por todas las funciones y componentes de la app, y algunos patrones se repiten en cada proyecto: leer la página actual, estrechar tipos de página, renderizar un componente por producto, mostrar un toast al recibir un evento.

@tiendanube/nube-sdk-helper concentra esos patrones en un conjunto de utilidades pequeño y fuertemente tipado.

Instalación

npm install @tiendanube/nube-sdk-helper @tiendanube/nube-sdk-types

@tiendanube/nube-sdk-types es una peer dependency y debe instalarse junto con el paquete helper.

Registrar la instancia

El runtime entrega la instancia del SDK solo como argumento del punto de entrada. La idea central del helper es simple: registrá una vez, y todos los demás helpers llegan a ella por su cuenta, sin necesidad de pasar nube por toda la jerarquía de la app.

src/App.ts
import {
setNubeInstance,
getCurrentState,
ui,
} from "@tiendanube/nube-sdk-helper";
import type { NubeSDK } from "@tiendanube/nube-sdk-types";

export function App(nube: NubeSDK) {
setNubeInstance(nube); // call this first, before anything else

const state = getCurrentState();
ui.showToast(`You are on the ${state.location.page.type} page`);
}

Tres funciones gestionan la instancia:

  • setNubeInstance(nube): registra la instancia (llamá una vez al inicio del App).
  • getNubeInstance(): devuelve la instancia registrada, lanzando un error descriptivo si aún no fue registrada.
  • clearNubeInstance(): limpia la instancia (útil en tests).

Por qué esto importa

Con la instancia registrada globalmente, las acciones más comunes se convierten en funciones independientes que podés llamar desde cualquier lugar: un componente anidado, un módulo utilitario, un event handler, sin necesidad de recibir nube como parámetro.

import { navigate, setNubeInstance, ui } from "@tiendanube/nube-sdk-helper";
import type { NubeSDK } from "@tiendanube/nube-sdk-types";

export function App(nube: NubeSDK) {
setNubeInstance(nube); // call this first, before any other helper
}

// En cualquier otra parte de la app, sin `nube` en el scope:
function onCheckoutClick() {
navigate("/checkout"); // routes to the path internally via the SDK instance
ui.showToast("Taking you to checkout...", "info");
}

Sin el helper, sería necesario tener una referencia a nube en el scope y llamar a nube.getBrowserAPIs().navigate(...), además de construir el componente de toast a mano. El helper reduce ambos a una sola línea.

Lo mismo aplica para el almacenamiento en el browser:

import { browser, setNubeInstance } from "@tiendanube/nube-sdk-helper";
import type { NubeSDK } from "@tiendanube/nube-sdk-types";

export async function App(nube: NubeSDK) {
setNubeInstance(nube); // call this first, before any other helper

await browser.asyncLocalStorage.setItem("seen-banner", "true");
const seen = await browser.asyncLocalStorage.getItem("seen-banner");
}

Leer el estado con selectores

Los selectores siguen un patrón consistente: llamados sin argumento, leen el estado actual del SDK; pasando un estado explícito, se convierten en funciones puras.

import {
getCartItems,
getCustomer,
getPageType,
setNubeInstance,
} from "@tiendanube/nube-sdk-helper";
import type { NubeSDK } from "@tiendanube/nube-sdk-types";

export function App(nube: NubeSDK) {
setNubeInstance(nube); // call this first, before any other helper

// Sin argumento: lee el estado actual de la instancia del SDK.
const items = getCartItems();
const pageType = getPageType();
const customer = getCustomer();
}
Testeabilidad

Pasá un estado mock a cualquier selector y se comporta como una función pura: sin efectos secundarios, sin depender de la instancia registrada. Este patrón aplica a toda la familia de selectores.

Guards

Los guards cumplen una doble función: validan en runtime y estrechan el tipo para TypeScript, desbloqueando los datos específicos de la página tipados por el compilador.

import {
getCurrentState,
isProductPage,
setNubeInstance,
} from "@tiendanube/nube-sdk-helper";
import type { NubeSDK } from "@tiendanube/nube-sdk-types";

export function App(nube: NubeSDK) {
setNubeInstance(nube); // call this first, before any other helper

const { page } = getCurrentState().location;

if (isProductPage(page)) {
// `page` is now narrowed to a ProductPage, so `page.data.product` is typed.
console.log(page.data.product.name);
}
}
Validación y tipado juntos

A diferencia de un cast (as ProductPage), los guards verifican la estructura en runtime antes de estrechar el tipo. Si la condición no pasa, TypeScript no expone page.data.product.

Hay un guard para casi toda estructura encontrada en una app NubeSDK:

  • Páginas: isProductPage, isCategoryPage, isCheckoutPage, isHomePage, isAllProductsPage, isSearchPage
  • Carrito: isCart, isCartItem, isCartValidationSuccess, isCartValidationPending, isCartValidationFail
  • Dominio: isStore, isCustomer, isPayment, isShipping, isAddress, y más
  • Componentes / datos de página: isNubeComponent, hasProductList, hasSections, hasSingleProduct, isSectionWithProducts

Getters

Además de los selectores de estado, los getters exponen los metadatos inyectados por el runtime sobre la app. Uno útil es getScriptURL, que analiza la URL desde donde se cargó el script de la app (cacheada como una URL congelada):

import {
getScriptParam,
getScriptURL,
setNubeInstance,
} from "@tiendanube/nube-sdk-helper";
import type { NubeSDK } from "@tiendanube/nube-sdk-types";

export function App(nube: NubeSDK) {
setNubeInstance(nube); // call this first, before any other helper

const url = getScriptURL();
console.log("Script origin:", url.origin);
console.log("Script pathname:", url.pathname);

// Read configuration passed as query params on the script URL, e.g. ?variant=b
const variant = getScriptParam("variant"); // string | null
}

Esta es la forma idiomática de configurar una app desde la tag de script, sin necesidad de una solicitud adicional.

Page matching

pageMatch y onPage resuelven el mismo problema desde dos ángulos. pageMatch despacha una vez contra un estado provisto, y cada handler recibe el payload correctamente tipado para su página. onPage envuelve pageMatch, pero suscribe a la navegación, re-ejecutándose en cada cambio de página y devolviendo una función de cancelación.

Usá pageMatch para una decisión puntual basada en el estado actual:

import {
getCurrentState,
pageMatch,
setNubeInstance,
} from "@tiendanube/nube-sdk-helper";
import type { NubeSDK } from "@tiendanube/nube-sdk-types";

export function App(nube: NubeSDK) {
setNubeInstance(nube); // call this first, before any other helper

// Runs once against the state you pass in.
pageMatch(getCurrentState(), {
product: (state, product) => console.log("Product:", product.name),
checkout: (state, checkout) => console.log("Step:", checkout.step),
});
}

Usá onPage para reaccionar continuamente a la navegación del usuario:

import { onPage, setNubeInstance } from "@tiendanube/nube-sdk-helper";
import type { NubeSDK } from "@tiendanube/nube-sdk-types";

export function App(nube: NubeSDK) {
setNubeInstance(nube); // call this first, before any other helper

const stop = onPage({
product: (state, product) => console.log("Viewing product:", product.id),
checkout: (state, checkout) => {
if (checkout.step === "success") console.log("Purchase complete");
},
// category / home handlers are optional
});

// Call stop() later, when you no longer need to react to navigation.
void stop;
}

Para checkout específicamente, onCheckoutStep permite reaccionar a un step particular:

import { onCheckoutStep, setNubeInstance } from "@tiendanube/nube-sdk-helper";
import type { NubeSDK } from "@tiendanube/nube-sdk-types";

export function App(nube: NubeSDK) {
setNubeInstance(nube); // call this first, before any other helper

onCheckoutStep({
success: () => console.log("Purchase complete"),
});
}

Render

Una necesidad frecuente es renderizar algo en un slot de grilla de producto: un badge, un label, un ícono. forEachProduct extrae todos los productos del estado actual (independientemente del tipo de página), los mapea a través de una factory de renderizado, descarta resultados vacíos y asigna automáticamente un key único a partir del id del producto.

import {
forEachProduct,
onPage,
setNubeInstance,
} from "@tiendanube/nube-sdk-helper";
import type { NubeSDK } from "@tiendanube/nube-sdk-types";
import { Badge } from "./components/Badge";

export function App(nube: NubeSDK) {
setNubeInstance(nube);

// Renderiza un badge sobre cada imagen de producto en la grilla del home.
onPage({
home: () => {
nube.render(
"product_grid_item_image_center_center",
forEachProduct((product) => <Badge product={product} />),
);
},
});
}

Sin JSX, la factory devuelve un objeto de componente directamente:

import {
forEachProduct,
onPage,
setNubeInstance,
} from "@tiendanube/nube-sdk-helper";
import type { NubeSDK } from "@tiendanube/nube-sdk-types";

export function App(nube: NubeSDK) {
setNubeInstance(nube); // call this first, before any other helper

onPage({
home: () => {
nube.render(
"product_grid_item_image_bottom_right",
forEachProduct((product) => ({ type: "txt", children: product.name })),
);
},
});
}

Devolver null o undefined desde la factory omite el producto: esas entradas se filtran automáticamente.

Helpers de UI y eventos

ui agrupa las operaciones de vista más comunes, incluyendo renderizar el mismo componente en múltiples slots en una sola llamada:

import { setNubeInstance, ui } from "@tiendanube/nube-sdk-helper";
import type { NubeSDK } from "@tiendanube/nube-sdk-types";

export function App(nube: NubeSDK) {
setNubeInstance(nube); // call this first, before any other helper

ui.renderAll(["corner_top_left", "corner_top_right"], {
type: "txt",
children: "Hi",
});
ui.showToast("Done!", "success");
ui.clear("corner_top_right");
}

onEvent y toastOn reducen el patrón repetitivo de "escuchar y reaccionar" a una línea cada uno, ambos devolviendo una función de cancelación:

import { onEvent, setNubeInstance, toastOn } from "@tiendanube/nube-sdk-helper";
import type { NubeSDK } from "@tiendanube/nube-sdk-types";

export function App(nube: NubeSDK) {
setNubeInstance(nube); // call this first, before any other helper

const off = onEvent("cart:update", (state) => {
console.log("items:", state.cart.items.length);
});

// Call off() later, when you no longer need it.
void off;

toastOn("cart:add:success", "Added to cart", "success");
toastOn("cart:update", (state) => `Cart: ${state.cart.items.length} items`);
}

Descubrimiento de slots

Los slots de una página no son fijos. En temas sectionable, la persona dueña de la tienda agrega, elimina y reordena secciones dinámicas, así que el mismo slot lógico puede existir varias veces, en otra posición, o no existir. Además, la misma sección a veces se expone con nombres distintos como slot estático y como slot dinámico — por ejemplo after_section_products_featured versus after_dynamic_section_featured_products. En la práctica, esto empuja a las apps a hardcodear nombres de slot y adivinar tema por tema.

Los helpers de slot envuelven nube.api.getAvailableSlots() para responder las preguntas que la app realmente tiene — ¿qué slots existen acá? y ¿dónde está la primera/última sección de este tipo? — y devuelven un slot listo para ui.render, o null cuando nada coincide.

Disponibilidad

El descubrimiento de slots depende de la API getAvailableSlots(), que no está disponible en el tema Patagonia ni en el Checkout por el momento. En esos contextos las consultas no devuelven slots.

Listar los slots de la página

Tres funciones asíncronas exponen el registro de slots de la página actual:

import {
getAvailableSlots,
getDynamicSlots,
getStaticSlots,
setNubeInstance,
} from "@tiendanube/nube-sdk-helper";
import type { NubeSDK } from "@tiendanube/nube-sdk-types";

export async function App(nube: NubeSDK) {
setNubeInstance(nube); // call this first, before any other helper

// Todos los slots de la página, separados por tipo.
const { static: statics, dynamic: dynamics } = await getAvailableSlots();

// Solo los puntos de inyección fijos del tema, direccionables por `slotId`.
const fixed = await getStaticSlots();
const hasNewsletter = fixed.some(
(slot) => slot.slotId === "before_section_newsletter",
);

// Solo los slots dinámicos, cada uno con las coordenadas de su sección.
const sections = await getDynamicSlots();
const featured = sections.filter(
(slot) => slot.sectionType === "featured_products",
);
}

getDynamicSlots() devuelve los slots crudos: cada uno lleva el sectionType que la sección realmente tiene en la página, sin resolución de nombres equivalentes. Para eso, usá las consultas de sección de abajo.

Encontrar el slot de una sección

Cuatro consultas responden "¿dónde está la sección X?" y devuelven un slot listo para renderizar:

import {
afterLastSection,
beforeFirstSection,
setNubeInstance,
ui,
} from "@tiendanube/nube-sdk-helper";
import type { NubeSDK } from "@tiendanube/nube-sdk-types";
import { Text } from "@tiendanube/nube-sdk-jsx";

function Component() {
return <Text>Hello</Text>;
}

export function App(nube: NubeSDK) {
setNubeInstance(nube); // call this first, before any other helper

// `ui.render` acepta la promise directamente y no renderiza nada si es `null`.
ui.render(beforeFirstSection("newsletter"), <Component />);
ui.render(afterLastSection("newsletter"), <Component />);
}

Cada consulta sigue el mismo orden de resolución:

  1. Primero las secciones dinámicas. Filtra los slots dinámicos por tipo de sección y por posición (before / after), y elige el de menor sectionIndex (first) o el de mayor sectionIndex (last). Esto funciona sin importar cuántas secciones de ese tipo existan ni dónde estén en la página.
  2. Fallback al slot estático. Si el tema no tiene ninguna sección dinámica que coincida, busca el slot estático ${posición}_section_${tipo} — por ejemplo before_section_newsletter. Los slots estáticos son únicos, así que beforeFirstSection y beforeLastSection devuelven el mismo slot en ese caso.
  3. Nada encontrado. Registra un error SlotNotFound en la consola y resuelve a null.

Nombres de sección equivalentes

Los slots estáticos se nombraron según la sección que envuelven (products_featured), mientras que las secciones dinámicas se nombraron según los datos de página que las alimentan (featured_products). La misma sección, entonces, responde a dos nombres según si el tema la renderiza como sección fija o dinámica.

El helper mantiene internamente una tabla de equivalencias (hoy featured_productsproducts_featured) y ejecuta cada consulta sobre el tipo pedido y sus alias, probando primero la forma que la app usó. El resultado práctico: tu app sigue pasando el nombre que conoce, y la sección se encuentra de cualquier manera.

// Ambas llamadas encuentran la misma sección, sea estática o dinámica.
ui.render(afterLastSection("featured_products"), <Component />);
ui.render(afterLastSection("products_featured"), <Component />);

Los tipos de sección desconocidos se aceptan y resuelven a sí mismos, lo que cubre secciones personalizadas cuyo nombre solo existe en runtime. El tipo SectionType sugiere los nombres conocidos en el autocompletado, pero acepta cualquier string.

Cuando nada coincide

Una consulta que no encuentra nada no lanza excepción: registra un SlotNotFound en la consola y resuelve a null, de modo que un slot ausente se degrada a "nada renderizado" en lugar de romper la app. Al pasar la promise a ui.render, ese caso ya está resuelto. Si preferís usar await, verificá el resultado:

const slot = await beforeFirstSection("products_featured");

if (slot) {
ui.render(slot, <Component />);
}

Referencia de la API

Referencia formal de cada símbolo exportado en la raíz del paquete (@tiendanube/nube-sdk-helper).

Instancia

Gestionan la instancia del SDK que usa el resto del helper.

setNubeInstance(nube)

Registra la instancia de NubeSDK para la app actual. Llámala una vez, al inicio de App(nube).

setNubeInstance(nube: Readonly<NubeSDK>): void

getNubeInstance()

Devuelve la instancia registrada. Si no se registró ninguna, recurre a self.__SDK_INSTANCE__ y, en ausencia de ambas, lanza un error descriptivo.

getNubeInstance(): Readonly<NubeSDK>

clearNubeInstance()

Limpia la instancia registrada. Útil en tests o al reinicializar la app.

clearNubeInstance(): void

Getters

Exponen el estado actual y los metadatos que el runtime inyecta sobre la app.

getCurrentState()

Devuelve el estado actual (readonly) del SDK.

getCurrentState(): Readonly<NubeSDKState>

getAppData()

Devuelve los datos de la app inyectados por el runtime: id y script.

getAppData(): Readonly<{ id: string; script: string }>

getScriptURL()

Devuelve la URL desde la que se cargó el script de la app, como una instancia URL congelada (cacheada en la primera llamada).

getScriptURL(): Readonly<URL>

getScriptSearchParams()

Devuelve los URLSearchParams (readonly) de la URL del script.

getScriptSearchParams(): Readonly<URLSearchParams>

getScriptParam(key)

Devuelve el valor de un query param específico de la URL del script, o null si no está presente. Es la forma idiomática de configurar una app desde la etiqueta de script, sin una petición adicional.

getScriptParam(key: string): Nullable<string>

Selectores de estado

Accesores enfocados en las porciones más leídas del estado. Todos aceptan un state opcional; cuando se omite, leen el estado actual de la instancia registrada (pasa un estado explícito para volverlos puros).

getCart(state?: NubeSDKState): Cart
getCartItems(state?: NubeSDKState): CartItem[]
getPageType(state?: NubeSDKState): Page["type"] // ej.: "home", "product", "checkout"
getCustomer(state?: NubeSDKState): Nullable<Customer> // null cuando no está disponible en la página

Guards

Los guards cumplen doble función: validan en runtime y estrechan el tipo para TypeScript. A diferencia de un cast (as ProductPage), verifican la estructura antes de estrechar — si la comprobación falla, el tipo no se expone.

import {
getCurrentState,
isProductPage,
setNubeInstance,
} from "@tiendanube/nube-sdk-helper";
import type { NubeSDK } from "@tiendanube/nube-sdk-types";

export function App(nube: NubeSDK) {
setNubeInstance(nube); // call this first, before any other helper

const { page } = getCurrentState().location;
if (isProductPage(page)) {
// `page` se estrechó a ProductPage, así que `page.data.product` está tipado.
console.log(page.data.product.name);
}
}

Páginas — reciben un Page y estrechan al tipo de página correspondiente:

GuardEstrecha a
isProductPageProductPage
isCategoryPageCategoryPage
isCheckoutPageCheckoutPage
isAllProductsPageAllProductsPage
isSearchPageSearchPage
isHomePageHomePage
isAccountPageAccountPage
isAccountLoginPageAccountLoginPage
isAccountRegisterPageAccountRegisterPage
isAccountInfoPageAccountInfoPage
isAccountResetPageAccountResetPage
isAccountNewPasswordPageAccountNewPasswordPage
isAccountOrdersPageAccountOrdersPage

Carrito — reciben unknown y validan la estructura:

GuardEstrecha a
isCartCart
isCartItemCartItem
isCartValidationSuccessvalidación de carrito exitosa
isCartValidationPendingvalidación de carrito pendiente
isCartValidationFailvalidación de carrito fallida

Dominio — reciben unknown y validan la estructura:

GuardEstrecha a
isStoreStore
isCustomerCustomer
isPaymentPayment
isShippingShipping
isShippingOptionShippingOption

Dirección — reciben unknown y validan la estructura:

GuardEstrecha a
isAddressAddress
isShippingAddressShippingAddress
isBillingAddressBillingAddress

Componentes y datos de página — útiles para comprobar el formato de page.data antes de acceder a él:

GuardEstrecha a
isNubeComponentNubeComponent
hasProductList{ products: ProductDetails[] }
hasSections{ sections: unknown[] }
isSectionWithProductsuna sección que contiene products
hasSingleProduct{ product: ProductDetails }

Page matching

pageMatch(state, handlers)

Despacha al handler correspondiente al tipo de página en el estado que le pases. Cada handler recibe el payload correctamente tipado para su página. Se ejecuta una vez.

pageMatch(state: NubeSDKState, handlers: PageHandlers): void

onPage(handlers)

Se suscribe al evento page:loaded y llama al handler correspondiente en cada navegación. Devuelve una función de cancelación.

onPage(handlers: PageHandlers): () => void

onCheckoutStep(handlers)

Escucha checkout:ready y, cuando la página actual es un checkout, invoca el handler registrado para el step actual. También se ejecuta de inmediato para el step corriente si ya está en el checkout. Devuelve una función de cancelación.

onCheckoutStep(handlers: CheckoutStepHandlers): () => void

Tipos relacionados: PageDataMap, PageHandlerFunction<T>, PageHandlers, CheckoutStepHandlers.

Render

getProductsFromState(state)

Extrae todos los productos del estado, sin importar el tipo de página (listas directas, productos dentro de secciones y el producto principal en páginas de detalle). Devuelve un array vacío si no hay productos.

getProductsFromState(state: NubeSDKState): ProductDetails[]

forEachProduct(renderFactory)

Crea una función de render que extrae los productos del estado, mapea cada uno con renderFactory, descarta los resultados null/undefined y asigna automáticamente una key única a partir del id del producto.

forEachProduct(
renderFactory: (product: ProductDetails) => NubeComponent | null | undefined,
): (state: NubeSDKState) => NubeComponent[]

UI

ui es un objeto congelado con cuatro helpers de vista.

ui.showToast(message: string, variant?: ToastVariant): void  // variant por defecto "info"
ui.clear(slot: UISlot): void
ui.render(slot: UISlot | StaticSlot | DynamicSlot, component: RenderableComponent): void
ui.render(slot: Promise<QuerySlotResult>, component: RenderableComponent): void
ui.renderAll(slots: UISlot[], component: RenderableComponent): void
  • showToast — muestra un toast en la esquina superior derecha. variant es "success" | "error" | "warning" | "info".
  • clear — limpia un slot (nube.clearSlot). No acepta promises.
  • render — renderiza un componente en un slot. Acepta un nombre de slot, un descriptor StaticSlot / DynamicSlot, o la promise devuelta por una consulta de sección : en ese caso espera la resolución, no renderiza nada si el resultado es null y registra cualquier error en la consola.
  • renderAll — renderiza el mismo componente en varios slots en una sola llamada.

Tipos relacionados: ToastVariant, RenderableComponent, UIHelper, QuerySlotResult.

Descubrimiento de slots

Consultas sobre los slots disponibles en la página actual, construidas sobre nube.api.getAvailableSlots() . Todas son asíncronas y todas lanzan un error si no se registró ninguna instancia del SDK. Disponibles a partir de la versión 0.3.0 del helper.

getAvailableSlotsAPI()

Devuelve el adaptador de available slots de la instancia registrada. Se resuelve una vez y se memoiza durante toda la vida de la app, así que las consultas repetidas reutilizan el mismo canal de comandos.

getAvailableSlotsAPI(): AvailableSlotsCommands

getAvailableSlots()

Todos los slots de la página actual, separados por tipo.

getAvailableSlots(): Promise<{ static: StaticSlot[]; dynamic: DynamicSlot[] }>

getStaticSlots()

Solo los slots estáticos: los puntos de inyección fijos del tema, direccionables por su slotId.

getStaticSlots(): Promise<StaticSlot[]>

getDynamicSlots()

Solo los slots dinámicos. Cada uno lleva las coordenadas de su sección (sectionType, sectionId, sectionIndex), que es lo que permite elegir una instancia específica cuando la sección se repite. Los sectionType llegan tal como están en la página, sin resolución de nombres equivalentes.

getDynamicSlots(): Promise<DynamicSlot[]>

Consultas de sección

Encuentran el slot antes/después de la primera/última sección de un tipo. Buscan primero en las secciones dinámicas (por el menor o mayor sectionIndex) y, si no hay ninguna, caen al slot estático ${posición}_section_${tipo}. Como el slot estático es único, first y last devuelven el mismo slot en ese fallback. Cuando nada coincide, registran un SlotNotFound en la consola y resuelven a null.

beforeFirstSection(sectionType: SectionType): Promise<QuerySlotResult>
afterFirstSection(sectionType: SectionType): Promise<QuerySlotResult>
beforeLastSection(sectionType: SectionType): Promise<QuerySlotResult>
afterLastSection(sectionType: SectionType): Promise<QuerySlotResult>

Las consultas se ejecutan sobre el tipo pedido y sus nombres equivalentes, probando primero la forma que la app usó — ver Nombres de sección equivalentes .

SlotNotFound

Error que describe una consulta que no encontró nada. Las consultas no lo lanzan: lo registran vía SlotNotFound.log y devuelven null.

class SlotNotFound extends Error {
constructor(queryDescription: string, appid: string | number);
static log(queryDescription: string): void;
}

Tipos relacionados:

type QuerySlotResult = StaticSlot | DynamicSlot | null;
type SectionType = "newsletter" | "products_sale" | "products_new" | "products_featured" | "featured_products" | (string & {});

SectionType sugiere los nombres conocidos en el autocompletado, pero acepta cualquier string, para cubrir secciones personalizadas y dinámicas cuyo nombre solo se conoce en runtime.

Eventos

Wrappers ergonómicos alrededor de nube.on que devuelven una función de cancelación.

onEvent(event, listener)

Equivalente a nube.on(event, listener), pero la función devuelta desregistra el listener vía nube.off — sin necesidad de guardar referencia a la instancia y al listener para limpiarlo.

onEvent<T extends NubeSDKListenableEvent>(
event: T,
listener: EventListenerMap[T],
): () => void

toastOn(event, message, variant?)

Muestra un toast cada vez que el evento se dispara. El mensaje puede ser una cadena estática o una función que lo deriva del estado. Devuelve una función de cancelación.

toastOn<T extends NubeSDKListenableEvent>(
event: T,
message: string | ((state: Readonly<NubeSDKState>) => string),
variant?: ToastVariant,
): () => void

Browser

Acceso a las Browser APIs (storage, navegación) a través de la instancia del SDK. Ver también Browser APIs .

browser

Objeto que expone las Browser APIs (asyncLocalStorage, asyncSessionStorage, navigate, ...). Se materializa de forma lazy en el primer acceso a una propiedad y se cachea.

import { browser, setNubeInstance } from "@tiendanube/nube-sdk-helper";
import type { NubeSDK } from "@tiendanube/nube-sdk-types";

export async function App(nube: NubeSDK) {
setNubeInstance(nube); // call this first, before any other helper

await browser.asyncLocalStorage.setItem("seen-banner", "true");
const seen = await browser.asyncLocalStorage.getItem("seen-banner");
}

Navega a una ruta dentro del dominio de la tienda. La ruta debe empezar con /.

navigate(route: `/${string}`): void

clearBrowserCache()

Limpia la caché interna de las Browser APIs, forzando una nueva instancia en el próximo acceso. Útil en tests.

clearBrowserCache(): void

Utilidades

Funciones de propósito general, independientes de la instancia del SDK.

deepClone(obj)

Clona un valor en profundidad. Usa structuredClone cuando está disponible (lo está, en el runtime del worker de NubeSDK), con fallback a serialización JSON.

deepClone<T>(obj: T): T

debounce(func, wait)

Devuelve una versión debounced de la función, que solo se ejecuta tras wait ms sin nuevas llamadas.

debounce<T extends (...args: never[]) => unknown>(
func: T,
wait: number,
): (...args: Parameters<T>) => void

throttle(func, limit)

Devuelve una versión throttled de la función, que se ejecuta como máximo una vez cada limit ms.

throttle<T extends (...args: never[]) => unknown>(
func: T,
limit: number,
): (...args: Parameters<T>) => void

Próximos pasos

  • Events — Lista completa de eventos disponibles en NubeSDK
  • State — Estructura de estado de NubeSDK
  • UI Slots — Slots disponibles para renderizado

Help us improve NubeSDK

Found an issue or have a suggestion? Let us know on GitHub.