@applica-software-guru/crud-client
v1.1.46
Published
Libreria per l'accesso ai servizi REST di Applica.
Readme
Libreria per l'accesso ai servizi REST di Applica.
| Info | Dettagli | | --------------- | ------------------------------------------------------- | | Ultima versione | 1.0.* | | Autore | Roberto Conte Rosito | | Repository | https://bitbucket.org/applicaguru/crud-client | | Pipeline | https://bitbucket.org/applicaguru/crud-client/pipelines |
Prefazione
La libreria @applica-software-guru/crud-client è un client REST che consente l'accesso ai servizi REST di Applica.
La sua implementazione si basa sui principi e le linee guida definite all'interno del progetto React-Admin
Installazione
Per installare la libreria:
npm install @applica-software-guru/crud-clientConfigurazione
Configurazione Base
import { ApplicaDataProvider, createAttachmentsParser } from '@applica-software-guru/crud-client';
import { createAuthProvider, MemoryStorage } from '@applica-software-guru/iam-client';
import { HttpError } from 'ra-core';
const apiUrl = 'https://api.applica.guru/api';
const storage = new MemoryStorage();
const authProvider = createAuthProvider({ apiUrl, storage });
const dataProvider = new ApplicaDataProvider({
apiUrl,
HttpErrorClass: HttpError,
getHeaders: async () => await authProvider.getHeaders(),
getToken: async () => await authProvider.getToken(),
attachmentsParser: createAttachmentsParser()
});Configurazione Avanzata
const dataProvider = new ApplicaDataProvider({
apiUrl: 'https://api.applica.guru/api',
HttpErrorClass: HttpError,
getHeaders: async () => await authProvider.getHeaders(),
getToken: async () => await authProvider.getToken(),
attachmentsParser: createAttachmentsParser(),
// Opzionale: modalità mobile
mobile: false, // default: false
// Opzionale: timeout di default per tutte le richieste (in millisecondi)
timeout: 30000, // default: 30000 (30 secondi)
// Opzionale: funzione per preparare i dati prima dell'invio
prepareData: (data, resource, params) => {
// Personalizza i dati prima dell'invio
return data;
}
});Configurazione per Applicazioni Mobile
Se lavori su un'applicazione mobile devi necessariamente creare il data provider in questo modo:
const dataProvider = new ApplicaDataProvider({
apiUrl,
// ... altre configurazioni
mobile: true
});In modalità mobile, il dataProvider adotta comportamenti diversi per le chiamate di creazione e modifica dei record:
- Utilizza chiamate REST pure invece di FormData
- La gestione degli upload dei file viene gestita separatamente
API Reference
Il dataProvider implementa tutte le operazioni CRUD standard di React-Admin, estese con funzionalità specifiche di Applica.
🕒 Timeout Support: Tutte le operazioni supportano un parametro timeout opzionale che sovrascrive il timeout globale configurato nel provider. Questo permette di personalizzare il timeout per ogni singola richiesta in base alle necessità specifiche dell'operazione.
Operazioni CRUD Standard
getList
Recupera una lista paginata di record con supporto per filtri e ordinamento.
const result = await dataProvider.getList('entities/user', {
pagination: {
page: 1,
perPage: 10
},
sort: {
field: 'name',
order: 'ASC' // o 'DESC'
},
filter: {
name__like: 'Giovanni',
id__gt: 10,
active__is: true,
keyword: 'search term' // ricerca globale
},
// Opzionale: timeout specifico per questa richiesta
timeout: 5000 // 5 secondi
});
// Risultato:
// {
// data: [...], // array di record
// total: 150 // numero totale di record
// }Operatori di filtro supportati:
__like: ricerca LIKE__eq: uguaglianza esatta__gt: maggiore di__gte: maggiore o uguale__lt: minore di__lte: minore o uguale__is: valore booleano__in: valore in array
getOne
Recupera un singolo record per ID.
const result = await dataProvider.getOne('entities/user', {
id: 1,
timeout: 3000 // timeout opzionale
});
// Risultato:
// {
// data: { id: 1, name: 'Roberto', ... }
// }getMany
Recupera più record specificando i loro ID.
const result = await dataProvider.getMany('entities/user', {
ids: [1, 2, 3],
timeout: 4000
});
// Risultato:
// {
// data: [
// { id: 1, name: 'Roberto' },
// { id: 2, name: 'Mario' },
// { id: 3, name: 'Luigi' }
// ]
// }getManyReference
Recupera record che referenziano un altro record.
const result = await dataProvider.getManyReference('entities/post', {
target: 'author_id',
id: 123, // ID dell'autore
pagination: { page: 1, perPage: 10 },
sort: { field: 'title', order: 'ASC' },
filter: { published: true },
timeout: 6000
});create
Crea un nuovo record. Supporta upload di file e allegati.
const result = await dataProvider.create('entities/user', {
data: {
name: 'Nuovo Utente',
email: '[email protected]',
avatar: fileObject, // File object per upload
documents: [file1, file2] // Array di file
},
timeout: 10000 // timeout più lungo per upload
});
// Risultato:
// {
// data: { id: 456, name: 'Nuovo Utente', ... }
// }update
Aggiorna un record esistente.
const result = await dataProvider.update('entities/user', {
id: 1,
data: {
name: 'Nome Aggiornato',
email: '[email protected]'
},
previousData: { id: 1, name: 'Vecchio Nome', ... }, // richiesto da React-Admin
timeout: 8000
});updateMany
Aggiorna più record contemporaneamente.
const result = await dataProvider.updateMany('entities/user', {
ids: [1, 2, 3],
data: {
status: 'active'
},
rows: [
// dati specifici per ogni record (opzionale)
{ id: 1, name: 'Roberto' },
{ id: 2, name: 'Mario' },
{ id: 3, name: 'Luigi' }
],
timeout: 15000
});delete
Elimina un record.
const result = await dataProvider.delete('entities/user', {
id: 1,
timeout: 5000
});deleteMany
Elimina più record contemporaneamente.
const result = await dataProvider.deleteMany('entities/user', {
ids: [1, 2, 3],
timeout: 10000
});Operazioni Estese
get
Esegue una chiamata GET generica. Supporta timeout configurabile per richiesta.
// Chiamata GET di base
const result = await dataProvider.get('users', {
name: 'Roberto',
active: true
});
// Con timeout personalizzato
const result = await dataProvider.get('users', {
name: 'Roberto',
active: true,
timeout: 5000 // 5 secondi per questa richiesta
});post
Esegue una chiamata POST generica. Supporta timeout configurabile per richiesta.
import { stringify } from 'query-string';
// Chiamata POST di base
const result = await dataProvider.post(`users?${stringify({ k: 'f' })}`, {
id: 1,
name: 'Roberto'
});
// Con timeout personalizzato
const result = await dataProvider.post('users', {
id: 1,
name: 'Roberto',
timeout: 10000 // 10 secondi per questa richiesta
});getFile
Scarica un file dal server mantenendo l'autenticazione.
const fileUrl = await dataProvider.getFile('/attachments/post/1/picture/1');
// Utilizzo per download
const link = document.createElement('a');
link.href = fileUrl;
link.download = 'filename.jpg';
link.click();getApiUrl
Ottiene l'URL base dell'API configurato.
const apiUrl = dataProvider.getApiUrl();
console.log(apiUrl); // 'https://api.applica.guru/api'Gestione Timeout
Ogni operazione supporta un timeout configurabile a livello di singola richiesta, che sovrascrive il timeout di default del provider.
Timeout di Default
const dataProvider = new ApplicaDataProvider({
// ... altre configurazioni
timeout: 30000 // 30 secondi per tutte le richieste
});Timeout per Richiesta Specifica
// Timeout specifico sovrascrive quello di default
await dataProvider.getList('users', {
pagination: { page: 1, perPage: 10 },
timeout: 5000 // Solo questa richiesta avrà timeout di 5 secondi
});
// Timeout per operazioni di upload (solitamente più lunghi)
await dataProvider.create('documents', {
data: { file: largeFileObject },
timeout: 60000 // 1 minuto per upload di file grandi
});Gestione Errori di Timeout
try {
const result = await dataProvider.getList('users', {
pagination: { page: 1, perPage: 10 },
timeout: 1000 // timeout molto breve
});
} catch (error) {
if (error.message === 'error.request_timeout') {
console.log('La richiesta è andata in timeout');
// Gestisci l'errore di timeout
}
}Gestione Timeout Globale vs Locale
Il sistema di timeout del dataProvider funziona su due livelli: globale e locale.
Timeout Globale
Il timeout globale è configurato una sola volta durante l'istanziazione del dataProvider e si applica a tutte le richieste come valore di default. È particolarmente utile per:
- Definire un timeout standard per tutta l'applicazione
- Evitare di specificare il timeout per ogni singola chiamata
- Gestire connessioni lente o instabili con un valore appropriato
// Configurazione globale - si applica a tutte le operazioni
const dataProvider = new ApplicaDataProvider({
apiUrl: 'https://api.applica.guru/api',
timeout: 15000 // 15 secondi per TUTTE le richieste
// ... altre configurazioni
});
// Tutte queste chiamate useranno il timeout di 15 secondi
await dataProvider.getList('users', { pagination: { page: 1, perPage: 10 } });
await dataProvider.getOne('users', { id: 1 });
await dataProvider.create('users', { data: { name: 'Roberto' } });Timeout Locale
Il timeout locale è specificato per ogni singola operazione e sovrascrive il timeout globale solo per quella chiamata specifica. È ideale per:
- Operazioni che richiedono più tempo (upload di file, export di dati)
- Operazioni critiche che necessitano di risposta rapida
- Adattare il timeout in base al tipo di operazione
// Il dataProvider ha un timeout globale di 15 secondi
const dataProvider = new ApplicaDataProvider({
timeout: 15000 // timeout globale
// ...
});
// Timeout locale: questa chiamata aspetterà solo 3 secondi
await dataProvider.getList('users', {
pagination: { page: 1, perPage: 10 },
timeout: 3000 // SOVRASCRIVE il timeout globale per questa chiamata
});
// Upload con timeout esteso: questa chiamata aspetterà 2 minuti
await dataProvider.create('documents', {
data: { file: largeFile },
timeout: 120000 // SOVRASCRIVE il timeout globale per questa chiamata
});
// Questa chiamata userà il timeout globale di 15 secondi (nessun timeout locale specificato)
await dataProvider.getOne('users', { id: 1 });Strategia di Timeout Consigliata
// Configurazione ottimale per la maggior parte delle applicazioni
const dataProvider = new ApplicaDataProvider({
timeout: 30000 // 30 secondi come default sicuro
// ...
});
// Operazioni veloci - timeout ridotto
await dataProvider.getOne('config', { id: 1, timeout: 5000 });
// Operazioni normali - usa il timeout globale
await dataProvider.getList('users', { pagination: { page: 1, perPage: 10 } });
// Upload/download - timeout esteso
await dataProvider.create('files', {
data: { file: bigFile },
timeout: 300000 // 5 minuti per file molto grandi
});
// Operazioni critiche real-time - timeout molto breve
await dataProvider.get('system/status', { timeout: 2000 });
// Chiamate POST personalizzate con timeout
await dataProvider.post('analytics/report', {
startDate: '2024-01-01',
endDate: '2024-12-31',
timeout: 45000 // 45 secondi per report complessi
});La precedenza è sempre: Timeout Locale > Timeout Globale > Default di Sistema (30 secondi)
Operazioni che supportano timeout personalizzato:
getList,getOne,getMany,getManyReference- Tutte le operazioni di letturacreate,update,updateMany- Tutte le operazioni di scritturadelete,deleteMany- Tutte le operazioni di eliminazioneget,post- Chiamate generiche GET e POST
Gestione File e Allegati
Il dataProvider include supporto integrato per il caricamento di file e allegati.
Parser per Allegati
import { createAttachmentsParser } from '@applica-software-guru/crud-client';
// Configurazione di base
const attachmentsParser = createAttachmentsParser();
// Configurazione personalizzata
const customAttachmentsParser = createAttachmentsParser({
images: ['avatar', 'thumbnail', 'banner'],
files: ['document', 'pdf', 'contract'],
attachments: ['gallery'] // array di file
});Upload di File
const fileInput = document.querySelector('input[type="file"]');
const file = fileInput.files[0];
const result = await dataProvider.create('entities/document', {
data: {
title: 'Documento Importante',
file: file, // File object
images: [image1, image2], // Array di immagini
metadata: {
category: 'important'
}
}
});Gestione Errori
Il dataProvider utilizza una classe di errore configurabile per gestire gli errori HTTP.
import { HttpError } from 'ra-core';
const dataProvider = new ApplicaDataProvider({
// ... altre configurazioni
HttpErrorClass: HttpError
});Codici di Errore Standard
401:iam.error.unauthorized- Non autorizzato403:iam.error.forbidden- Accesso negato404:error.not_found- Risorsa non trovata408:error.request_timeout- Timeout richiesta- Errori di validazione:
error.validation - Errori generici:
error.generic
Gestione degli Errori
try {
const result = await dataProvider.getOne('users', { id: 999 });
} catch (error) {
switch (error.message) {
case 'iam.error.unauthorized':
// Reindirizza al login
break;
case 'error.not_found':
// Mostra messaggio "utente non trovato"
break;
case 'error.request_timeout':
// Mostra opzione per ritentare
break;
default:
// Errore generico
console.error('Errore:', error);
}
}Utilizzo con React-Admin
Il dataProvider è completamente compatibile con React-Admin:
import { Admin, Resource } from 'react-admin';
import { ApplicaDataProvider } from '@applica-software-guru/crud-client';
const dataProvider = new ApplicaDataProvider({
// configurazione...
});
function App() {
return (
<Admin dataProvider={dataProvider}>
<Resource name="users" list={UserList} edit={UserEdit} create={UserCreate} />
</Admin>
);
}Migrazione dalla Versione Precedente
Se stai utilizzando la funzione deprecata createDataProvider, migra alla nuova sintassi:
// DEPRECATO ❌
import { createDataProvider } from '@applica-software-guru/crud-client';
const dataProvider = createDataProvider(config);
// NUOVO ✅
import { ApplicaDataProvider } from '@applica-software-guru/crud-client';
const dataProvider = new ApplicaDataProvider(config);Esempi Avanzati
Configurazione Completa per Produzione
import { ApplicaDataProvider, createAttachmentsParser } from '@applica-software-guru/crud-client';
import { createAuthProvider, MemoryStorage } from '@applica-software-guru/iam-client';
import { HttpError } from 'ra-core';
const apiUrl = process.env.REACT_APP_API_URL;
const storage = new MemoryStorage();
const authProvider = createAuthProvider({ apiUrl, storage });
const dataProvider = new ApplicaDataProvider({
apiUrl,
HttpErrorClass: HttpError,
getHeaders: async () => await authProvider.getHeaders(),
getToken: async () => await authProvider.getToken(),
attachmentsParser: createAttachmentsParser({
images: ['avatar', 'banner', 'thumbnail'],
files: ['cv', 'document', 'contract'],
attachments: ['gallery', 'portfolio']
}),
timeout: 15000, // 15 secondi timeout di default
prepareData: (data, resource, params) => {
// Aggiungi timestamp a tutti i record
return {
...data,
updatedAt: new Date().toISOString()
};
}
});
export { dataProvider, authProvider };Gestione Avanzata degli Upload
// Upload con progress tracking
const uploadDocument = async (file, onProgress) => {
try {
const result = await dataProvider.create('documents', {
data: {
title: file.name,
file: file,
category: 'user-upload'
},
timeout: 120000 // 2 minuti per file grandi
});
onProgress(100);
return result;
} catch (error) {
if (error.message === 'error.request_timeout') {
throw new Error('Upload timeout - il file potrebbe essere troppo grande');
}
throw error;
}
};