App SDK
The App SDK is the toolkit for building revenexx Apps. An App declares its data in JSON and runs a function for its custom logic. The SDK gives that function two things: a typed data client over the app's own tables, and a small HTTP router for the function's request handling. It also ships a CLI that generates the typed client from your app's declarations.
Status: early (0.x), under active development. It's available for JavaScript/TypeScript and PHP.
If you're new to Apps, read the App Marketplace overview and the app model first — this page is about the SDK you write the app's code with.
Install
npm install @revenexx/app-sdk
For an app written in PHP, the Composer package is revenexx/app-sdk (PHP 8.2 or newer).
composer require revenexx/app-sdk
Generate the typed client
Your app declares its tables in schema.json and its identity and permissions in manifest.json. The CLI reads both and generates a typed data client. Generate JavaScript or PHP.
npx appsdk generate \
--schema ./schema.json \
--manifest ./manifest.json \
--out ./src/db \
--target js
The generated client only exposes the operations your manifest grants. If the manifest gives an entity read access, the client has list and get; create, update, and delete follow the matching grants. Ungranted operations aren't generated, so the permission boundary is enforced in the types, not just at runtime.
Adapters: the same code in every environment
The data client takes an adapter. Your app code stays the same; you swap the adapter for where it runs.
| Adapter | What it does | Use it for |
|---|---|---|
mock | In-memory fixtures, no infrastructure. | Unit tests and fast local iteration. |
remote | Real data over HTTP against a dev tenant. | Checking behavior against the real data plane before deploy. |
runtime | Production. Auto-configured from the function's invocation context. | The deployed App (JavaScript only). |
import { createDb } from "./db/db.generated.js";
const db = createDb({ adapter: "mock", seed: { greetings: [] } });
await db.greetings.create({ name: "Max" });
const list = await db.greetings.list({
where: { locale: "en" },
order: "created_at.desc",
limit: 20,
});
Queries take where, select, order, limit, and offset. The where operators are eq, neq, gt, gte, lt, lte, like, ilike, in, and is.
The app's function handler
For an App with custom logic, the SDK's router turns the function's request into declarative routes. createApp makes the router; mountCrud exposes an entity over standard CRUD paths.
const { createApp, mountCrud } = require("@revenexx/app-sdk/router");
const { createDb, ENTITIES } = require("./db.generated");
module.exports = (context) => {
const app = createApp({ name: "markets" });
const db = createDb({ adapter: "runtime", context });
mountCrud(app, db.markets, {
path: "/markets",
columns: ENTITIES.markets.columns,
});
return app.handler()(context);
};
In production the runtime adapter reads the App's invocation context, so you don't wire up the endpoint, tenant, or credentials yourself. When you use the remote adapter to test against a dev tenant, the data-plane call carries the public auth contract: Authorization: Bearer <token> and X-Revenexx-Tenant: <slug>.
The router also gives you HTTP error helpers — notFound, badRequest, forbidden, conflict, and the HttpError class — for returning correct status codes from custom routes.
Where to go next
- App Marketplace — what an App is and how it's published.
- App model — the declarative JSON files an App is built from.
- Manifest reference — the manifest fields, including permissions.
- Schema reference — how to declare your tables.
- API Explorer — the platform API your App data is served through.