Skip to content

Commit 4f19913

Browse files
authored
chore: reduce logging and update README (#493)
1 parent 8285f11 commit 4f19913

File tree

3 files changed

+55
-25
lines changed

3 files changed

+55
-25
lines changed

README.md

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,17 @@
2121

2222
## What it is
2323

24-
ZenStack is a toolkit that simplifies the development of a web app's backend. It supercharges [Prisma ORM](https://prisma.io) with a powerful access control layer and unleashes its full potential for web development.
24+
ZenStack is a Node.js/TypeScript toolkit that simplifies the development of a web app's backend. It supercharges [Prisma ORM](https://prisma.io) with a powerful access control layer and unleashes its full potential for full-stack development.
2525

2626
Our goal is to let you save time writing boilerplate code and focus on building real features!
2727

2828
## How it works
2929

30-
ZenStack extended Prisma schema language for supporting custom attributes and functions and, based on that, implemented a flexible access control layer around Prisma.
30+
ZenStack incrementally extends Prisma's power with the following four layers:
31+
32+
### 1. ZModel - an extended Prisma schema language
33+
34+
ZenStack introduces a data modeling language called "ZModel" - a superset of Prisma schema language. It extended Prisma schema with custom attributes and functions and, based on that, implemented a flexible access control layer around Prisma.
3135

3236
```prisma
3337
// schema.zmodel
@@ -47,34 +51,58 @@ model Post {
4751
}
4852
```
4953

50-
At runtime, transparent proxies are created around Prisma clients for intercepting queries and mutations to enforce access policies. Moreover, framework integration packages help you wrap an access-control-enabled Prisma client into backend APIs that can be safely called from the frontend.
54+
The `zenstack` CLI transpiles the ZModel into a standard Prisma schema, which you can use with the regular Prisma workflows.
55+
56+
### 2. Runtime enhancements to Prisma client
57+
58+
At runtime, transparent proxies are created around Prisma clients for intercepting queries and mutations to enforce access policies.
5159

5260
```ts
53-
// Next.js example: pages/api/model/[...path].ts
61+
import { withPolicy } from '@zenstackhq/runtime';
62+
63+
// a regular Prisma client
64+
const prisma = new PrismaClient();
65+
66+
async function getPosts(userId: string) {
67+
// create an enhanced Prisma client that has access control enabled
68+
const enhanced = withPolicy(prisma, { user: userId });
69+
70+
// only posts that're visible to the user will be returned
71+
return enhanced.post.findMany();
72+
}
73+
```
74+
75+
### 3. Automatic RESTful APIs through server adapters
76+
77+
Server adapter packages help you wrap an access-control-enabled Prisma client into backend CRUD APIs that can be safely called from the frontend. Here's an example for Next.js:
78+
79+
```ts
80+
// pages/api/model/[...path].ts
5481

5582
import { requestHandler } from '@zenstackhq/next';
5683
import { withPolicy } from '@zenstackhq/runtime';
5784
import { getSessionUser } from '@lib/auth';
5885
import { prisma } from '@lib/db';
5986

87+
// Mount Prisma-style APIs: "/api/model/post/findMany", "/api/model/post/create", etc.
88+
// Can be configured to provide standard RESTful APIs (using JSON:API) instead.
6089
export default requestHandler({
6190
getPrisma: (req, res) => withPolicy(prisma, { user: getSessionUser(req, res) }),
6291
});
6392
```
6493

65-
Plugins can generate strong-typed client libraries that talk to the APIs:
94+
### 4. Generated client libraries (hooks) for data access
95+
96+
Plugins can generate strong-typed client libraries that talk to the aforementioned APIs. Here's an example for React:
6697

6798
```tsx
68-
// React example: components/MyPosts.tsx
99+
// components/MyPosts.tsx
69100

70-
import { usePost } from '@lib/hooks';
101+
import { useFindManyPost } from '@lib/hooks';
71102

72103
const MyPosts = () => {
73-
// Post CRUD hooks
74-
const { findMany } = usePost();
75-
76104
// list all posts that're visible to the current user, together with their authors
77-
const { data: posts } = findMany({
105+
const { data: posts } = useFindManyPost({
78106
include: { author: true },
79107
orderBy: { createdAt: 'desc' },
80108
});
@@ -91,7 +119,9 @@ const MyPosts = () => {
91119
};
92120
```
93121

94-
The following diagram gives a high-level overview of how it works.
122+
## Architecture
123+
124+
The following diagram gives a high-level architecture overview of ZenStack.
95125

96126
![Architecture](https://zenstack.dev/img/architecture-light.png)
97127

@@ -123,7 +153,7 @@ The following diagram gives a high-level overview of how it works.
123153

124154
### Framework adapters
125155

126-
- [Next.js](https://zenstack.dev/docs/reference/server-adapters/next)
156+
- [Next.js](https://zenstack.dev/docs/reference/server-adapters/next) (including support for the new "app directory" in Next.js 13)
127157
- [SvelteKit](https://zenstack.dev/docs/reference/server-adapters/sveltekit)
128158
- [Fastify](https://zenstack.dev/docs/reference/server-adapters/fastify)
129159
- [ExpressJS](https://zenstack.dev/docs/reference/server-adapters/express)

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"test": "pnpm -r run test --silent",
88
"lint": "pnpm -r lint",
99
"publish-all": "pnpm --filter \"./packages/**\" -r publish --access public",
10-
"publish-preview": "pnpm --filter \"./packages/**\" -r publish --registry https://packagecloud.io/ymc9/zenstack-preview/npm"
10+
"publish-preview": "pnpm --filter \"./packages/**\" -r publish --registry http://localhost:4873"
1111
},
1212
"keywords": [],
1313
"author": "",

packages/runtime/src/enhancements/policy/policy-utils.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -360,11 +360,11 @@ export class PolicyUtil {
360360
const ids = this.getEntityIds(fieldInfo.type, fieldData);
361361

362362
if (Object.keys(ids).length !== 0) {
363-
if (this.logger.enabled('info')) {
364-
this.logger.info(
365-
`Validating read of to-one relation: ${fieldInfo.type}#${formatObject(ids)}`
366-
);
367-
}
363+
// if (this.logger.enabled('info')) {
364+
// this.logger.info(
365+
// `Validating read of to-one relation: ${fieldInfo.type}#${formatObject(ids)}`
366+
// );
367+
// }
368368
await this.checkPolicyForFilter(fieldInfo.type, ids, operation, this.db);
369369
}
370370
}
@@ -749,9 +749,9 @@ export class PolicyUtil {
749749
return;
750750
}
751751

752-
if (this.logger.enabled('info')) {
753-
this.logger.info(`Checking policy for ${model}#${JSON.stringify(filter)} for ${operation}`);
754-
}
752+
// if (this.logger.enabled('info')) {
753+
// this.logger.info(`Checking policy for ${model}#${JSON.stringify(filter)} for ${operation}`);
754+
// }
755755

756756
const queryFilter = deepcopy(filter);
757757

@@ -835,9 +835,9 @@ export class PolicyUtil {
835835
db: Record<string, DbOperations>,
836836
preValue: any
837837
) {
838-
if (this.logger.enabled('info')) {
839-
this.logger.info(`Checking post-update policy for ${model}#${ids}, preValue: ${formatObject(preValue)}`);
840-
}
838+
// if (this.logger.enabled('info')) {
839+
// this.logger.info(`Checking post-update policy for ${model}#${ids}, preValue: ${formatObject(preValue)}`);
840+
// }
841841

842842
const guard = await this.getAuthGuard(model, 'postUpdate', preValue);
843843

0 commit comments

Comments
 (0)