Esempi di codice JavaScript e React del framework di estensioni

Questa pagina fornisce esempi di codice scritti in React e JavaScript per le funzioni comuni che potresti voler utilizzare nelle tue estensioni.

Utilizzo dell'SDK di estensione di Looker

Le estensioni devono stabilire una connessione con l'host di Looker. In React, questo viene fatto inserendo l'estensione in un componente ExtensionProvider40. Questo componente stabilisce una connessione con l'host di Looker e rende disponibili per l'estensione l'SDK di Looker Extension e l'SDK di Looker.

import React from 'react'
import { ExtensionProvider40 } from '@looker/extension-sdk-react'
import { DemoCoreSDK } from './DemoCoreSDK'


export const App = () => {
 return (
   <ExtensionProvider40 chattyTimeout={-1}>
     <DemoCoreSDK />
   </ExtensionProvider40>
 )
}

Informazioni sui fornitori di estensioni

I provider di estensioni mettono a disposizione delle estensioni l'SDK e l'API dell'SDK di Looker. Dal momento della creazione del framework delle estensioni sono state create diverse versioni del provider di estensioni. Questa sezione spiega la cronologia dei provider di estensioni e perché ExtensionProvider40 è il provider consigliato.

Il primo provider di estensioni era ExtensionProvider, che esponeva entrambi gli SDK di Looker, nelle versioni 3.1 e 4.0. Il rovescio della medaglia è che l'inclusione di entrambi gli SDK ha aumentato le dimensioni del bundle di produzione finale.

È stata quindi creata la pagina ExtensionProvider2. Questo è stato creato perché non aveva senso che un'estensione usi entrambi gli SDK e costringa lo sviluppatore a scegliere uno o l'altro. Purtroppo, questo ha comportato comunque l'inclusione di entrambi gli SDK nelle dimensioni del bundle di produzione finale.

Quando l'SDK 4.0 è passato a GA, è stato creato ExtensionProvider40. Il vantaggio di ExtensionProvider40 è che lo sviluppatore non deve scegliere quale SDK utilizzare, perché l'SDK 4.0 è l'unica versione disponibile. Poiché l'SDK 3.1 non è incluso nel bundle finale, questo ha il vantaggio di ridurre le dimensioni del bundle.

Per aggiungere funzioni dall'SDK di estensioni di Looker, devi prima ottenere un riferimento all'SDK, che può essere ottenuto dal provider o a livello globale. A questo punto puoi chiamare le funzioni dell'SDK come faresti in qualsiasi applicazione JavaScript.

  • Per accedere all'SDK dal provider:
  import { ExtensionContext40 } from '@looker/extension-sdk-react'

  export const Comp1 = () => {
    const extensionContext = useContext(
      ExtensionContext40
    )
    const { extensionSDK, coreSDK } = extensionContext
  • Per accedere all'SDK a livello globale (l'estensione deve essere inizializzata prima di questa chiamata), segui questi passaggi:
    const coreSDK = getCoreSDK()

Ora puoi utilizzare l'SDK come faresti in qualsiasi applicazione JavaScript:

  const GetLooks = async () => {
    try {
      const looks = await sdk.ok(sdk.all_looks('id'))
      // process looks
      . . .
    } catch (error) {
      // do error handling
      . . .
    }
}

Poiché l'estensione viene eseguita in un iframe in sandbox, non puoi spostarti altrove all'interno dell'istanza di Looker aggiornando l'oggetto window.location principale. È possibile navigare utilizzando l'SDK di estensione di Looker.

Questa funzione richiede il diritto navigation.

import { ExtensionContext40 } from '@looker/extension-sdk-react'

. . .

  const extensionContext = useContext(
    ExtensionContext40
  )
  const { extensionSDK } = extensionContext

. . .

  extensionSDK.updateLocation('/browse')

Apertura di una nuova finestra del browser

Poiché l'estensione viene eseguita in un iframe in sandbox, non puoi utilizzare la finestra principale per aprire una nuova finestra del browser. È possibile aprire una finestra del browser utilizzando l'SDK di estensione di Looker.

Questa funzione richiede il dirietto new_window per aprire una nuova finestra in una posizione nell'istanza Looker corrente o il dirietto new_window_external_urls per aprire una nuova finestra che viene eseguita su un host diverso.

