Installazione
Efesto distribuisce due stack da un unico pacchetto. Scegli la tab per il tuo
runtime: il resto della documentazione usa lo stesso groupId, così la tua scelta ti
segue tra le pagine.
Prerequisiti
- Express
- Bun/Elysia
Installa
- Express
- Bun/Elysia
npm install efesto express
# oppure: yarn add efesto express / pnpm add efesto express
npm install -D typescript @types/node @types/express
Elysia e il plugin OpenAPI sono peer dependency opzionali: installale insieme a Efesto:
bun add efesto elysia @elysiajs/openapi
Struttura del progetto
L'unico requisito imprescindibile è una directory delle rotte i cui file mappino i percorsi. Una disposizione comune:
my-efesto-api/
├── src/ (o lib/)
│ ├── routes/ # endpoint — il percorso del file diventa il percorso URL
│ │ └── users/
│ │ └── index.ts
│ ├── server.ts # oppure app.ts
│ └── ...
├── tsconfig.json
└── package.json
Lo stack Express scrive in aggiunta l'OpenAPI generato in una cartella
swagger-declarations/ (configurabile). Lo stack Elysia serve l'OpenAPI dalla memoria
e non scrive nulla.
Il tuo primo endpoint
- Express
- Bun/Elysia
src/routes/users/index.ts — una classe di servizio. La posizione del file
(users/index.ts) diventa il percorso /users:
import { BaseApiService, SwaggerModel, SwaggerOptions } from "efesto";
class Users extends BaseApiService {
constructor() {
super(__filename);
}
swaggerModel: SwaggerModel = {
modelName: "User",
schemas: [
{
name: "User",
properties: {
id: "number",
name: "string",
email: "string::email",
},
},
],
};
_getSwagger: SwaggerOptions = {
operationId: "getUsers",
summary: "List users",
responses: { 200: "@User[]" }, // forma breve: un array di User
};
async _get(req, res) {
return res.json([{ id: 1, name: "Ada", email: "ada@example.com" }]);
}
}
export default Users;
src/app.ts — monta Efesto come middleware Express:
import express from "express";
import efesto from "efesto";
import path from "path";
const app = express();
app.use(express.json());
app.use(
"/api/v1",
efesto({
authMiddleware: (req, res, next) => next(), // la tua auth qui
errorMiddleware: (req, res, next) => next(), // la tua gestione errori qui
isProduction: process.env.NODE_ENV === "production",
options: {
absoluteDirRoutes: path.join(__dirname, "routes"),
relativeDirSwaggerDeclarationsPath: "swagger-declarations",
},
})
);
app.listen(3000, () => console.log("http://localhost:3000/api/v1"));
Eseguilo:
npx ts-node src/app.ts # dev
# oppure: tsc && node dist/app.js
GET http://localhost:3000/api/v1/users restituisce la lista.
src/routes/user/index.ts — un modulo Elysia nativo. La posizione del file
(user/index.ts) diventa il prefisso /user:
import { Elysia, t } from "efesto/elysia"; // ri-esporta `Elysia` e `t` di Elysia
const users = [{ id: 1, name: "Ada", surname: "Lovelace" }];
export default new Elysia()
.get("/", () => users, {
detail: { summary: "List users", tags: ["User"] },
})
.post("/", ({ body }) => ({ id: users.length + 1, ...body }), {
body: t.Object({ name: t.String(), surname: t.String() }),
detail: { summary: "Create user", tags: ["User"] },
});
src/server.ts — crea l'app:
import efesto from "efesto/elysia";
const app = efesto({
isProduction: process.env.NODE_ENV === "production",
routesDir: `${import.meta.dir}/routes`,
prefix: "/api/v1",
swagger: true, // OpenAPI nativo su /api/v1/openapi
}).listen(2014);
console.log(`http://localhost:${app.server?.port}/api/v1`);
Eseguilo:
bun run src/server.ts
GET http://localhost:2014/api/v1/user restituisce la lista; l'OpenAPI è su
/api/v1/openapi.
Visualizzare la documentazione
- Express
- Bun/Elysia
Efesto scrive file OpenAPI .yaml in swagger-declarations/. Uniscili in un bundle e
servi una UI con swagger-ui-express:
import swaggerUi from "swagger-ui-express";
// dopo il middleware Efesto (apis.json è il documento in bundle)
app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(require("../swagger-declarations/apis.json")));
Vedi Documentazione Swagger per l'intera pipeline.
Niente da configurare: @elysiajs/openapi serve un documento interattivo su
<prefix>/openapi (qui /api/v1/openapi) ogni volta che swagger non è false.
Risoluzione dei problemi
- Rotte non trovate — verifica che
absoluteDirRoutes(Express) /routesDir(Elysia) puntino alla cartella reale e cheisProductioncorrisponda ai tuoi file: la produzione analizza i.js, lo sviluppo i.ts. - Express: nulla esportato — un file di rotta deve fare
export defaultdi una classe che estendeBaseApiService. - Elysia: modulo saltato — un file di rotta deve fare
export defaultdi un'istanza Elysia nativa oppure di una classe/istanza che estendeBaseApiService; qualsiasi altra cosa viene saltata con un avviso. - Elysia: peer dep —
elysiae@elysiajs/openapisono peer opzionali; se usi lo stack Elysia devi installarle tu.
Poi, impara il modello degli endpoint o l'intera configurazione.