Skip to content

Commit 72fd14e

Browse files
LiamandrewGabrola
andauthored
feat(serverless): add support for Azure Functions V4 serverless runtime (#615)
Co-authored-by: Youssef Gaber <1728215+Gabrola@users.noreply.github.com>
1 parent c2dcab1 commit 72fd14e

27 files changed

Lines changed: 1336 additions & 5 deletions

.changeset/twelve-needles-walk.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@ts-rest/serverless': minor
3+
---
4+
5+
Add Azure Functions compatibility
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Azure Functions
2+
3+
The Azure Function handler can handle the Azure Functions V4 programming model.
4+
5+
```typescript
6+
import { app } from '@azure/functions';
7+
import { createAzureFunctionHandler } from '@ts-rest/serverless/azure';
8+
import { contract } from './contract';
9+
import { router } from './router';
10+
11+
const handler = createAzureFunctionHandler(contract, router, {
12+
// options
13+
});
14+
15+
// This will register a single function handler for the handler
16+
app.http('api', {
17+
// Be sure to include any method that the router requires
18+
methods: ['POST', 'PATCH', 'DELETE', 'GET'],
19+
authLevel: 'anonymous',
20+
route: '{*route}',
21+
handler,
22+
});
23+
```
24+
25+
## Route Prefix
26+
27+
By default, Azure Functions have a route prefix `api` for every route registered. Unless you specifically have the same in your contract, then you will need to add the following to the end of your `host.json` file to remove this prefix.
28+
29+
```json
30+
// host.json
31+
{
32+
...,
33+
"extensions": {
34+
"http": {
35+
"routePrefix": ""
36+
}
37+
}
38+
}
39+
```
40+
41+
## Context Object
42+
43+
In addition to the regular context properties, the context object for Azure Function handlers includes the following additional properties:
44+
45+
- `rawHttpRequest: HttpRequest`: The raw request that was passed to the Azure Function
46+
- `azureContext: InvocationContext`: The Azure Function Invocation Context passed with each invocation of a function
47+
48+
```typescript
49+
import { createLambdaHandler } from '@ts-rest/serverless/aws';
50+
import { contract } from './contract';
51+
52+
export const handler = createAzureFunctionHandler(
53+
contract,
54+
{
55+
getPost: async ({ params: { id } }, { azureContext, rawHttpRequest }) => {
56+
azureContext.log('Received request!');
57+
58+
return {
59+
status: 200,
60+
body: {
61+
id,
62+
title: 'Hello, World!',
63+
},
64+
};
65+
},
66+
},
67+
{
68+
requestMiddleware: [
69+
(request, { rawHttpRequest, azureContext }) => {
70+
console.log('Raw HttpRequest:', rawHttpRequest);
71+
console.log('Azure Invocation Context:', azureContext);
72+
},
73+
],
74+
responseHandlers: [(response, request, { rawHttpRequest, azureContext }) => {}],
75+
},
76+
);
77+
```

apps/docs/sidebars.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ const sidebars = {
123123
{ type: 'doc', id: 'serverless/fetch-runtimes' },
124124
{ type: 'doc', id: 'serverless/aws' },
125125
{ type: 'doc', id: 'serverless/next-serverless' },
126+
{ type: 'doc', id: 'serverless/azure-functions' },
126127
],
127128
},
128129
{

apps/example-azure-function/.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
FUNCTIONS_WORKER_RUNTIME=node
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"extends": ["../../.eslintrc.json"],
3+
"ignorePatterns": ["!**/*"],
4+
"overrides": [
5+
{
6+
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7+
"rules": {
8+
"@typescript-eslint/no-unused-vars": ["warn"],
9+
"@typescript-eslint/no-explicit-any": ["warn"]
10+
}
11+
},
12+
{
13+
"files": ["*.ts", "*.tsx"],
14+
"rules": {}
15+
},
16+
{
17+
"files": ["*.js", "*.jsx"],
18+
"rules": {}
19+
}
20+
]
21+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
*.js.map
2+
*.ts
3+
.git*
4+
.vscode
5+
local.settings.json
6+
test
7+
getting_started.md
8+
node_modules/@types/
9+
node_modules/azure-functions-core-tools/
10+
node_modules/typescript/
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
bin
2+
obj
3+
csx
4+
.vs
5+
edge
6+
Publish
7+
8+
*.user
9+
*.suo
10+
*.cscfg
11+
*.Cache
12+
project.lock.json
13+
14+
/packages
15+
/TestResults
16+
17+
/tools/NuGet.exe
18+
/App_Data
19+
/secrets
20+
/data
21+
.secrets
22+
appsettings.json
23+
local.settings.json
24+
25+
node_modules
26+
dist
27+
28+
# Local python packages
29+
.python_packages/
30+
31+
# Python Environments
32+
.venv
33+
env/
34+
venv/
35+
ENV/
36+
env.bak/
37+
venv.bak/
38+
39+
# Byte-compiled / optimized / DLL files
40+
__pycache__/
41+
*.py[cod]
42+
*$py.class
43+
44+
# Azurite artifacts
45+
__blobstorage__
46+
__queuestorage__
47+
__azurite_db*__.json
48+
49+
!.env
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"version": "2.0",
3+
"logging": {
4+
"applicationInsights": {
5+
"samplingSettings": {
6+
"isEnabled": true,
7+
"excludedTypes": "Request"
8+
}
9+
}
10+
},
11+
"extensionBundle": {
12+
"id": "Microsoft.Azure.Functions.ExtensionBundle",
13+
"version": "[4.*, 5.0.0)"
14+
},
15+
"extensions": {
16+
"http": {
17+
"routePrefix": ""
18+
}
19+
}
20+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/* eslint-disable */
2+
export default {
3+
displayName: 'example-azure-function',
4+
preset: '../../jest.preset.js',
5+
globals: {},
6+
testEnvironment: 'node',
7+
transform: {
8+
'^.+\\.[tj]s$': [
9+
'ts-jest',
10+
{
11+
tsconfig: '<rootDir>/tsconfig.spec.json',
12+
},
13+
],
14+
},
15+
moduleFileExtensions: ['ts', 'js', 'html'],
16+
coverageDirectory: '../../coverage/apps/example-azure-function',
17+
};
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"name": "example-azure-function",
3+
"version": "0.0.0",
4+
"main": "../../dist/apps/example-azure-function/*.js"
5+
}

0 commit comments

Comments
 (0)