Azure Deploy Example - Typescript

post-thumb

Today we’ll deploy a tiny TypeScript function to Azure Functions on the Linux Consumption plan. It’s a single HTTP endpoint that returns “Hello world.”

Architecture

LayerComponentResponsibilityFiles / PackagesNotes
ClientCLI (curl) / Postman / HTTPieSend HTTP requests to test the APIUse curl in examples; GUI tools like Postman also work.
API (Functions)Azure Functions (HTTP trigger)Expose REST endpoints under /api (e.g., /api/test)src/functions/test.ts, @azure/functionsAzure Functions v4, Node 20 (Linux Consumption).
Handlerapp.http("test", …)Route + handle GET requests, return JSONsrc/functions/test.tsroute: "test" → final path /api/test; authLevel: "anonymous" for quick testing.
DTO / PayloadSimple object { message: string }Define response shapesrc/functions/test.tsKeep payloads explicit; expand to request DTOs when adding POST/PUT.
Response Helpersjson(status, body) utilityConsistent JSON responses + headerssrc/functions/test.tsCentralizes status code + Content-Type: application/json.
Error HandlingTry/catch + ctx.log.errorReturn proper HTTP status codes on failuressrc/functions/test.ts500 on unhandled errors; prefer ctx.log over console.log for structured logs.
ConfigFunctions host + local settingsRuntime & local dev configurationhost.json, local.settings.json/api prefix comes from Functions defaults; secrets live in App Settings in Azure.
Build ToolingNode + npm + Func Core ToolsCompile TypeScript, run locally, publish to Azurepackage.json, tsconfig.json, Azure Functions Core Tools (func)npm run buildfunc start; func azure functionapp publish <app>.
Cloud ResourcesFunction App + Storage AccountHost the function; store triggers/state/artifactsCreated via az functionapp create, az storage account createStorage account name: 3–24 chars, lowercase + digits, globally unique.
ObservabilityApp Insights (optional)Centralized logs/metrics/tracesEnable in Function App → Application InsightsHelpful once you add more routes or start troubleshooting.
Security/AuthAnonymous (for demo)Public endpoint for quick testingauthLevel: "anonymous" in handlerSwitch to function/admin or enable Easy Auth/Entra ID before real use.
PlatformNode.js 20 LTSLanguage/runtime versionSpecified on Function App (--runtime-version 20)Stick to LTS for stability and Functions compatibility.

Dependencies

Login to Azure and select subscription

We need to login to Azure. Use the default subscription that was created when free account was created.

az login
az account list -o table
az account set --subscription "<Your-Subscription-Name-or-ID>"

Register namespaces

We need a couple namespaces enabled for the application, so enable them if not already. If state is “registering”, wait a couple minutes and run show command again.

az provider show --namespace Microsoft.Storage --query "registrationState"
az provider show --namespace Microsoft.Web    --query "registrationState"
az provider register --namespace Microsoft.Storage
az provider register --namespace Microsoft.Web

Create resource group

Resource group contains all the resources for this project. Choose the location from given list, we use westeurope as an example.

az account list-locations --query "[].name" -o tsv
az group create \
  -n azure-deploy-example \
  -l westeurope

Create storage account

Functions requires a general-purpose storage account for triggers, logs, and state.

Use Standard_LRS (lowest cost). Storage isn’t “free”, but with small usage and free credits it’s typically zero cost while learning. Naming rules: 3–24 chars, lowercase letters & numbers only, globally unique. So in case the name is taken, choose some other name.

az storage account create \
  -n azuredeployecxzxghr0m \
  -g azure-deploy-example \
  -l westeurope \
  --sku Standard_LRS

Create function app

Next we create function application that holds our functions. Application name must be globally unique (becomes <name>.azurewebsites.net).

az functionapp create \
  -n azure-deploy-example-ecxzxghr0m \
  -g azure-deploy-example \
  --consumption-plan-location westeurope \
  --runtime node \
  --runtime-version 20 \
  --functions-version 4 \
  --os-type linux \
  --storage-account azuredeployecxzxghr0m

Prepare the app

The application is very basic, mostly whatever is coming from scaffold. Application sources are here.

Scaffold the project

Create repository files with func cli tool.

mkdir ts-func && cd ts-func
func init . --typescript
npm install

Create function

Save file to src/functions/test.ts

import { app, HttpRequest, HttpResponseInit, InvocationContext } from "@azure/functions";

function json(status: number, body: unknown): HttpResponseInit {
  return { status, jsonBody: body, headers: { "Content-Type": "application/json" } };
}

app.http("test", {
    // /api is added automatically as a route prefix unless changed in host.json
    route: "test",
    methods: ["GET"],
    authLevel: "anonymous",
    handler: async (req: HttpRequest, ctx: InvocationContext): Promise<HttpResponseInit> => {
        try {
            switch (req.method) {
                case "GET": {
                    return json(200, { message: "Hello world" });
                }

                default:
                    return json(405, { error: "Method not allowed" });
            }
        } catch (err: any) {
            ctx.log.error("Unhandled error", err);
            return json(500, { error: "Internal Server Error" });
        }
    },
});

Run locally

Build and run application, and then we can test it with curl, browser or any other similar tool.

npm run build
func start

# in another terminal window
curl http://localhost:7071/api/test

Publish

This will publish app to production.

npm run build
func azure functionapp publish azure-deploy-example-ecxzxghr0m

# test in the cloud
curl https://azure-deploy-example-ecxzxghr0m.azurewebsites.net/api/test

Recap

We created a Function App, added a TypeScript HTTP function, tested locally, and published to Azure.

comments powered by Disqus