mirror of
https://github.com/streetwriters/notesnook-sync-server.git
synced 2026-03-28 22:10:48 +01:00
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:
@@ -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
|
||||
|
||||
|
||||
68
Notesnook.Inbox.API/README.md
Normal file
68
Notesnook.Inbox.API/README.md
Normal 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.
|
||||
@@ -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");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user