inbox: add health endpoint & docs (#64)

* inbox: add health endpoint && docs

* inbox: update post endpoint uri

* inbox: update docs & dockerfile

---------

Co-authored-by: Abdullah Atta <abdullahatta@streetwriters.co>
This commit is contained in:
01zulfi
2026-03-27 14:20:42 +05:00
committed by GitHub
parent 3a2a04317f
commit 1c5bcd6eff
3 changed files with 85 additions and 8 deletions

View File

@@ -1,4 +1,4 @@
FROM oven/bun:1.2.21-slim
FROM oven/bun:1.3.5-slim
RUN mkdir -p /home/bun/app && chown -R bun:bun /home/bun/app

View File

@@ -0,0 +1,68 @@
# Notesnook Inbox API
## Running locally
### Requirements
- Bun (v1.3.0 or higher)
### Commands
- `bun install` - Install dependencies
- `bun run dev` - Start the development server
- `bun run build` - Build the project for production
- `bun run start` - Start the production server
## Self-hosting
The easiest way to self-host is with Docker or Docker Compose.
Prerequisites:
- `docker` (Engine) installed
- `docker-compose` (optional, for multi-service setups)
Build and run with Docker:
```bash
# build the image from the current folder
docker build -t notesnook-inbox-api .
# run the container (example)
docker run --rm -p 3000:3000 \
-e PORT=3000 \
-e NOTESNOOK_API_SERVER_URL="https://api.notesnook.com" \
notesnook-inbox-api
```
Docker Compose (example):
```yaml
services:
inbox-api:
image: notesnook-inbox-api
build: .
ports:
- "3000:3000"
environment:
PORT: 3000
NOTESNOOK_API_SERVER_URL: "https://api.notesnook.com"
restart: unless-stopped
```
Environment variables:
- `PORT` — port the service listens on (default: `5181`)
- `NOTESNOOK_API_SERVER_URL` — base URL of the Notesnook API used to fetch public inbox keys
_If you prefer running without Docker, use `bun install` and `bun run start` with the environment variables set._
## Writing from scratch
The inbox API server is pretty simple to write from scratch in any programming language and/or framework. There's only one endpoint that needs to be implemented, which does these three steps:
1. Fetch the user's public inbox API key from the Notesnook API.
2. Encrypt the payload using `openpgp` or any other `openpgp` compatible library.
3. Post the encrypted payload to the Notesnook API.
You can refer to the [source code](./src/index.ts) for implementation details.

View File

@@ -33,9 +33,15 @@ interface EncryptedInboxItem {
alg: string;
}
/**
* Encrypts raw data using OpenPGP with the recipient's public key
*
* @param {string} rawData - The plaintext data to encrypt
* @param {string} rawPublicKey - The recipient's OpenPGP public key
*/
async function encrypt(
rawData: string,
rawPublicKey: string
rawPublicKey: string,
): Promise<EncryptedInboxItem> {
const publicKey = await openpgp.readKey({ armoredKey: rawPublicKey });
const message = await openpgp.createMessage({ text: rawData });
@@ -57,11 +63,11 @@ async function getInboxPublicEncryptionKey(apiKey: string) {
headers: {
Authorization: apiKey,
},
}
},
);
if (!response.ok) {
throw new Error(
`failed to fetch inbox public encryption key: ${await response.text()}`
`failed to fetch inbox public encryption key: ${await response.text()}`,
);
}
@@ -71,7 +77,7 @@ async function getInboxPublicEncryptionKey(apiKey: string) {
async function postEncryptedInboxItem(
apiKey: string,
item: EncryptedInboxItem
item: EncryptedInboxItem,
) {
const response = await fetch(`${NOTESNOOK_API_SERVER_URL}/inbox/items`, {
method: "POST",
@@ -92,9 +98,12 @@ app.use(
rateLimit({
windowMs: 1 * 60 * 1000, // 1 minute
limit: 60,
})
}),
);
app.post("/inbox", async (req, res) => {
app.get("/health", (_, res) => {
return res.status(200).json({ status: "ok" });
});
app.post("/", async (req, res) => {
try {
const apiKey = req.headers["authorization"];
if (!apiKey) {
@@ -117,7 +126,7 @@ app.post("/inbox", async (req, res) => {
const encryptedItem = await encrypt(
JSON.stringify(validationResult.data),
inboxPublicKey
inboxPublicKey,
);
console.log("[info] encrypted item");