A gennaio 2016, subito dopo la laurea, ho iniziato a lavorare in Air Reply e ho incontrato NetSuite. Nel giro di poco mi sono accorto che continuavo a eseguire a mano gli stessi snippet nella console del browser: cercare l’ID di un campo, leggerne il valore, abilitarlo per una prova. Tutte cose che sarebbero state molto più comode con un’estensione per Chrome. Così ho deciso di scriverla.
C’era anche un altro motivo. Il mio desiderio più grande è creare qualcosa che possano usare tutti: un desiderio comune, lo so, ma io provo a realizzarlo un progetto alla volta. NetSuite Helper for Your Works è stato il primo. Oggi la usano circa 3.000 persone in tutto il mondo, e a ottobre 2026 l’ho riscritta da zero.
Questa è la storia di cosa c’era sotto il cofano, e di cosa ho cambiato.
Il pulsante invisibile
Un’estensione Chrome non vive davvero dentro la pagina che modifica. Il suo codice gira in un mondo isolato: vede l’HTML, ma non le variabili JavaScript della pagina. Per NetSuite è un problema serio, perché tutto quello che serve, le API SuiteScript e i dati del record, sta proprio lì.
Trovare un modo per superare questo muro non è stato affatto semplice: Chrome non offriva una strada diretta, e ci ho perso parecchio tempo. Alla fine la soluzione è stata un ponte costruito con due elementi della pagina. In ogni pagina NetSuite l’estensione aggiungeva due elementi nascosti: una casella di testo invisibile e un pulsante invisibile. Quando sceglievi una voce dal menu del tasto destro, l’estensione scriveva nella casella il codice da eseguire e “premeva” il pulsante. Dall’altra parte, nel mondo della pagina, il pulsante leggeva la casella ed eseguiva il testo con eval().
Funzionava, ed è andato avanti per anni. Ma ogni comando viaggiava come una stringa di codice, e i valori comparivano in una finestra prompt() del browser: l’unico modo semplice per mostrare un testo e permettere di copiarlo.
Nella versione 4 il ponte non c’è più. Il motore viene caricato una volta nel mondo della pagina ed espone un oggetto, NHFS; l’estensione gli passa le azioni con le API ufficiali di Chrome (chrome.scripting) come dati strutturati, non come codice da valutare.
Trovare il campo giusto
La funzione più usata è anche la più difficile: capire su quale campo hai cliccato. NetSuite non mette l’ID del campo sull’elemento che tocchi, ma lo nasconde negli ID degli elementi vicini, con suffissi come _fs, _fs_lbl o _lbl_uir_label.
La versione 3 andava a tentativi: guardava l’elemento cliccato, poi il genitore, poi il genitore del genitore, provando un suffisso alla volta. Bastava che NetSuite aggiungesse un livello di HTML per sbagliare campo, o per non trovarne nessuno.
La versione 4 usa una regola sola: risale dall’elemento cliccato e si ferma al primo contenitore che racchiude esattamente un campo. Se un contenitore ne racchiude due o più, si ferma: meglio non rispondere che indicare il campo del vicino. Dove NetSuite espone l’ID in chiaro, come l’attributo data-field-name delle pagine recenti, lo usa direttamente.
Poi ci sono i casi difficili:
- Campi disabilitati. Un campo disabilitato non riceve i clic del mouse, quindi l’estensione non saprebbe su cosa hai cliccato. La v4 guarda anche tutti gli elementi che si trovano sotto il cursore in quel punto (
document.elementsFromPoint) e trova il campo lì sotto. - Liste in sola lettura, come le righe degli articoli in visualizzazione o le note di sistema. Lì le celle non contengono nessun ID, solo il testo dell’intestazione di colonna. La v4 carica il record, legge le etichette dei campi della sublist e cerca quella che coincide con l’intestazione.
- Etichette. Il link di aiuto sull’etichetta di un campo contiene una chiamata
nlFieldHelp(...)con l’ID del campo tra gli argomenti: un’altra fonte affidabile.
SuiteScript 2.1, con un piano B
La versione 3 usava solo le API di SuiteScript 1.0 (nlapiGetFieldValue, nlapiLoadRecord…). La 4 prova prima i moduli moderni, N/currentRecord, N/record e N/search, caricandoli con il loader che NetSuite stesso usa nella pagina. Se in quella pagina non rispondono entro pochi secondi, ripiega su SuiteScript 1.0. Il popup mostra quali delle due versioni sono disponibili dove ti trovi.
Le stesse funzioni sono a disposizione nella console del browser, per chi vuole sperimentare:
NHFS.help(); // l'elenco delle utility
const record = await NHFS.N('N/record'); // un modulo SuiteScript 2.x
await NHFS.getRecordContext(); // { type, id, editable }
NHFS.toast('Ciao da NetSuite Helper!', 'success');
Addio prompt()
Al posto delle finestre del browser, i risultati ora compaiono in una finestra disegnata dall’estensione dentro la pagina, con il pulsante Copia e le notifiche a comparsa. È costruita in uno Shadow DOM, una specie di bolla in cui lo stile di NetSuite non entra e da cui il mio non esce: le due grafiche non si disturbano. E segue il tema chiaro o scuro del sistema.
Non rompere il lavoro degli altri
La parte più delicata non era il codice nuovo, ma quello degli utenti. Molti hanno scritto le proprie funzioni personalizzate, piccoli script salvati nell’estensione e lanciati con un clic, che chiamano le 13 funzioni della versione 3 o leggono la variabile con l’ultimo elemento cliccato.
Nella v4 quelle 13 funzioni esistono ancora, con lo stesso nome: dietro le quinte chiamano il motore nuovo e mostrano le finestre nuove al posto di prompt(). Anche la vecchia variabile c’è ancora, e restituisce l’elemento sotto l’ultimo clic destro come prima. Le funzioni scritte per la 3.x continuano a funzionare senza toccare una riga.
Un’altra trappola è più sottile. Su Chrome, se un aggiornamento chiede un permesso nuovo su un sito, l’estensione viene disattivata a tutti finché ciascuno non lo approva a mano. Per la versione Pro serviva contattare il server delle licenze: quel permesso è facoltativo, chiesto solo a chi attiva la licenza, nel momento in cui lo fa.
Otto lingue, scelte con i dati
Le statistiche dello store mi hanno sorpreso: l’italiano, la mia lingua, è appena il 5% degli utenti. Il 62% usa l’inglese e quasi uno su cinque il portoghese brasiliano. Così la versione 4 parla inglese, italiano, spagnolo, francese, tedesco, portoghese (Brasile e Portogallo) e cinese semplificato.
Non conoscendo la maggior parte di queste lingue, ogni testo è stato tradotto, rivisto in modo indipendente e ritradotto in italiano, per accorgermi se il senso si perdeva per strada.
Gratis, con un Pro onesto
Tutto quello che c’era nella versione 3 resta gratuito. La versione Pro aggiunge funzioni per chi usa l’estensione tutti i giorni, come le funzioni personalizzate illimitate e direttamente nel menu del tasto destro. Si paga una volta sola, con prezzo libero a partire da 4,99 €: niente abbonamenti.
Cosa mi porto a casa
Riaprire il codice del 2016 è stato un po’ come rileggere un vecchio quaderno. Il pulsante invisibile, per esempio: oggi Chrome offre una strada ufficiale, ma allora non c’era, e trovare un modo per far parlare l’estensione con la pagina è stato un vero rompicapo. Quella soluzione ha retto per quasi dieci anni, e l’idea di fondo dell’estensione regge ancora.
La cosa più importante che mi ha insegnato questa riscrittura è che, quando qualcosa che hai costruito viene usato da altri, non è più solo tuo. Ogni scelta, anche la più tecnica, va fatta pensando a chi lo usa ogni giorno: a chi ha scritto le proprie funzioni personalizzate e non deve perderle, a chi lavora in una lingua diversa dalla mia, a chi aggiorna l’estensione senza nemmeno accorgersene e si aspetta che tutto continui a funzionare.
E gli utenti sanno sorprenderti. Non mi sarei mai aspettato che il Brasile fosse così attivo: quasi un utente su cinque usa l’estensione in portoghese brasiliano. Per me è la conferma più bella del desiderio da cui tutto è partito: creare qualcosa che possano usare tutti, ovunque siano.
Se lavori su NetSuite, puoi provarla dal Chrome Web Store. E se hai un’idea o trovi un problema, scrivimi.