import { ExtensionContext40 } from '@looker/extension-sdk-react'

. . .

  const extensionContext = useContext(
    ExtensionContext40
  )
  const { extensionSDK } = extensionContext

. . .
  extensionSDK.openBrowserWindow('/browse', '_blank')
. . .
  extensionSDK.openBrowserWindow('https://docs.looker.com/reference/manifest-params/application#entitlements', '_blank')

Routing e link diretti

Quanto segue si applica alle estensioni basate su React.

I componenti ExtensionProvider, ExtensionProvider2 e ExtensionProvider40 creano automaticamente un router React denominato MemoryRouter da utilizzare. Non tentare di creare un BrowserRouter, in quanto non funziona negli iframe con sandbox. Non tentare di creare un HashRouter, in quanto non funziona negli iframe con sandbox per la versione non basata su Chromium del browser Microsoft Edge.

Se utilizzi MemoryRouter e react-router nella tua estensione, il framework dell'estensione sincronizzerà automaticamente il router dell'estensione con il router host di Looker. Ciò significa che l'estensione riceverà una notifica dei clic sui pulsanti Indietro e Avanti del browser e del percorso corrente quando la pagina viene ricaricata. Ciò significa anche che l'estensione dovrebbe supportare automaticamente i link diretti. Consulta gli esempi di estensioni per scoprire come utilizzare react-router.

Dati sul contesto dell'estensione

I dati di contesto del framework di estensioni non devono essere confusi con i contesti React.

Le estensioni hanno la possibilità di condividere i dati di contesto tra tutti gli utenti di un'estensione. I dati di contesto possono essere utilizzati per i dati che non cambiano di frequente e che non hanno requisiti di sicurezza speciali. È necessario prestare attenzione durante la scrittura dei dati, poiché non è previsto il blocco dei dati e l'ultima scrittura ha la precedenza. I dati di contesto sono disponibili per l'estensione immediatamente all'avvio. L'SDK di estensioni di Looker fornisce funzioni per consentire l'aggiornamento e il riavvio dei dati di contesto.

La dimensione massima dei dati di contesto è di circa 16 MB. I dati di contesto verranno serializzati in una stringa JSON, quindi questo aspetto deve essere preso in considerazione anche se utilizzi i dati di contesto per l'estensione.

import { ExtensionContext40 } from '@looker/extension-sdk-react'

. . .

  const extensionContext = useContext(
    ExtensionContext40
  )
  const { extensionSDK } = extensionContext

. . .

  // Get loaded context data. This will reflect any updates that have
  // been made by saveContextData.
  let context = await extensionSDK.getContextData()

. . .

  // Save context data to Looker server.
  context = await extensionSDK.saveContextData(context)

. . .

  // Refresh context data from Looker server.
  context = await extensionSDK.refreshContextData()

Attributi utente

L'SDK di estensione di Looker fornisce un'API per accedere agli attributi utente di Looker. Esistono due tipi di accesso agli attributi utente:

  • Con ambito: associato all'estensione. Un attributo utente basato su ambito è associato allo spazio dei nomi dell'estensione e deve essere definito nell'istanza di Looker prima di poter essere utilizzato. Per assegnare uno spazio dei nomi a un attributo utente, anteponi al nome dell'attributo il nome dell'estensione. Eventuali trattini e i caratteri "::" nel nome dell'estensione devono essere sostituiti da un trattino basso, poiché i trattini e i due punti non possono essere utilizzati nei nomi degli attributi utente.

    Ad esempio, un attributo utente con ambito denominato my_value utilizzato con un ID estensione my-extension::my-extension deve avere un nome dell'attributo utente my_extension_my_extension_my_value definito. Una volta definito, l'attributo utente può essere letto e aggiornato dall'estensione.

  • Globali: si tratta di attributi utente globali e sono di sola lettura. Un esempio è l'attributo utente locale.

Di seguito è riportato un elenco di chiamate API degli attributi utente:

  • userAttributeGetItem: legge un attributo utente. È possibile definire un valore predefinito che verrà utilizzato se non esiste un valore dell'attributo utente per l'utente.
  • userAttributeSetItem: salva un attributo utente per l'utente corrente. Non avrà esito positivo per gli attributi utente globali. Il valore salvato è visibile solo all'utente corrente.
  • userAttributeResetItem: reimposta un attributo utente per l'utente corrente sul valore predefinito. Non avrà esito positivo per gli attributi utente globali.

