Configurazione
Efesto si configura tramite l'oggetto che passi a efesto(). Ogni opzione, con il suo
tipo e default, è elencata qui sotto.
I due stack accettano oggetti di configurazione diversi. Gran parte di questa
pagina documenta l'oggetto Express (efesto da "efesto"). Il più piccolo
oggetto Bun/Elysia (efesto/elysia) è documentato nella
sua sezione alla fine.
Costruisci la tua configurazione
Attiva/disattiva le opzioni per assemblare una chiamata efesto({ ... }) di partenza
per entrambi gli stack, poi copiala. Ogni campo corrisponde a un'opzione reale
documentata sotto.
import efesto from "efesto";
app.use(
"/api/v1",
efesto({
authMiddleware: (req, res, next) => next(),
errorMiddleware: (req, res, next) => next(),
isProduction: false,
options: {
absoluteDirRoutes: `${__dirname}/routes`,
generatedTypesFolder: `${__dirname}/efesto-types`,
config: {
defaultRequiredValueForModels: true,
},
},
})
);Oggetto di configurazione Efesto (Express)
La configurazione Express viene passata alla funzione efesto() e contiene la seguente
struttura:
efesto({
authMiddleware: Middleware, // Obbligatorio
errorMiddleware: Middleware, // Obbligatorio
isProduction: boolean, // Obbligatorio
options?: { // Opzionale
absoluteDirRoutes?: string | string[];
generatedTypesFolder?: string;
relativeDirSwaggerDeclarationsPath?: string;
customFormats?: SwaggerFormats;
automaticTypesGenerationInlineFile?: boolean;
config?: ConfigObject;
}
})
Parametri obbligatori
authMiddleware
Tipo: Middleware
Obbligatorio: ✅
Descrizione: il middleware di autenticazione che verrà applicato a tutti gli endpoint.
authMiddleware: (req, res, next) => {
// La tua logica di autenticazione qui
// Esempio: verifica JWT, validazione della sessione, ecc.
// Se l'autenticazione fallisce:
// return res.status(401).json({ error: 'Unauthorized' });
// Se l'autenticazione ha successo:
next();
};
errorMiddleware
Tipo: Middleware
Obbligatorio: ✅
Descrizione: il middleware di gestione degli errori per processare gli errori.
errorMiddleware: (req, res, next) => {
// La tua logica di gestione degli errori qui
// Esempio: logging, formattazione degli errori, ecc.
next();
};
isProduction
Tipo: boolean
Obbligatorio: ✅
Descrizione: abilita la modalità produzione. Quando true, Efesto analizza i file
di rotta .js compilati; quando false analizza i file sorgente .ts (e abilita
funzionalità riservate allo sviluppo come la generazione dei tipi e la modifica magica
del codice).
isProduction: process.env.NODE_ENV === "production";
Parametri opzionali
options.absoluteDirRoutes
Tipo: string | string[]
Default: "/v1/routes"
Descrizione: percorso/i in cui Efesto troverà i file di rotta da analizzare.
// Percorso singolo
absoluteDirRoutes: path.join(__dirname, "routes");
// Percorsi multipli
absoluteDirRoutes: [
path.join(__dirname, "routes"),
path.join(__dirname, "api"),
];
options.generatedTypesFolder
Tipo: string
Default: undefined
Descrizione: cartella in cui Efesto genererà le definizioni dei tipi TypeScript.
generatedTypesFolder: path.join(__dirname, "types");
options.relativeDirSwaggerDeclarationsPath
Tipo: string
Default: "swagger-declarations"
Descrizione: cartella in cui Efesto creerà i file YAML di Swagger.
relativeDirSwaggerDeclarationsPath: "docs/swagger";
options.customFormats
Tipo: SwaggerFormats
Default: undefined
Descrizione: formati Swagger personalizzati per la validazione.
customFormats: {
'custom-format': {
example: 'custom-value'
}
}
options.automaticTypesGenerationInlineFile
Tipo: boolean
Default: false
Descrizione: se generare i tipi inline nello stesso file.
Oggetto Config
L'oggetto config contiene opzioni di configurazione avanzate:
config: {
createdAtField?: string;
updatedAtField?: string;
dynamicParameterType?: "string" | "number";
defaultRequiredValueForModels?: boolean;
defaultNullableOnOptionalFields?: boolean;
customTypes?: { [key: string]: SwaggerDataTypes | SwaggerSchemaItems };
optionalFieldsType?: "null" | "undefined";
canMagicallyEditCode?: boolean;
verbose?: boolean;
mongoIdParser?: boolean;
abacPermissions?: AbacConfigurationObject;
redis?: RedisConfigurationObject;
}
| Opzione | Tipo | Default | Descrizione |
|---|---|---|---|
createdAtField | string | "createdAt" | Campo usato come timestamp di creazione |
updatedAtField | string | "updatedAt" | Campo usato come timestamp di aggiornamento |
dynamicParameterType | "string" | "number" | "string" | Tipo documentato dei parametri di percorso [param] |
defaultRequiredValueForModels | boolean | true | I campi sono obbligatori salvo che siano marcati ? |
defaultNullableOnOptionalFields | boolean | false | I campi opzionali (?) diventano anche nullable |
optionalFieldsType | "null" | "undefined" | "undefined" | Tipo dei campi opzionali (usa "null" con Prisma) |
customTypes | Record<string, …> | undefined | Tipi nominati riutilizzabili per i Magic Types (vedi sotto) |
canMagicallyEditCode | boolean | true | Permetti a Efesto di riscrivere le firme dei metodi (solo dev) |
verbose | boolean | false | Logging di avvio dettagliato |
mongoIdParser | boolean | false | Mappa _id su id nelle risposte |
abacPermissions | object | undefined | Config ABAC |
redis | object | undefined | Config Redis |
customTypes mappa un nome su un tipo base o uno schema, poi usi il nome come
qualsiasi Magic Type:
customTypes: {
ObjectId: "string",
Date: { type: "string", format: "date-time" },
Decimal: { type: "number", format: "decimal" },
}
Le opzioni di generazione dei tipi (generatedTypesFolder,
automaticTypesGenerationInlineFile, canMagicallyEditCode) sono trattate in
Generazione dei tipi.
Configurazione ABAC
abacPermissions
Tipo: AbacConfigurationObject
Default: undefined
Descrizione: configurazione per il controllo degli accessi basato sugli attributi.
abacPermissions: {
actions?: string[];
models?: string[];
checkPermissionBeforeResolver?: boolean;
reqAbilityField?: string;
}
Opzioni di configurazione ABAC
actions: array di azioni consentite (es.["read", "write", "delete"])models: array di nomi di modello a cui applicare i permessicheckPermissionBeforeResolver: se verificare i permessi prima di eseguire i resolverreqAbilityField: nome del campo nell'oggetto request che contiene l'ability (default:"ability")
abacPermissions: {
actions: ["read", "write", "delete"],
models: ["User", "Post", "Comment"],
checkPermissionBeforeResolver: true,
reqAbilityField: "userAbility"
}
Configurazione Redis
redis
Tipo: RedisConfigurationObject
Default: undefined
Descrizione: configurazione per il caching con Redis.
redis: {
host: string;
port: number;
defaultExpiresInSeconds: number;
}
Opzioni di configurazione Redis
host: hostname del server Redisport: porta del server RedisdefaultExpiresInSeconds: tempo di scadenza della cache di default
redis: {
host: "127.0.0.1",
port: 6379,
defaultExpiresInSeconds: 600
}
Variabili d'ambiente
Puoi usare le variabili d'ambiente per configurare Efesto:
// file .env
NODE_ENV=development
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_EXPIRES=600
EFESTO_VERBOSE=true
EFESTO_TYPES_FOLDER=./types
// Nella tua configurazione
efesto({
authMiddleware: authMiddleware,
errorMiddleware: errorMiddleware,
isProduction: process.env.NODE_ENV === "production",
options: {
absoluteDirRoutes: "./routes",
generatedTypesFolder: process.env.EFESTO_TYPES_FOLDER,
config: {
verbose: process.env.EFESTO_VERBOSE === "true",
redis: process.env.REDIS_HOST
? {
host: process.env.REDIS_HOST,
port: parseInt(process.env.REDIS_PORT || "6379"),
defaultExpiresInSeconds: parseInt(
process.env.REDIS_EXPIRES || "600"
),
}
: undefined,
},
},
});
Esempio di configurazione completa
import express from "express";
import efesto from "efesto";
import path from "path";
const app = express();
// Middleware
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Middleware di autenticazione
const authMiddleware = (req, res, next) => {
const token = req.headers.authorization?.replace("Bearer ", "");
if (!token) {
return res.status(401).json({ error: "No token provided" });
}
try {
// Verifica del token JWT
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded;
next();
} catch (error) {
return res.status(401).json({ error: "Invalid token" });
}
};
// Middleware degli errori
const errorMiddleware = (req, res, next) => {
console.error("Error:", req.error);
res.status(500).json({
error: "Internal Server Error",
message:
process.env.NODE_ENV === "development" ? req.error?.message : undefined,
});
};
// Configurazione di Efesto
app.use(
"/api/v1",
efesto({
authMiddleware,
errorMiddleware,
isProduction: process.env.NODE_ENV === "production",
options: {
absoluteDirRoutes: path.join(__dirname, "routes"),
generatedTypesFolder: path.join(__dirname, "types"),
relativeDirSwaggerDeclarationsPath: "swagger-declarations",
automaticTypesGenerationInlineFile: false,
config: {
createdAtField: "createdAt",
updatedAtField: "updatedAt",
dynamicParameterType: "string",
defaultRequiredValueForModels: true,
defaultNullableOnOptionalFields: false,
optionalFieldsType: "undefined",
canMagicallyEditCode: true,
verbose: process.env.NODE_ENV === "development",
mongoIdParser: false,
customTypes: {
ObjectId: "string",
Date: { type: "string", format: "date-time" },
Email: { type: "string", format: "email" },
},
abacPermissions: {
actions: ["read", "write", "delete"],
models: ["User", "Post", "Comment"],
checkPermissionBeforeResolver: true,
reqAbilityField: "ability",
},
redis: process.env.REDIS_HOST
? {
host: process.env.REDIS_HOST,
port: parseInt(process.env.REDIS_PORT || "6379"),
defaultExpiresInSeconds: parseInt(
process.env.REDIS_EXPIRES || "600"
),
}
: undefined,
},
},
})
);
export default app;
Configurazione Bun/Elysia (efesto/elysia)
L'entrypoint Elysia accetta un oggetto più piccolo. Non ha authMiddleware,
errorMiddleware, swaggerModel o generazione di YAML: validazione, OpenAPI e hook
sono tutti nativi di Elysia.
import efesto from "efesto/elysia";
const app = efesto({
isProduction: process.env.NODE_ENV === "production", // obbligatorio
routesDir: `${import.meta.dir}/routes`, // obbligatorio
prefix: "/api/v1", // opzionale
swagger: true, // opzionale (default true)
setup: (root) => { // opzionale
// aggiungi plugin/hook globali prima del mount delle rotte (auth, ability ABAC, cors, ...)
},
abac: { // opzionale
abilityField: "ability",
checkPermissionBeforeResolver: true,
},
}).listen(2014);
| Parametro | Tipo | Obbligatorio | Descrizione | Default |
|---|---|---|---|---|
isProduction | boolean | ✅ | Analizza i file di rotta .js compilati invece dei .ts | — |
routesDir | string | string[] | ✅ | Directory (o directory) analizzate per i moduli di rotta | — |
prefix | string | ❌ | Prefisso di mount per l'intera app, es. /api/v1 | nessuno |
swagger | boolean | OpenApiOptions | ❌ | Abilita il plugin OpenAPI nativo; passa un oggetto per personalizzarlo | true |
setup | (app) => unknown | ❌ | Aggiungi plugin/hook globali sulla root prima del mount delle rotte | — |
abac | { abilityField?, checkPermissionBeforeResolver? } | ❌ | Regola l'applicazione dei permission basati su classe | vedi ABAC |
efesto(...) restituisce un'istanza Elysia nativa, quindi puoi farne .listen(...) o
montarla come plugin con new Elysia().use(efesto(...)).