Passa al contenuto principale

@webround/commerce

La logica di uno store, in TypeScript, senza interfaccia e senza framework (ESM, Node 22 o successivo).

Crea lo store​

import { createCommerce } from '@webround/commerce';

const commerce = createCommerce({
storeId: '<id dello store>',
commerceApiUrl: 'https://commerce-api.webround.com',
catalogApiUrl: 'https://catalog-api.webround.com',
checkoutApiUrl: 'https://checkout-api.webround.com',
});

createCommerce costruisce insieme ciò che a una pagina serve di uno store: auth, catalog, cart, checkout, account, addresses, orders, returns, wishlist, reviews e la cache che condividono. Senza checkoutApiUrl lo store funziona e il checkout fallisce dove lo usi, dicendo perché. Altre opzioni: returnUrls (dove torna il cliente dopo aver pagato), cartStorage (dove si tiene il carrello di un ospite: localStorage di base), langCode e cartPricing.

commerce.catalog ha le chiamate dell'API del catalogo e restituisce ciò che risponde:

  • products.search(input): una pagina di prodotti ({ data, pagination }).
  • products.getBySlug(variantSlug, input) e products.getById(id, input): un prodotto con le sue varianti. Lo slug appartiene a una variante, non a un prodotto.
  • products.getReviews(...) e products.getRelated(...).
  • storeData.get(...): i dati dello store (tag, collezioni, filtri, valute, e le impostazioni di recensioni e lista desideri), da cui si disegnano i controlli.

La cache tiene le risposte per tutta la visita: la stessa domanda fatta da più punti è una sola richiesta, un errore non viene mai tenuto, e commerce.catalog.invalidate(...) dimentica ciò che vuoi richiedere.

Lo shop​

Le regole di uno shop (cosa ha scelto un cliente e come diventa una ricerca) sono funzioni pure su ShopState: una collezione, un testo, valori di tag, un intervallo per ogni filtro, un ordinamento e una pagina. Ogni modifica restituisce un nuovo stato (setRange, toggleTagValue, setSort…) e riporta alla pagina 1, tranne setPage. toSearch(state, storeData, context) lo trasforma nella ricerca del catalogo e non lancia mai errori. createShopStore tiene lo stato in memoria, o nella barra degli indirizzi con createAddressShopStore, così una ricerca è un link e "indietro" ripercorre le scelte. Nell'indirizzo, q è il testo, tags i valori di tag, r.<filtro>=min..max un intervallo, sort=<campo>:<asc|desc> l'ordine, e page e limit.

Clienti​

commerce.auth è la sessione: signup, login, verifyTwoFactor, logout, refresh. Lo stato è unknown, signedOut, signingIn, challenge (serve il codice dell'app di autenticazione) o signedIn.

  • Il token (JWT) del cliente dura un'ora e si tiene in memoria. Ciò che sopravvive a un ricaricamento è il cookie di refresh dello store, che JavaScript non vede mai.
  • Il token si rinnova un minuto prima della scadenza, e di nuovo se una richiesta torna 401. Molte richieste rifiutate insieme sono un solo rinnovo.
  • Una chiamata che fallisce lancia ciò che ha detto lo store: spetta al form che l'ha fatta.
  • L'autenticazione a due fattori ne fa parte, come le richieste del cliente sul proprio account (commerce.account): reset della password, verifica dell'email, cancellazione dell'account, configurazione dei due fattori e newsletter.

Carrello​

commerce.cart funziona in due modi con le stesse chiamate:

  • Un ospite ha le righe nel browser (wrCart_<storeId> in localStorage), e lo store le prezza.
  • Un cliente ha il carrello dello store: ogni azione è una chiamata. Quando un ospite fa il login, le sue righe vengono unite al carrello del cliente, e dimenticate nel browser solo quando lo store le ha.

Le azioni sono add({ variantId, priceId, quantity }) (aggiunge a una variante già presente), setQuantity(variantId, quantity), remove(variantId), clear() e refresh(). Lo stato ha ciò che il carrello è (lines, count), noto subito, a parte ciò che costa (priced, e isStale quando è indietro di una modifica). Un carrello ha al massimo 99 varianti diverse e una sola valuta e cadenza; un'azione rifiutata lancia ciò che ha detto lo store, e il carrello torna a ciò che lo store ha.

Checkout​

commerce.checkout usa l'API del checkout, con lo stesso token del cliente.

  • quote() è l'anteprima: quanto costa il carrello con le regole dello store e gli hook. Non cambia niente e non viene mai messa in cache: chiederla di nuovo annulla quella in corso. Le righe senza giacenza sufficiente non sono un errore: si mettono da parte in quote.unavailable, e items e totals contano solo ciò che si può comprare.
  • pay(returnUrls?) riserva la giacenza, crea l'ordine e risponde { url, orderId, reference }: mandi il cliente a url. Non fa il redirect da solo.
  • Ciò che il cliente ha scelto (la consegna di ogni variante, gli indirizzi, il metodo di spedizione, i codici promozionali, l'email di un ospite, la fattura) è in state; le righe sono quelle del carrello e qui non si tengono.
  • Dopo il pagamento, nella pagina di successo, commerce.checkout.complete() svuota il carrello e dimentica le scelte.

Lo store rifiuta di proposito con un codice: CHECKOUT_BLOCKED (un hook di validazione), CHECKOUT_HOOK_FAILED e SHIPPING_METHOD_UNAVAILABLE. checkoutRefusalOf(error) lo legge. Se non resta niente da pagare, pay lancia NOTHING_TO_PAY senza chiedere allo store.

Cosa ha un cliente​

  • commerce.addresses: la rubrica di un cliente, tenuta dallo store; gli indirizzi di un ospite stanno in memoria per la pagina. remember(input) tiene un indirizzo appena ricevuto dal checkout.
  • commerce.orders: gli ordini e gli abbonamenti del cliente, una pagina alla volta, come risorse della cache.
  • commerce.returns: le richieste di reso di un cliente (create, cancel) e il flusso dell'ospite: guest.requestLink({ customerEmail, orderId | reference }) fa inviare dallo store un link alla pagina /returns?token=… del tuo sito, dove l'ospite sceglie gli articoli. I resi valgono solo per gli ordini pagati.
  • commerce.wishlist: un interruttore (toggle(variantId)) che aggiunge o toglie. Un ospite non ne ha: lancia LOGIN_REQUIRED senza chiedere allo store. Uno store può spegnerla.
  • commerce.reviews: un cliente scrive una recensione per ogni variante, con un indirizzo email verificato (altrimenti EMAIL_NOT_VERIFIED). Uno store può spegnere le recensioni.

Lista desideri e recensioni sono attive se le impostazioni dello store non dicono altro: le porta storeData, e la tua interfaccia nasconde ciò che è spento.