Per accedere agli attributi utente, devi specificare i nomi degli attributi nei diritti global_user_attributes e/o scoped_user_attributes. Ad esempio, nel file manifest del progetto LookML, aggiungi:

  entitlements: {
    scoped_user_attributes: ["my_value"]
    global_user_attributes: ["locale"]
  }
import { ExtensionContext40 } from '@looker/extension-sdk-react'

. . .

  const extensionContext = useContext(
    ExtensionContext40
  )
  const { extensionSDK } = extensionContext

  // Read global user attribute
  const locale = await extensionSDK.userAttributeGetItem('locale')

  // Read scoped user attribute
  const value = await extensionSDK.userAttributeGetItem('my_value')

  // Update scoped user attribute
  const value = await extensionSDK.userAttributeSetItem('my_value', 'abcd1234')

  // Reset scoped user attribute
  const value = await extensionSDK.userAttributeResetItem('my_value')

Conservazione locale

Gli iframe con sandbox non consentono l'accesso allo spazio di archiviazione locale del browser. L'SDK di estensione di Looker consente a un'estensione di leggere e scrivere nello spazio di archiviazione locale della finestra principale. Lo spazio di archiviazione locale è associato allo spazio dei nomi dell'estensione, il che significa che non può leggere lo spazio di archiviazione locale creato dalla finestra principale o da altre estensioni.

L'utilizzo dello spazio di archiviazione locale richiede il dirietto local_storage.

L'API localhost dell'estensione è asincrona, a differenza dell'API di archiviazione locale del browser sincrona.

import { ExtensionContext40 } from '@looker/extension-sdk-react'

. . .

  const extensionContext = useContext(
    ExtensionContext40
  )
  const { extensionSDK } = extensionContext

  // Read from local storage
  const value = await extensionSDK.localStorageGetItem('my_storage')

  // Write to local storage
  await extensionSDK.localStorageSetItem('my_storage', 'abcedefh')

  // Delete item from local storage
  await extensionSDK.localStorageRemoveItem('my_storage')

Aggiornamento del titolo della pagina

Le estensioni potrebbero aggiornare il titolo della pagina corrente. Per eseguire questa azione non sono richiesti diritti.

import { ExtensionContext40 } from '@looker/extension-sdk-react'

. . .

  const extensionContext = useContext(
    ExtensionContext40
  )
  const { extensionSDK } = extensionContext

  extensionSDK.updateTitle('My Extension Title')

Scrittura negli appunti di sistema

Gli iframe con sandbox non consentono l'accesso agli appunti di sistema. L'SDK di estensione Looker consente a un'estensione di scrivere del testo negli appunti di sistema. Per motivi di sicurezza, l'estensione non è autorizzata a leggere dagli appunti di sistema.

Per scrivere negli appunti di sistema, devi disporre del diririttto use_clipboard.

import { ExtensionContext40 } from '@looker/extension-sdk-react'

. . .

const extensionContext = useContext(
    ExtensionContext40
  )
  const { extensionSDK } = extensionContext

    // Write to system clipboard
    try {
      await extensionSDK.clipboardWrite(
        'My interesting information'
      )
      . . .
    } catch (error) {
      . . .
    }

Incorporazione di dashboard, Look ed esplorazioni

Il framework di estensione supporta l'incorporamento di dashboard, Look ed esplorazioni.

Il diritto use_embeds è obbligatorio. Ti consigliamo di utilizzare l'SDK di incorporamento JavaScript di Looker per incorporare i contenuti. Per ulteriori informazioni, consulta la documentazione dell'SDK Embed.

import { ExtensionContext40 } from '@looker/extension-sdk-react'

. . .

  const extensionContext = useContext(
    ExtensionContext40
  )
  const { extensionSDK } = extensionContext

