Vai al contenuto principale

Struttura dei Moduli

Ogni modulo API segue una struttura interna coerente con controller, repository, modelli e helper. Comprendere questa organizzazione rende semplice navigare nella codebase e aggiungere nuove funzionalità a qualsiasi modulo.

Prima di Iniziare

Struttura delle Directory

Ogni modulo risiede sotto src/modules/{name}/ e contiene quattro directory:

src/modules/{name}/
├── controllers/ ← Gestori delle route (endpoint Express)
├── repositories/ ← Livello di accesso ai dati (SQL diretto)
├── models/ ← Interfacce e tipi TypeScript
└── helpers/ ← Logica di business specifica del modulo

Ad esempio, il modulo membership:

src/modules/membership/
├── controllers/
│ ├── PersonController.ts
│ ├── GroupController.ts
│ └── ...
├── repositories/
│ ├── PersonRepository.ts
│ ├── GroupRepository.ts
│ └── ...
├── models/
│ ├── Person.ts
│ ├── Group.ts
│ └── ...
└── helpers/
└── ...

Controller

I controller definiscono le route API per un modulo. Estendono CustomBaseController da @churchapps/apihelper e usano i decoratori di Inversify per la registrazione delle route.

import { controller, httpGet, httpPost } from "inversify-express-utils";
import { CustomBaseController } from "@churchapps/apihelper";

@controller("/people")
export class PersonController extends CustomBaseController {

@httpGet("/")
public async loadAll() {
return this.actionWrapper(async (au) => {
// au = contesto utente autenticato
au.checkAccess("People", "View");
const repos = RepositoryManager.getRepositories<MembershipRepositories>("membership");
return repos.person.loadByChurchId(au.churchId);
});
}

@httpPost("/")
public async save() {
return this.actionWrapper(async (au) => {
au.checkAccess("People", "Edit");
const data = this.request.body;
// ... logica di salvataggio
});
}
}

Decoratori delle Route

DecoratoreMetodo HTTP
@httpGet("/path")GET
@httpPost("/path")POST
@httpPut("/path")PUT
@httpPatch("/path")PATCH
@httpDelete("/path")DELETE

Il decoratore @controller("/base") imposta il percorso base per tutte le route nel controller.

Repository

I repository gestiscono tutte le operazioni sul database usando SQL diretto tramite DB.query(). Non c'è ORM -- si scrive SQL direttamente.

export class PersonRepository {
public async loadByChurchId(churchId: string) {
return DB.query("SELECT * FROM people WHERE churchId=?", [churchId]);
}

public async save(person: Person) {
// Logica INSERT o UPDATE
}
}

Accedi ai repository tramite RepositoryManager:

const repos = RepositoryManager.getRepositories<MembershipRepositories>("membership");
const people = await repos.person.loadByChurchId(churchId);

Autenticazione e Autorizzazione

Autenticazione JWT

Tutte le richieste sono autenticate tramite token JWT gestiti da CustomAuthProvider. Il token viene validato automaticamente e il contesto dell'utente autenticato (au) è disponibile in ogni azione del controller.

Controllo dei Permessi

Usa au.checkAccess() per verificare che l'utente corrente abbia il permesso richiesto:

au.checkAccess("People", "View");    // Accesso in lettura
au.checkAccess("People", "Edit"); // Accesso in scrittura

Se l'utente non ha il permesso richiesto, viene restituita automaticamente una risposta di errore.

Avviso

Chiama sempre au.checkAccess() prima di eseguire operazioni sui dati. Non saltare mai i controlli dei permessi, nemmeno per endpoint apparentemente di sola lettura.

Configurazione dell'Ambiente

La classe Environment gestisce la configurazione tra gli ambienti:

  • Sviluppo locale: Legge dal file .env nella root del progetto
  • Ambienti deployati: Legge da AWS SSM Parameter Store
// Accesso alle variabili d'ambiente
const dbConnection = Environment.membershipDb;
const jwtSecret = Environment.jwtSecret;

Questa astrazione significa che il tuo codice non ha bisogno di sapere da dove proviene la configurazione.

Funzioni Lambda

Quando distribuito su AWS, l'API viene eseguito come quattro funzioni Lambda:

FunzioneScopo
webGestisce tutte le richieste HTTP dell'API REST
socketGestisce le connessioni WebSocket per le funzionalità in tempo reale
timer15MinSchedulato ogni 15 minuti per le notifiche email
timerMidnightSchedulato giornalmente per email digest e manutenzione
Info

Localmente, la funzione web gira sulla porta 8084 e la funzione socket sulla porta 8087. Le funzioni timer possono essere attivate manualmente durante lo sviluppo.

Articoli Correlati

  • Database -- Stringhe di connessione, script dello schema e pattern di accesso ai dati
  • Setup Locale dell'API -- Guida completa passo-passo al setup
  • ApiHelper -- La libreria condivisa che fornisce CustomBaseController e il middleware di autenticazione