| name | description | license |
|---|---|---|
azure-functions-v4-migration |
Migrate Azure Functions from the deprecated Node.js v3 model to the new v4 model. Use when asked to upgrade Azure Functions, migrate to v4 model, or refactor function handlers to follow the latest standards. |
Complete terms in LICENSE.txt |
This skill provides the instructions and patterns required to migrate PagoPA Azure Functions from the deprecated Node.js v3 model to the new v4 model using the wrapHandlerV4 adapter from @pagopa/io-functions-commons.
- When upgrading a project's Azure Functions model from v3 to v4.
- When refactoring existing handlers to use the standardized
wrapHandlerV4approach. - When creating new Azure Functions that should follow the v4 model.
@azure/functionsversion^4.0.0@pagopa/io-functions-commonsversion^30.0.0- TypeScript project setup.
Update the dependencies and add the main entry point.
| Field | Action | Value |
|---|---|---|
main |
Add/Update | dist/main.js |
@azure/functions |
Update | ^4.0.0 |
@pagopa/io-functions-commons |
Update | ^30.0.0 |
@pagopa/express-azure-functions |
Remove | (No longer needed) |
express |
Remove | (If only used for v3 adapter) |
The v4 model uses a code-first approach for registration.
- Remove all
function.jsonfiles in function directories. - Remove
index.tsfiles that served as v3 entry points. - Remove winston-related logging boilerplate (e.g.,
AzureContextTransportsetup) as v4 handles logging natively throughInvocationContext.
Create a centralized src/main.ts to register all HTTP functions.
import { app } from "@azure/functions";
import { Info } from "./Info/handler";
// Import other handlers...
app.http("Info", {
methods: ["GET"],
authLevel: "anonymous", // or "function"
route: "info",
handler: Info(),
});
// Register other functions...Replace v3 wrapping logic with wrapHandlerV4.
| Feature | v3 (Old) | v4 (New) |
|---|---|---|
| Wrapper | wrapRequestHandler(handler) |
wrapHandlerV4(middlewares, handler) |
| Import | @pagopa/io-functions-commons/dist/src/utils/request_middleware |
@pagopa/io-functions-commons/dist/src/utils/azure-functions-v4-express-adapter |
| Context | Context |
InvocationContext |
| Error Log | context.log.error |
context.error |
| Debug Log | context.log.verbose |
context.debug |
| Warning Log | context.log.warn |
context.warn |
| Info Log | context.log.info |
context.log |
In v4, the handler receives the InvocationContext as the first argument, followed by the resolved values of the middlewares in the order they are defined in the middlewares array.
- Note:
ContextMiddleware()result is typically the context itself and is often skipped or merged in the handler signature if it's the first middleware.
type IMyHandler = (
context: InvocationContext,
token: TokenParam, // First middleware after ContextMiddleware
) => Promise<IResponse...>;Standardize middlewares using built-in factories from @pagopa/io-functions-commons where possible:
// Old custom middleware
export const TokenHeaderParamMiddleware = async (request: Request) => ...
// New standardized middleware
export const TokenHeaderParamMiddleware = RequiredHeaderMiddleware(
TOKEN_HEADER_NAME,
TokenParam,
);import { wrapHandlerV4 } from "@pagopa/io-functions-commons/dist/src/utils/azure-functions-v4-express-adapter";
import { ContextMiddleware } from "@pagopa/io-functions-commons/dist/src/utils/middlewares/context_middleware";
export const MyFunction = () => {
const handler = MyFunctionHandler();
const middlewares = [
ContextMiddleware(),
// Add other middlewares here
] as const;
return wrapHandlerV4(middlewares, handler);
};Ensure middlewares are compatible with the v4 adapter. Many PagoPA-standard middlewares already work, but some may need to be updated to return the expected Promise<Either<...>> format if they were using custom Express-style logic.
Update unit tests to accommodate the new InvocationContext and handler signature.
- Change
Contextmocks toInvocationContext. - Update property accesses (
log.errortoerror). - v4 handlers are invoked as
handler(context, ...args)whereargsare the resolved middleware results.
| Issue | Solution |
|---|---|
| Functions not discovered | Ensure main in package.json points to the compiled main.js. |
| Middleware type mismatch | Ensure middlewares are passed as a const array to wrapHandlerV4 to preserve type inference. |
Missing context in handler |
Ensure ContextMiddleware() is included in the middlewares array. |
Build errors with express |
Remove express and @types/express if they are no longer explicitly used outside of the adapter. |