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
Yarn
pnpm
npm install @tiendanube/nube-sdk-helper @tiendanube/nube-sdk-types
yarn add @tiendanube/nube-sdk-helper @tiendanube/nube-sdk-types
pnpm add @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.
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 delApp).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();
}
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);
}
}
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`);
}
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:
| Guard | Estrecha a |
|---|---|
isProductPage | ProductPage |
isCategoryPage | CategoryPage |
isCheckoutPage | CheckoutPage |
isAllProductsPage | AllProductsPage |
isSearchPage | SearchPage |
isHomePage | HomePage |
isAccountPage | AccountPage |
isAccountLoginPage | AccountLoginPage |
isAccountRegisterPage | AccountRegisterPage |
isAccountInfoPage | AccountInfoPage |
isAccountResetPage | AccountResetPage |
isAccountNewPasswordPage | AccountNewPasswordPage |
isAccountOrdersPage | AccountOrdersPage |
Carrito — reciben unknown y validan la estructura:
| Guard | Estrecha a |
|---|---|
isCart | Cart |
isCartItem | CartItem |
isCartValidationSuccess | validación de carrito exitosa |
isCartValidationPending | validación de carrito pendiente |
isCartValidationFail | validación de carrito fallida |
Dominio — reciben unknown y validan la estructura:
| Guard | Estrecha a |
|---|---|
isStore | Store |
isCustomer | Customer |
isPayment | Payment |
isShipping | Shipping |
isShippingOption | ShippingOption |
Dirección — reciben unknown y validan la estructura:
| Guard | Estrecha a |
|---|---|
isAddress | Address |
isShippingAddress | ShippingAddress |
isBillingAddress | BillingAddress |
Componentes y datos de página — útiles para comprobar el formato de page.data antes de acceder a él:
| Guard | Estrecha a |
|---|---|
isNubeComponent | NubeComponent |
hasProductList | { products: ProductDetails[] } |
hasSections | { sections: unknown[] } |
isSectionWithProducts | una 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, component: RenderableComponent): void
ui.renderAll(slots: UISlot[], component: RenderableComponent): void
showToast— muestra un toast en la esquina superior derecha.variantes"success" | "error" | "warning" | "info".clear— limpia un slot (nube.clearSlot).render— renderiza un componente en un slot.renderAll— renderiza el mismo componente en varios slots en una sola llamada.
Tipos relacionados: ToastVariant, RenderableComponent, UIHelper.
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");
}
navigate(route)
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
Help us improve NubeSDK
Found an issue or have a suggestion? Let us know on GitHub.