Services

ImportExportApi

Client HTTP per i microservizi node-excel-import e node-excel-export.

Panoramica

ImportExportApi è il client HTTP usato dalla libreria per interagire con i due microservizi backend:

  • node-excel-import — endpoint {baseUrl}/api/import/*
  • node-excel-export — endpoint {baseUrl}/api/export/*

Internamente usa fetch con AbortController per supportare l'annullamento di upload ed export. Espone metodi tipizzati per upload, test, esecuzione, polling, metadata, template e storico.

Costruttore

new ImportExportApi(baseUrl: string, options?: ImportExportApiOptions)
ParametroTipoDescrizione
baseUrlstringURL base — gli slash finali vengono normalizzati
optionsImportExportApiOptionsPath personalizzati per gli endpoint (opzionale)

ImportExportApiOptions

interface ImportExportApiOptions {
  /** Path base degli endpoint di import (default: '/api/import'). */
  importPath?: string
  /** Path base degli endpoint di export (default: '/api/export'). */
  exportPath?: string
}

Il costruttore concatena baseUrl + path normalizzando le slash:

// Default
new ImportExportApi('https://api.example.com')
// → importUrl = 'https://api.example.com/api/import'
// → exportUrl = 'https://api.example.com/api/export'

// Custom path
new ImportExportApi('https://api.example.com', {
  importPath: '/v2/import',
  exportPath: '/v2/export',
})
// → importUrl = 'https://api.example.com/v2/import'
// → exportUrl = 'https://api.example.com/v2/export'

Implementa 3 contratti

ImportExportApi implementa simultaneamente le tre interfacce IImportClient, IExportClient e ITemplateClient. La type union ImportExportClient è il tipo accettato dalle prop api di ImportWizard / ExportDialog.

Per backend custom (mock di test, GraphQL, SDK alternativi) puoi implementare le interfacce senza ereditare dalla classe concreta. Vedi Client interfaces.

Metodi import

uploadFile(file, risorsa, opzioniCsv?)

uploadFile(
  file: File,
  risorsa: string,
  opzioniCsv?: Partial<CsvOpzioni>
): Promise<UploadResult>

Upload del file via multipart/form-data su POST /api/import/upload. Crea un AbortController interno usato da cancelUpload(). Se annullato, lancia Error("Upload annullato dall'utente").

testImport(sessionId, mappings)

testImport(sessionId: string, mappings: MappingColonna[]): Promise<TestImportResult>

Dry-run su POST /api/import/test. Body: { sessionId, mappings }.

executeImport(sessionId, mappings)

executeImport(sessionId: string, mappings: MappingColonna[]): Promise<ImportResult>

Esecuzione effettiva su POST /api/import/execute. Body: { sessionId, mappings }.

getImportStatus(importId)

getImportStatus(importId: string): Promise<ImportProgresso>

Polling status di un import asincrono — GET /api/import/status/{importId}.

uploadImages(sessionId, files)

uploadImages(
  sessionId: string,
  files: File[]
): Promise<{ caricati: number; errori: string[] }>

Upload immagini collegate alla sessione di import — POST /api/import/images (multipart con images[]).

downloadTemplate(risorsa, formato)

downloadTemplate(risorsa: string, formato: string): Promise<Blob>

Scarica template d'esempio della risorsa — GET /api/import/template/{risorsa}?formato={formato}. Restituisce un Blob.

getImportHistory(risorsa?)

getImportHistory(risorsa?: string): Promise<ImportHistoryItem[]>

Storico importazioni — GET /api/import/history?risorsa=.... Senza risorsa restituisce tutto lo storico accessibile all'utente.

cancelUpload()

cancelUpload(): void

Annulla l'upload in corso (no-op se non c'è upload attivo).

Metodi export

executeExport(request)

executeExport(
  request: ExportRequest
): Promise<ServerAsyncExportPayload | Blob>

