Create Serverless APIs using Cloudflare Workers, Durable Objects & Wrangler
📦 Installation & Usage
With Apiker, you can create an API in only 3 lines of code
import { apiker, res } from "apiker";
const routes = { "/users/:id/hello": () => res("Hello World!") };
apiker.init({ routes, exports, objects: ["Common"] });
➡️ GET /users/my-user/hello
{ "message": "Hello World!" }
Check out the Getting Started page to begin.
Note: To run Apiker, you need a Cloudflare account with Durable Objects access.
⭐ Features
- 📕 Routing and State management
- 🔑 Auth, JWT-based (Register, Login, Refresh token, Delete user, Forgot user, Verify user email)
- ✅ OAuth handlers (GitHub)
- ⚡️Automatically updates Durable Object migrations, classes and bindings so you don't have to.
- 🛑 Rate Limiting / Flooding mitigation
- 🛡️ Firewall support (IP bans with Cloudflare Firewall)
- 📧 Email support (with Brevo)
- ⚙️ Simple Admin panel
- 👤 Geolocation handlers
- 📝 Logging handlers
📕 Examples
1. Route example
import { res, res_400 } from "apiker";
export const myRouteHandler = async ({
request, // https://developers.cloudflare.com/workers/runtime-apis/request/
body, // The body of your request, such as form params or plaintext, depending on request content-type
headers, // Request headers. Response headers are located at `apiker.responseHeaders`
matches, // Your query params and route parts
state // The state method used to interact with permanent storage (check the examples below & docs for more info)
}) => {
if(request.method !== "POST"){
return res_400();
}
return res({ body });
};
const routes = {
"/users/myroute": myRouteHandler
};
Discuss: https://github.com/hodgef/apiker/issues/133
2. State: Save value to Common
object (shared by all visitors)
import { res } from "apiker";
export const example1_saveValueCommon = async ({ state }) => {
const count = ((await state().get("count")) || 0) + 1;
await state().put({ count });
return res({ count });
};
➡️ GET /example1
{ "count": 1 }
View Source | View Demo
3. State: Save value to a different object, and use one object instance per visitor
import { res } from "apiker";
export const example2_saveValueDiffObject = async ({ state }) => {
const count = (await state("Example2").get("count") || 0) + 1;
await state("Example2").put({ count });
return res({ count });
};
apiker.init({
...
objectStateMapping: {
Example2: OBMT.SIGNEDIP
}
});
➡️ GET /example2
{ "count": 1 }
View Source | View Demo
4. State: Use one object instance per route parameter value
import { res } from "apiker";
export const example3_instancePerRouteParam = async ({ state, matches }) => {
const username = matches.params.username;
const acceptedUsernames = ["bob", "rob", "todd"];
if (acceptedUsernames.includes(username)) {
const { name = username, count = 0 } = (await state("Example3").get("username")) || {};
const payload = {
username: {
name,
count: count + 1
}
};
await state("Example3").put(payload);
return res(payload);
} else {
return res({ acceptedUsernames });
}
};
apiker.init({
...
objectStateMapping: {
Example3: "username"
}
});
➡️ GET /example3/bob
{
"username": {
"name": "bob",
"count": 1
}
}
View Source | View Demo
For more details and examples, check out the Documentation.
✅ Contributing
PRs and issues are welcome. Feel free to submit any issues you have at:
https://github.com/hodgef/Apiker/issues
Questions? Join the chat