# Cloud Functions and the Admin SDK — Firebase

Source: https://www.skillbyai.com/en/firebase/sv-functions

> HTTP, callable and Firestore triggers.

## Three common trigger types

Cloud Functions for Firebase run Node.js (or Python) code on Google infrastructure; the second-generation API is imported from paths such as `firebase-functions/v2/https`. **HTTP functions** (`onRequest`) handle webhooks and plain HTTP. **Callable functions** (`onCall`) are called from the client SDK with `httpsCallable`; Firebase passes the caller's auth (and App Check) context automatically, and you signal errors with `HttpsError`. **Event triggers** such as `onDocumentCreated` react to Firestore, Auth or Storage changes. Inside functions, the **Admin SDK** has full access and **bypasses Security Rules**, so validate input and check `request.auth` yourself. Deploying functions requires the pay-as-you-go plan; check the docs for current plan requirements.

## Callable and trigger functions

TypeScript in functions/src/index.ts.

```typescript
import { onCall, HttpsError } from "firebase-functions/v2/https";
import { onDocumentCreated } from "firebase-functions/v2/firestore";
import { initializeApp } from "firebase-admin/app";
import { getFirestore, FieldValue } from "firebase-admin/firestore";

initializeApp();
const db = getFirestore();

// called from the client: httpsCallable(getFunctions(app), "joinTeam")({ teamId })
export const joinTeam = onCall(async (request) => {
  if (!request.auth) throw new HttpsError("unauthenticated", "Sign in first.");
  const teamId = request.data?.teamId;
  if (typeof teamId !== "string") throw new HttpsError("invalid-argument", "teamId required.");
  await db.doc(`teams/${teamId}/members/${request.auth.uid}`).set({
    joinedAt: FieldValue.serverTimestamp(),
  });
  return { ok: true };
});

// keep a denormalised counter up to date
export const onCommentCreated = onDocumentCreated("posts/{postId}/comments/{commentId}", async (event) => {
  await db.doc(`posts/${event.params.postId}`).update({
    commentCount: FieldValue.increment(1),
  });
});
```

## Make triggers idempotent

Event triggers are delivered at least once, so a function may run more than once for the same event. Design writes so a repeat run does no harm, or record processed event ids.

**Quiz:** Why must a callable function check request.auth and validate data itself?

- [ ] Rules run after the function
- [ ] Callable functions cannot read auth
- [x] The Admin SDK bypasses Security Rules, so the function is the only guard
- [ ] HttpsError disables validation

*Answer:* The Admin SDK bypasses Security Rules, so the function is the only guard. Trusted code carries the responsibility.