Esecuzione export — POST /api/export/execute. Comportamento polimorfico:

  • Risposta 2xx con content-type binario (application/... o text/csv) → Blob
  • Risposta 202 AcceptedServerAsyncExportPayload (export asincrono, partirà il polling)
  • Altre risposte JSON → ServerAsyncExportPayload

Mappa ExportRequest (formato libreria) sul DTO interno del microservizio (fileName, templateId numerico, opzioni.ordinamento).

Annullabile via cancelExport().

getExportStatus(exportId)

getExportStatus(exportId: string): Promise<ExportProgresso>

Polling export asincrono — GET /api/export/status/{exportId}.

downloadExport(url)

downloadExport(url: string): Promise<Blob>

Download del file generato. Validazione CSRF: l'origin dell'URL deve coincidere con l'origin di exportUrl, altrimenti viene rifiutato con Error("URL download non autorizzato: ...").

cancelExport()

cancelExport(): void

Annulla l'export in corso.

Metodi template

getTemplates(risorsa)

getTemplates(risorsa?: string): Promise<ModelloExport[]>

GET /api/export/templates?risorsa=.... Senza risorsa restituisce array vuoto. Il backend risponde con { risorsa, count, templates } o un array diretto — l'API normalizza entrambi e applica mapMsTemplateToModello per convertire dal formato microservizio (MsTemplate) al formato libreria (ModelloExport).

createTemplate(template)

createTemplate(
  template: Omit<ModelloExport, 'id' | 'dataCreazione' | 'dataModifica' | 'creatoDa'>
): Promise<ModelloExport>

POST /api/export/templates. La libreria mappa campi: string[]campijson: Array<{ nomecampo, etichetta, ordinamento }>.

updateTemplate(id, updates)

updateTemplate(
  id: string,
  updates: Partial<ModelloExport>
): Promise<ModelloExport>

PUT /api/export/templates/{id}. Solo i campi presenti in updates vengono inviati al server (patch semantics).

deleteTemplate(id)

deleteTemplate(id: string): Promise<void>

DELETE /api/export/templates/{id}.

Metodi metadata

getImportFieldMetadata(risorsa)

getImportFieldMetadata(risorsa: string): Promise<CampoMetadato[]>

GET /api/import/metadata/{risorsa}/fields. Restituisce i campi destinazione disponibili per l'import.

getExportFieldMetadata(risorsa)

getExportFieldMetadata(risorsa: string): Promise<CampoMetadato[]>

GET /api/export/metadata/{risorsa}/fields. Restituisce i campi esportabili.

Esempio standalone

import { ImportExportApi } from '@pzeta/vue-importexport'

const api = new ImportExportApi('https://api.example.com')

// Upload + test + execute
const upload = await api.uploadFile(file, 'anagrafica', { separatore: ';' })
const test = await api.testImport(upload.sessionId, mappings)

if (test.righeErrore === 0) {
  const result = await api.executeImport(upload.sessionId, mappings)
  console.log(`Importate: ${result.righeImportate}`)
}

Esempio export con polling

const result = await api.executeExport({
  risorsa: 'anagrafica',
  formato: 'xlsx',
  campi: ['nome', 'cognome', 'email'],
  filtri: { attivo: true },
})

if (result instanceof Blob) {
  // Sincrono: salva direttamente
  downloadBlob(result, 'anagrafica.xlsx')
} else {
  // Asincrono: poll fino a completamento
  let status = result
  while (status.stato === 'in_corso') {
    await new Promise((r) => setTimeout(r, 2000))
    status = await api.getExportStatus(result.exportId)
  }
  if (status.urlDownload) {
    const blob = await api.downloadExport(status.urlDownload)
    downloadBlob(blob, status.nomeFile ?? 'export.xlsx')
  }
}

Gestione errori

Tutte le risposte non-2xx lanciano Error con messaggio formattato:

Errore API: {status}: {message}
Errore export: {status}: {message}
Errore download: {status}: {message}

Il messaggio viene estratto da body.message o body.error se presente nel JSON di risposta, altrimenti viene usato res.statusText.