. . .

  const canceller = (event: any) => {
    return { cancel: !event.modal }
  }

  const updateRunButton = (running: boolean) => {
    setRunning(running)
  }

  const setupDashboard = (dashboard: LookerEmbedDashboard) => {
    setDashboard(dashboard)
  }

  const embedCtrRef = useCallback(
    (el) => {
      const hostUrl = extensionContext?.extensionSDK?.lookerHostData?.hostUrl
      if (el && hostUrl) {
        el.innerHTML = ''
        LookerEmbedSDK.init(hostUrl)
        const db = LookerEmbedSDK.createDashboardWithId(id as number)
          .withNext()
          .appendTo(el)
          .on('dashboard:loaded', updateRunButton.bind(null, false))
          .on('dashboard:run:start', updateRunButton.bind(null, true))
          .on('dashboard:run:complete', updateRunButton.bind(null, false))
          .on('drillmenu:click', canceller)
          .on('drillmodal:explore', canceller)
          .on('dashboard:tile:explore', canceller)
          .on('dashboard:tile:view', canceller)
          .build()
          .connect()
          .then(setupDashboard)
          .catch((error: Error) => {
            console.error('Connection error', error)
          })
      }
    },
    []
  )

  return (&#60;EmbedContainer ref={embedCtrRef} /&#62;)

Gli esempi di estensioni utilizzano componenti con stile per applicare uno stile semplice all'iframe generato. Ad esempio:

import styled from "styled-components"

export const EmbedContainer = styled.div`
  width: 100%;
  height: 95vh;
  & > iframe {
    width: 100%;
    height: 100%;
  }

Accesso agli endpoint API esterni

Il framework di estensione fornisce due metodi per accedere agli endpoint API esterni:

  • Il proxy del server: accede all'endpoint tramite il server Looker. Questo meccanismo consente al server Looker di impostare in modo sicuro gli ID client e le chiavi segrete.
  • Il proxy di recupero: accede all'endpoint dal browser dell'utente. Il proxy è l'interfaccia utente di Looker.

In entrambi i casi, devi specificare l'endpoint dell'API esterna nel diritto di external_api_urls dell'estensione.

Server proxy

L'esempio seguente mostra l'utilizzo del proxy del server per ottenere un token di accesso da utilizzare dal proxy di recupero. L'ID client e il secret devono essere definiti come attributi utente per l'estensione. In genere, quando l'attributo utente è configurato, il valore predefinito è impostato sull'ID cliente o sul secret.

import { ExtensionContext40 } from '@looker/extension-sdk-react'

. . .

  const extensionContext = useContext(
    ExtensionContext40
  )
  const { extensionSDK } = extensionContext

. . .
  const requestBody = {
    client_id: extensionSDK.createSecretKeyTag('my_client_id'),
    client_secret: extensionSDK.createSecretKeyTag('my_client_secret'),
  },
  try {
    const response = await extensionSDK.serverProxy(
      'https://myaccesstokenserver.com/access_token',
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(requestBody),
      }
    )
    const { access_token, expiry_date } = response.body
. . .
  } catch (error) {
    // Error handling
    . . .
  }

Il nome dell'attributo utente deve essere mappato all'estensione. I trattini devono essere sostituiti da trattini bassi e i caratteri :: devono essere sostituiti da un trattino basso.

Ad esempio, se il nome dell'estensione è my-extension::my-extension, gli attributi utente da definire per l'esempio precedente sono i seguenti:

my_extension_my_extension_my_client_id
my_extension_my_extension_'my_client_secret'

Recupera proxy

L'esempio seguente mostra l'utilizzo del proxy di recupero. Utilizza il token di accesso dell'esempio di server proxy precedente.

import { ExtensionContext40 } from '@looker/extension-sdk-react'

. . .

  const extensionContext = useContext(
    ExtensionContext40
  )
  const { extensionSDK } = extensionContext

. . .

  try {
    const response = await extensionSDK.fetchProxy(
      'https://myaccesstokenserver.com/myendpoint',
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          Authorization: `Bearer ${accessToken}`,
        },
        body: JSON.stringify({
          some_value: someValue,
          another_value: anotherValue,
        }),
      }
    )
    // Handle success

. . .

  } catch (error) {
    // Handle failure

. . .

  }

Integrazione OAuth

Il framework delle estensioni supporta l'integrazione con i provider OAuth. OAuth può essere utilizzato per ottenere un token di accesso per accedere a una determinata risorsa, ad esempio un documento di Fogli Google.

Dovrai specificare l'endpoint del server OAuth nel diritto extension oauth2_urls. Potresti anche dover specificare altri URL nel diritto external_api_urls.

I framework di estensioni supportano i seguenti flussi:

  • Flusso implicito
  • Tipo di concessione del codice di autorizzazione con chiave segreta
  • Verificatore e richiesta di codice PKCE

Il flusso generale prevede l'apertura di una finestra secondaria che carica una pagina del server OAuth. Il server OAuth autentica l'utente e reindirizza al server Looker con ulteriori dettagli che possono essere utilizzati per ottenere un token di accesso.

Flusso implicito:

import { ExtensionContext40 } from '@looker/extension-sdk-react'

. . .

  const extensionContext = useContext(
    ExtensionContext40
  )
  const { extensionSDK } = extensionContext

. . .

    const response = await extensionSDK.oauth2Authenticate(
      'https://accounts.google.com/o/oauth2/v2/auth',
      {
        client_id: GOOGLE_CLIENT_ID!,
        scope: GOOGLE_SCOPES,
        response_type: 'token',
      }
    )
    const { access_token, expires_in } = response

Tipo di concessione del codice di autorizzazione con chiave segreta:

  const authenticateParameters: Record&#60;string, string&#62; = {
    client_id: GITHUB_CLIENT_ID!,
    response_type: 'code',
  }
  const response = await extensionSDK.oauth2Authenticate(
    'https://github.com/login/oauth/authorize',
    authenticateParameters,
   'GET'
  )
  const exchangeParameters: Record&#60;string, string&#62; = {
    client_id: GITHUB_CLIENT_ID!,
    code: response.code,
    client_secret: extensionSDK.createSecretKeyTag('github_secret_key'),
  }
  const codeExchangeResponse = await extensionSDK.oauth2ExchangeCodeForToken(
    'https://github.com/login/oauth/access_token',
    exchangeParameters
  )
  const { access_token, error_description } = codeExchangeResponse

Verifica e richiesta di codice PKCE:

import { ExtensionContext40 } from '@looker/extension-sdk-react'

. . .

  const extensionContext = useContext(
    ExtensionContext40
  )
  const { extensionSDK } = extensionContext

. . .

  const authRequest: Record&#60;string, string&#62; = {
    client_id: AUTH0_CLIENT_ID!,
    response_type: 'code',
    scope: AUTH0_SCOPES,
    code_challenge_method:  'S256',
  }
  const response = await extensionSDK.oauth2Authenticate(
    'https://sampleoauthserver.com/authorize',
    authRequest,
    'GET'
  )
  const exchangeRequest: Record&#60;string, string&#62; = {
    grant_type: 'authorization_code',
    client_id: AUTH0_CLIENT_ID!,
    code: response.code,
  }
  const codeExchangeResponse = await extensionSDK.oauth2ExchangeCodeForToken(
    'https://sampleoauthserver.com/login/oauth/token',
    exchangeRequest
  )
  const { access_token, expires_in } = codeExchangeResponse

Spartan

Spartan si riferisce a un metodo per utilizzare l'istanza di Looker come ambiente per esporre le estensioni e solo le estensioni a un gruppo designato di utenti. Un utente spartano che accede a un'istanza di Looker visualizzerà il flusso di accesso configurato dall'amministratore di Looker. Una volta autenticato, all'utente verrà presentata un'estensione in base al suo landing_page attributo utente, come mostrato di seguito. L'utente può accedere solo alle estensioni e non può accedere ad altre parti di Looker. Se l'utente ha accesso a più estensioni, queste controllano la sua capacità di passare alle altre estensioni utilizzando extensionSDK.updateLocation. Esiste un metodo specifico dell'SDK di estensione di Looker per consentire all'utente di uscire dall'istanza di Looker.

import { ExtensionContext40 } from '@looker/extension-sdk-react'

. . .

  const extensionContext = useContext(
    ExtensionContext40
  )
  const { extensionSDK } = extensionContext

. . .
  // Navigate to another extension
  extensionSDK.updateLocation('/spartan/another::extension')

. . .
  // Logout
  extensionSDK.spartanLogout()

Definire gli utenti spartani

Per definire un utente spartano, devi creare un gruppo denominato "Solo estensioni".

Dopo aver creato il gruppo "Solo estensioni", vai alla pagina Attributi utente nella sezione Amministrazione di Looker e modifica l'attributo utente landing_page. Seleziona la scheda Valori gruppo e aggiungi il gruppo "Solo estensioni". Il valore deve essere impostato su /spartan/my_extension::my_extension/, dove my_extension::my_extension è l'ID dell'estensione. Ora, quando l'utente accede, viene indirizzato all'estensione designata.

Suddivisione del codice

La suddivisione del codice è la tecnica in cui il codice viene richiesto solo quando è necessario. In genere, i chunk di codice sono associati alle route di React, dove ogni route ha il proprio chunk di codice. In React, questa operazione viene eseguita con i componenti Suspense e React.lazy. Il componente Suspense mostra un componente di riserva durante il caricamento del frammento di codice. React.lazy è responsabile del caricamento del blocco di codice.

Configurazione della suddivisione in codice:

import { AsyncComp1 as Comp1 } from './Comp1.async'
import { AsyncComp1 as Comp2 } from './Comp2.async'

. . .

                <Suspense fallback={<div>Loading...</div>}>
                  <Switch>
                      <Route path="/comp1">
                        <Comp1 />
                      </Route>
                      <Route path="/comp2">
                        <Comp2 />
                      </Route>
                  </Switch>
                <Suspense>

Il componente con caricamento differito viene implementato come segue:

import { lazy } from 'react'

const Comp1 = lazy(
 async () => import(/* webpackChunkName: "comp1" */ './Comp1')
)

export const AsyncComp1 = () => &#60;Home />

Il componente viene implementato come segue. Il componente deve essere esportato come componente predefinito:

const Comp1 = () => {
  return (
    &#60;div&#62;Hello World&#60;/div&#62;
  )
}

export default Comp1

Movimento dell'albero

Sebbene gli SDK di Looker supportino attualmente il tree-shaking, questa funzione deve ancora essere migliorata. Modifichiamo continuamente i nostri SDK per migliorare il supporto del tree shaking. Per poter usufruire di alcune di queste modifiche, potrebbe essere necessario eseguire il refactoring del codice, ma se questo è necessario, verrà documentato nelle note di rilascio.

Per utilizzare il tree-shaking, il modulo che utilizzi deve essere esportato come esmodule e le funzioni che importi devono essere prive di effetti collaterali. L'SDK Looker per TypeScript/JavaScript, la libreria di runtime dell'SDK Looker, i componenti dell'interfaccia utente di Looker, l'SDK di estensioni di Looker e l'SDK di estensioni per React soddisfano tutti questi requisiti.

In un'estensione, utilizza l'SDK Looker 4.0 e il componente ExtensionProvider2 o ExtensionProvider40 dell'SDK di estensione per React.

Il seguente codice configura il provider di estensioni. Dovrai comunicare al provider quale SDK vuoi:

import { MyExtension } from './MyExtension'
import { ExtensionProvider40 } from '@looker/extension-sdk-react'
import { Looker40SDK } from '@looker/sdk/lib/4.0/methods'
import { hot } from 'react-hot-loader/root'

export const App = hot(() => {

  return (
    &#60;ExtensionProvider2 type={Looker40SDK}&#62;
      &#60;MyExtension /&#62;
    &#60;/ExtensionProvider2&#62;
  )
})

Non utilizzare il seguente stile di importazione nell'estensione:

import * as lookerComponents from `@looker/components`

L'esempio precedente include tutto il modulo. Importa solo i componenti di cui hai effettivamente bisogno. Ad esempio:

import { Paragraph }  from `@looker/components`

Glossario

  • Suddivisione del codice: una tecnica per il caricamento differito di JavaScript finché non è effettivamente necessario. Idealmente, è preferibile mantenere il bundle JavaScript caricato inizialmente il più piccolo possibile. Ciò può essere ottenuto utilizzando la suddivisione del codice. Qualsiasi funzionalità non richiesta immediatamente non viene caricata finché non è effettivamente necessaria.
  • IDE: ambiente di sviluppo integrato. Un editor utilizzato per creare e modificare un'estensione. Alcuni esempi sono Visual Studio Code, IntelliJ e WebStorm.
  • Scena: in genere una visualizzazione di pagina in Looker. Le scene vengono associate alle principali strade. A volte una scena contiene scene secondarie che mappano a sottopercorsi all'interno del percorso principale.
  • Transpilazione: la procedura di acquisizione del codice sorgente scritto in un linguaggio e trasformazione in un altro linguaggio con un livello di astrazione simile. Un esempio è TypeScript a JavaScript.