Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/reference/server-adapters/api-handlers/rest.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ The factory function accepts an options object with the following fields:

- externalIdMapping

Optional. An `Record<string, string>` value that provides a mapping from model names (as defined in ZModel) to unique contraint name. This is useful when you for example want to expose natural keys in place of a surrogate keys:
Optional. An `Record<string, string>` value that provides a mapping from model names (as defined in ZModel) to unique constraint name. This is useful when you for example want to expose natural keys in place of a surrogate keys:

```ts
// Expose tags by unique name and not by ID, ie. /tag/blue intead of /tag/id
Expand All @@ -112,7 +112,7 @@ The factory function accepts an options object with the following fields:
})
```

Currentlly it is not possible to use custom index names. This also works for compound unique contraints just like for [compound IDs](#compound-id-fields).
Currently it is not possible to use custom index names. This also works for compound unique constraints just like for [compound IDs](#compound-id-fields).


## Endpoints and Features
Expand Down
5 changes: 5 additions & 0 deletions versioned_docs/version-3.x/reference/package.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
sidebar_position: 5
---

# Packages
2 changes: 1 addition & 1 deletion versioned_docs/version-3.x/reference/plugin-dev.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 5
sidebar_position: 6
description: Plugin development guide
---

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
position: 4
position: 5
label: Plugins
collapsible: true
collapsed: true
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
position: 7
label: Server Adapters
collapsible: true
collapsed: true
link:
type: generated-index
title: Server Adapters
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### Error Handling

Refer to the specific sections for [RPC Handler](../../service/api-handler/rpc#http-status-code-and-error-responses) and [RESTful Handler](../../service/api-handler/rest#error-handling).
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p>The <code>{props.module}</code> module provides a quick way to install a full set of CRUD API onto <a href={props.url} target="_blank">{props.framework}</a> apps. Combined with ZenStack's powerful access policies, you can achieve a secure data backend without manually coding it.</p>
11 changes: 11 additions & 0 deletions versioned_docs/version-3.x/reference/server-adapters/_options.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
- getClient (required)

<blockquote>{props.getClient}</blockquote>

A callback for getting a ZenStackClient instance for talking to the database. Usually you'll return a client instance with access policy enabled and user identity bound.

- apiHandler (required)

<blockquote>{'ApiHandler'}</blockquote>

The [API handler](../../service/api-handler/) instance that determines the API specification.
67 changes: 67 additions & 0 deletions versioned_docs/version-3.x/reference/server-adapters/elysia.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
---
title: Elysia
description: Adapter for integrating with Elysia
sidebar_position: 8
---

import PackageInstall from '../../_components/PackageInstall';
import ErrorHandling from './_error-handling.md';
import Intro from './_intro.mdx';
import AdapterOptions from './_options.mdx';

# Elysia Adapter

<Intro module='@zenstackhq/server/elysia' framework='Elysia' url="https://elysiajs.com" />

This feature is contributed by [@rodrigoburigool](https://github.com/rodrigoburigool).

### Installation

<PackageInstall dependencies={['@zenstackhq/server@next']} />

### Mounting the API

You can use the `createElysiaHandler` API to create an Elysia request handler that handles CRUD requests automatically:

```ts
import { Elysia, Context } from 'elysia';
import { RPCApiHandler } from '@zenstackhq/server/api';
import { createElysiaHandler } from '@zenstackhq/server/elysia';
import { getSessionUser } from '~/auth';
import { client } from '~/db';
import { schema } from '~/zenstack/schema';

const app = new Elysia({ prefix: '/api' });

// install the CRUD middleware under route "/api/crud"
app.group('/crud', (app) =>
app.use(
createElysiaHandler({
apiHandler: new RPCApiHandler({ schema }),
basePath: '/api/model',
// getSessionUser extracts the current session user from the request,
// its implementation depends on your auth solution
getClient: (context) => client.$setAuth(getSessionUser(context)) }),
})
)
);

function getCurrentUser(context: Context) {
// the implementation depends on your authentication mechanism
...
}

app.listen(3000);
```

The middleware factory takes the following options to initialize:

<AdapterOptions getClient='(ctx: Context) => ClientContract<Schema> | Promise<ClientContract<Schema>>' />

- basePath (optional)

<blockquote>string</blockquote>

Optional base path to strip from the request path before passing to the API handler. E.g., if your CRUD handler is mounted at `/api/crud`, set this field to `'/api/crud'`.

<ErrorHandling />
59 changes: 59 additions & 0 deletions versioned_docs/version-3.x/reference/server-adapters/express.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
title: Express.js
description: Adapter for integrating with Express.js
sidebar_position: 5
---

import PackageInstall from '../../_components/PackageInstall';
import ErrorHandling from './_error-handling.md';
import Intro from './_intro.mdx';
import AdapterOptions from './_options.mdx';

# Express.js Adapter

<Intro module='@zenstackhq/server/express' framework='Express.js' url="https://expressjs.com/" />

### Installation

<PackageInstall dependencies={['@zenstackhq/server@next']} />

### Mounting the API

You can integrate ZenStack into your project with the `ZenStackMiddleware` [express middleware](https://expressjs.com/en/guide/using-middleware.html):

```ts
import express from 'express';
import { ZenStackMiddleware } from '@zenstackhq/server/express';
import { RPCApiHandler } from '@zenstackhq/server/api';
import { getSessionUser } from '~/auth';
import { client } from '~/db';
import { schema } from '~/zenstack/schema';

const app = express();

app.use(express.json());

app.use(
'/api/model',
ZenStackMiddleware({
apiHandler: new RPCApiHandler({ schema }),
// getSessionUser extracts the current session user from the request, its
// implementation depends on your auth solution
getClient: (request) => client.$setAuth(getSessionUser(request)),
})
);
```

The Express.js adapter takes the following options to initialize:

<AdapterOptions getClient='(request: Request, response: Response) => ClientContract<Schema> | Promise<ClientContract<Schema>>' />

- sendResponse (optional)

<blockquote>boolean</blockquote>

Controls if the middleware directly sends a response. If set to false, the response is stored in the `res.locals` object and then the middleware calls the `next()` function to pass the control to the next middleware. Subsequent middleware or request handlers need to make sure to send a response.

Defaults to `true`.

<ErrorHandling />
53 changes: 53 additions & 0 deletions versioned_docs/version-3.x/reference/server-adapters/fastify.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
title: Fastify
description: Adapter for integrating with Fastify
sidebar_position: 6
---

import PackageInstall from '../../_components/PackageInstall';
import ErrorHandling from './_error-handling.md';
import Intro from './_intro.mdx';
import AdapterOptions from './_options.mdx';

# Fastify Adapter

<Intro module='@zenstackhq/server/fastify' framework='Fastify' url="https://www.fastify.io/" />

### Installation

<PackageInstall dependencies={['@zenstackhq/server@next']} />

### Mounting the API

You can integrate ZenStack into your project with the `ZenStackFastifyPlugin` [fastify plugin](https://www.fastify.io/docs/latest/Reference/Plugins/):

```ts
import fastify from 'fastify'
import { ZenStackFastifyPlugin } from '@zenstackhq/server/fastify';
import { RPCApiHandler } from '@zenstackhq/server/api';
import { getSessionUser } from '~/auth';
import { client } from '~/db';
import { schema } from '~/zenstack/schema';

const server = fastify();

server.register(ZenStackFastifyPlugin, {
apiHandler: new RPCApiHandler({ schema }),
prefix: '/api/model',
// getSessionUser extracts the current session user from the request, its
// implementation depends on your auth solution
getClient: (request) => client.$setAuth(getSessionUser(request)),
});
```

The Fastify adapter takes the following options to initialize:

- prefix

<blockquote>string</blockquote>

Prefix for the mounted API endpoints. E.g.: /api/model.

<AdapterOptions getClient='(request: FastifyRequest, reply: FastifyReply) => ClientContract<Schema> | Promise<ClientContract<Schema>>' />

<ErrorHandling />
49 changes: 49 additions & 0 deletions versioned_docs/version-3.x/reference/server-adapters/hono.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
title: Hono
description: Adapter for integrating with Hono
sidebar_position: 7
---

import PackageInstall from '../../_components/PackageInstall';
import ErrorHandling from './_error-handling.md';
import Intro from './_intro.mdx';
import AdapterOptions from './_options.mdx';

# Hono Adapter

<Intro module='@zenstackhq/server/hono' framework='Hono' url="https://hono.dev/" />

### Installation

<PackageInstall dependencies={['@zenstackhq/server@next']} />

### Mounting the API

You can use the `createHonoHandler` API to create a [Hono middleware](https://hono.dev/docs/getting-started/basic#using-middleware) that handles CRUD requests automatically:

```ts
import { Context, Hono } from 'hono';
import { createHonoHandler } from '@zenstackhq/server/hono';
import { RPCApiHandler } from '@zenstackhq/server/api';
import { getSessionUser } from '~/auth';
import { client } from '~/db';
import { schema } from '~/zenstack/schema';

const app = new Hono();

app.use(
'/api/model/*',
createHonoHandler({
apiHandler: new RPCApiHandler({ schema }),
// getSessionUser extracts the current session user from the request,
// its implementation depends on your auth solution
getClient: (ctx) => client.$setAuth(getSessionUser(ctx)),
})
);
```

The middleware factory takes the following options to initialize:

<AdapterOptions getClient='(ctx: Context) => ClientContract<Schema> | Promise<ClientContract<Schema>>' />

<ErrorHandling />
Loading