Skip to content

Standard di codifica

Linguaggio e tipi

  • TypeScript ESM, strict attivo con exactOptionalPropertyTypes e noUncheckedIndexedAccess.
  • any vietato in src/ (ESLint error). I dati esterni entrano come unknown e si restringono con Zod.
  • Import con estensione .js (requisito ESM). Le pipeline importano dal barrel src/core/index.ts.
  • Preferire funzioni e dati immutabili (readonly, const). Evitare stato globale.

Architettura ETL

  • Separare estrazione, trasformazione e caricamento. I side-effect verso sistemi esterni stanno solo in Source/Sink. Le Transform sono funzioni pure e testabili.
  • Iniezione delle dipendenze. Una pipeline riceve Source e Sink come parametri (vedi buildSalesDailyPipeline), così la si testa con connettori in-memory e si cambia ambiente senza toccare la logica.
  • Streaming di default. I connettori restituiscono AsyncIterable: non caricare interi dataset in memoria.
  • Schema-contratto su ogni confine. Validare con Zod ciò che entra dalla sorgente e ciò che esce verso il sink (validate()), così i dati malformati non si propagano.

Naming

  • File: kebab-case.ts. Tipi/classi: PascalCase. Funzioni/variabili: camelCase. Costanti: UPPER_SNAKE.
  • Stage con nome descrittivo e unico nella pipeline (compare in log/metriche): "raw-contract", "to-fact".
  • Pipeline: nome kebab-case che descrive il dominio e la cadenza: langfuse-sessions-daily, orders-hourly.

Errori

  • Lanciare solo sottoclassi di EtlError (ValidationError, ExtractError, LoadError, ConfigError).
  • Un EtlError con record problematico è instradabile al dead-letter; un errore generico aborta la run (è un bug da fixare).
  • Mai inghiottire errori in silenzio. O dead-letter, o fail-fast esplicito.

Logging

  • Usare ctx.logger (JSON strutturato su stderr), mai console.log (ESLint lo segnala).
  • Niente segreti nei log. Loggare conteggi e identificatori, non payload sensibili.
  • Arricchire il contesto con logger.child({ stage, ... }).

Idempotenza (regola d'oro dell'ETL)

  • Un Sink.load deve poter essere rieseguito senza creare duplicati: usare upsert / MERGE su chiave naturale, oppure write-then-swap (scrivi su tabella temp, poi swap atomico).
  • Il caricamento incrementale legge il watermark da ctx.params (es. since) e lo avanza solo a caricamento riuscito.

Noeva è un marchio registrato di 4D S.R.L.