diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..674d4087 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,109 @@ +# Contributing to ZenStack + +I want to thank you first for considering contributing to ZenStack πŸ™πŸ». It's people like you who make ZenStack a better toolkit that benefits more developers! + +Before you start working on anything major, please make sure to open an issue or discuss with us in our [Discord](https://discord.gg/Ykhr738dUe) first. This will help ensure your work aligns with the project's goals and avoid duplication of effort. + +## Prerequisites + +- Node.js: v20 or above +- PNPM: as specified in [package.json](./package.json) + +Test cases are run against both SQLite and Postgres. You should have a postgres server (16 or above) running (either natively or via Docker). The default connection is: + +`postgresql://${TEST_PG_USER}:${TEST_PG_PASSWORD}$@${TEST_PG_HOST}$:${TEST_PG_PORT}$` + +The default values for the environment variables (if not set) are: + +- `TEST_PG_HOST`: localhost +- `TEST_PG_PORT`: 5432 +- `TEST_PG_USER`: postgres +- `TEST_PG_PASSWORD`: postgres + +## Get started + +1. Install dependencies: `pnpm install` +2. Build all packages: `pnpm build` +3. Run all tests: `pnpm test` + +## Development workflow + +ZenStack adopts a very simple development workflow: + +1. Changes should be made in branches created off the "dev" branch. + +1. Non-trivial changes should include test cases. Bug-fixes should include regression tests that refer to GitHub issues if applicable. + +1. After coding and testing, create a PR to merge the changes into the "dev" branch. + +1. After code review is done, maintainer will squash and merge the PR into the "dev" branch. + +1. Periodically, the "dev" branch is merged back to the "main" branch to create a new release. + +## Project structure + +ZenStack is a monorepo consisting of multiple NPM packages managed by [pnpm workspace](https://pnpm.io/workspaces). + +### Packages + +The source and tests of ZenStack npm packages reside in the "packages" folder: + +#### [language](./packages/language) + +The ZModel language's definition, including its syntax definition and parser/linker implementation. The compiler is implemented with the [Langium](https://github.com/langium/langium) toolkit. + +#### [cli](./packages/cli) + +The `zen` CLI and built-in plugins. + +#### [schema](./packages/schema) + +The runtime representation of ZModel schema. + +#### [orm](./packages/orm) + +The ORM runtime built on top of [Kysely](https://kysely.dev). + +#### [server](./packages/server) + +The `server` package implements the automatic CRUD services and contains two main parts: + +1. Framework-agnostic API handlers: defining input/output format and API routes in a framework-independent way. Currently supports "rpc" and "rest" styles. + +1. Framework-specific adapters: translating framework-dependent request and response formats. + +#### [clients/tanstack-query](./packages/clients/tanstack-query) + +TanStack Query client for consuming the automatic CRUD services. + +#### [sdk](./packages/sdk) + +Utilities for building ZenStack plugins. + +#### [plugins/policy](./plugins/policy) + +The access policy plugin implementation. + +#### [ide/vscode](./packages/ide/vscode) + +VSCode extension for ZModel. + +#### [testtools](./packages/testtools) + +Test utilities. + +### Tests + +#### [e2e](./tests/e2e/) + +End-to-end tests covering essential features (ORM, access policies, etc.). + +#### [regression](./tests/regression/) + +Regression tests for previously reported issues. + +## Testing changed packages locally + +The [samples](./samples) folder contains sample projects that directly reference the packages in the workspace. Once you make changes to a package and rebuild it, the sample projects will automatically pick up the changes. They are handy for quick manual testing. + +If you prefer to test against your own project, simply copy the built bundles (from the `dist` folder of each package) to your project's `node_modules` folder to overwrite the installed packages. diff --git a/README.md b/README.md index 16f6309f..23290fd9 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ -

ZenStack V3

+

ZenStack: Modern Data Layer for TypeScript Apps

@@ -21,27 +21,23 @@ -> V3 is currently in beta phase and not ready for production use. Feedback and bug reports are greatly appreciated. Please visit this dedicated [discord channel](https://discord.com/channels/1035538056146595961/1352359627525718056) for chat and support. - # What's ZenStack -> Read full documentation at πŸ‘‰πŸ» https://zenstack.dev/v3. +> Read full documentation at πŸ‘‰πŸ» https://zenstack.dev/docs. -ZenStack is a TypeScript database toolkit for developing full-stack or backend Node.js/Bun applications. It provides a unified data modeling and access solution with the following features: +ZenStack is a TypeScript database toolkit for developing full-stack or backend Node.js/Bun applications. It provides a unified data modeling and query solution with the following features: -- A modern schema-first ORM that's compatible with [Prisma](https://github.com/prisma/prisma)'s schema and API -- Versatile data access APIs: high-level (Prisma-style) ORM queries + low-level ([Kysely](https://github.com/kysely-org/kysely)) query builder -- Built-in access control and data validation (coming soon) -- Advanced data modeling patterns like [polymorphism](https://zenstack.dev/blog/polymorphism) -- Designed for extensibility and flexibility: plugins, life-cycle hooks, etc. -- Automatic CRUD web APIs with adapters for popular frameworks (coming soon) -- Automatic [TanStack Query](https://github.com/TanStack/query) hooks for easy CRUD from the frontend (coming soon) +- πŸ”§ Modern schema-first ORM that's compatible with [Prisma](https://github.com/prisma/prisma)'s schema and API +- πŸ“Š Versatile API - high-level ORM queries + low-level [Kysely](https://kysely.dev) query builder +- πŸ” Built-in access control and data validation +- πŸš€ Advanced data modeling patterns like [polymorphism](https://zenstack.dev/docs/orm/polymorphism) +- 🧩 Designed for extensibility and flexibility +- βš™οΈ Automatic CRUD web APIs with adapters for popular frameworks +- πŸ–οΈ Automatic [TanStack Query](https://github.com/TanStack/query) hooks for easy CRUD from the frontend # What's New in V3 -ZenStack V3 is a major rewrite of [V2](https://github.com/zenstackhq/zenstack). The biggest change is V3 doesn't have a runtime dependency to Prisma anymore. Instead of working as a big wrapper of Prisma as in V2, V3 made a bold move and implemented the entire ORM engine using [Kysely](https://github.com/kysely-org/kysely), while keeping the query API fully compatible with Prisma. - -Please check [this blog post](https://zenstack.dev/blog/next-chapter-1) for why we made this big architectural change decision. +ZenStack V3 is a major rewrite of [V2](https://github.com/zenstackhq/zenstack/docs/2.x). It replaced Prisma ORM with its own ORM engine built on top of [Kysely](https://kysely.dev) while keeping a Prisma-compatible query API. This architecture change brings the level of flexibility that we couldn't imagine in previous versions. Please check [this blog post](https://zenstack.dev/blog/next-chapter-1) for why we made this bold decision. Even without using advanced features, ZenStack offers the following benefits as a drop-in replacement to Prisma: @@ -49,12 +45,9 @@ Even without using advanced features, ZenStack offers the following benefits as 2. More TypeScript type inference, less code generation. 3. Fully-typed query-builder API as a better escape hatch compared to Prisma's [raw queries](https://www.prisma.io/docs/orm/prisma-client/using-raw-sql/raw-queries) or [typed SQL](https://www.prisma.io/docs/orm/prisma-client/using-raw-sql/typedsql). -> Although ZenStack v3's ORM runtime doesn't depend on Prisma anymore (specifically, `@prisma/client`), it still relies on Prisma to handle database migration. See [database migration](https://zenstack.dev/docs/3.x/orm/migration) for more details. - -# Quick Start +# Try It Now -- [ORM](./samples/orm): A simple example demonstrating ZenStack ORM usage. -- [Next.js + TanStack Query](./samples/next.js): A full-stack sample demonstrating using TanStack Query to consume ZenStack's automatic CRUD services in a Next.js app. +[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/~/github.com/zenstackhq/v3-doc-quick-start?file=zenstack%2fschema.zmodel&file=main.ts&view=editor&showSidebar=0&hideNavigation=1&hideExplorer=1) ## Installation @@ -63,7 +56,7 @@ Even without using advanced features, ZenStack offers the following benefits as Use the following command to scaffold a simple TypeScript command line application with ZenStack configured: ```bash -npm create zenstack@next my-project +npm create zenstack@latest my-project ``` ### 2. Setting up an existing project @@ -71,7 +64,7 @@ npm create zenstack@next my-project Or, if you have an existing project, use the CLI to initialize it: ```bash -npx @zenstackhq/cli@next init +npx @zenstackhq/cli@latest init ``` ### 3. Setting up manually @@ -79,12 +72,42 @@ npx @zenstackhq/cli@next init Alternatively, you can set it up manually: ```bash -npm install -D @zenstackhq/cli@next -npm install @zenstackhq/orm@next +npm install -D @zenstackhq/cli +npm install @zenstackhq/orm ``` Then create a `zenstack` folder and a `schema.zmodel` file in it. # Documentation -Please visit the [doc site](https://zenstack.dev/docs/3.x/) for detailed documentation. +[https://zenstack.dev/docs/](https://zenstack.dev/docs/) + +# Sponsors + +Thank you for your generous support! + +## Current Sponsors + + + + + + + + + +
Suhyl
Suhyl
Marblism
Marblism
Mermaid Chart
Mermaid Chart
CodeRabbit
CodeRabbit
Johann Rohn
Johann Rohn
+ +## Previous Sponsors + + + + + + + +
Benjamin Zecirovic
Benjamin Zecirovic
Ulric
Ulric
Fabian Jocks
Fabian Jocks
+ +# Community + +Join our [discord server](https://discord.gg/Ykhr738dUe) for chat and updates! diff --git a/package.json b/package.json index 3732c8a9..0803435e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "zenstack-v3", - "version": "3.0.0-beta.34", + "version": "3.0.0", "description": "ZenStack", "packageManager": "pnpm@10.23.0", "type": "module", @@ -9,12 +9,15 @@ "watch": "turbo run watch build", "lint": "turbo run lint", "test": "turbo run test", + "test:all": "pnpm run test:sqlite && pnpm run test:pg", + "test:pg": "TEST_DB_PROVIDER=postgresql turbo run test", + "test:sqlite": "TEST_DB_PROVIDER=sqlite turbo run test", "format": "prettier --write \"**/*.{ts,tsx,md}\"", "pr": "gh pr create --fill-first --base dev", "merge-main": "gh pr create --title \"merge dev to main\" --body \"\" --base main --head dev", "bump-version": "gh workflow run .github/workflows/bump-version.yml --ref dev", - "publish-all": "pnpm --filter \"./packages/**\" -r publish --access public --tag next", - "publish-preview": "pnpm --filter \"./packages/**\" -r publish --tag next --force --registry https://preview.registry.zenstack.dev/", + "publish-all": "pnpm --filter \"./packages/**\" -r publish --access public", + "publish-preview": "pnpm --filter \"./packages/**\" -r publish --force --registry https://preview.registry.zenstack.dev/", "unpublish-preview": "pnpm --filter \"./packages/**\" -r --shell-mode exec -- npm unpublish -f --registry https://preview.registry.zenstack.dev/ \"\\$PNPM_PACKAGE_NAME\"" }, "keywords": [], diff --git a/packages/auth-adapters/better-auth/package.json b/packages/auth-adapters/better-auth/package.json index cd21a5e6..90beab8f 100644 --- a/packages/auth-adapters/better-auth/package.json +++ b/packages/auth-adapters/better-auth/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/better-auth", - "version": "3.0.0-beta.34", + "version": "3.0.0", "description": "ZenStack Better Auth Adapter. This adapter is modified from better-auth's Prisma adapter.", "type": "module", "scripts": { diff --git a/packages/cli/package.json b/packages/cli/package.json index 87a680c3..506a6376 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -3,7 +3,7 @@ "publisher": "zenstack", "displayName": "ZenStack CLI", "description": "FullStack database toolkit with built-in access control and automatic API generation.", - "version": "3.0.0-beta.34", + "version": "3.0.0", "type": "module", "author": { "name": "ZenStack Team" diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index b48fc321..c2307fa1 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -50,7 +50,7 @@ function createProgram() { .description( `${colors.bold.blue( 'ΞΆ', - )} ZenStack is the data layer for modern TypeScript apps.\n\nDocumentation: https://zenstack.dev/docs/3.x`, + )} ZenStack is the modern data layer for TypeScript apps.\n\nDocumentation: https://zenstack.dev/docs`, ) .showHelpAfterError() .showSuggestionAfterError(); diff --git a/packages/clients/tanstack-query/package.json b/packages/clients/tanstack-query/package.json index b3d799e3..15451c0c 100644 --- a/packages/clients/tanstack-query/package.json +++ b/packages/clients/tanstack-query/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/tanstack-query", - "version": "3.0.0-beta.34", + "version": "3.0.0", "description": "TanStack Query Client for consuming ZenStack v3's CRUD service", "main": "index.js", "type": "module", diff --git a/packages/common-helpers/package.json b/packages/common-helpers/package.json index 85c8ba5f..8d60e7df 100644 --- a/packages/common-helpers/package.json +++ b/packages/common-helpers/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/common-helpers", - "version": "3.0.0-beta.34", + "version": "3.0.0", "description": "ZenStack Common Helpers", "type": "module", "scripts": { diff --git a/packages/config/eslint-config/package.json b/packages/config/eslint-config/package.json index 12323bf4..c06180d7 100644 --- a/packages/config/eslint-config/package.json +++ b/packages/config/eslint-config/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/eslint-config", - "version": "3.0.0-beta.34", + "version": "3.0.0", "type": "module", "private": true, "license": "MIT" diff --git a/packages/config/typescript-config/package.json b/packages/config/typescript-config/package.json index b18e688d..a6e97e28 100644 --- a/packages/config/typescript-config/package.json +++ b/packages/config/typescript-config/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/typescript-config", - "version": "3.0.0-beta.34", + "version": "3.0.0", "private": true, "license": "MIT" } diff --git a/packages/config/vitest-config/package.json b/packages/config/vitest-config/package.json index 341eb16f..26441c95 100644 --- a/packages/config/vitest-config/package.json +++ b/packages/config/vitest-config/package.json @@ -1,7 +1,7 @@ { "name": "@zenstackhq/vitest-config", "type": "module", - "version": "3.0.0-beta.34", + "version": "3.0.0", "private": true, "license": "MIT", "exports": { diff --git a/packages/create-zenstack/package.json b/packages/create-zenstack/package.json index 77c0f809..e532900e 100644 --- a/packages/create-zenstack/package.json +++ b/packages/create-zenstack/package.json @@ -1,6 +1,6 @@ { "name": "create-zenstack", - "version": "3.0.0-beta.34", + "version": "3.0.0", "description": "Create a new ZenStack project", "type": "module", "scripts": { diff --git a/packages/language/package.json b/packages/language/package.json index cd7c4d81..c4b598dd 100644 --- a/packages/language/package.json +++ b/packages/language/package.json @@ -1,7 +1,7 @@ { "name": "@zenstackhq/language", "description": "ZenStack ZModel language specification", - "version": "3.0.0-beta.34", + "version": "3.0.0", "license": "MIT", "author": "ZenStack Team", "files": [ diff --git a/packages/orm/package.json b/packages/orm/package.json index 208fc70b..d48d0beb 100644 --- a/packages/orm/package.json +++ b/packages/orm/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/orm", - "version": "3.0.0-beta.34", + "version": "3.0.0", "description": "ZenStack ORM", "type": "module", "scripts": { diff --git a/packages/plugins/policy/package.json b/packages/plugins/policy/package.json index 757a3c1b..dc95282b 100644 --- a/packages/plugins/policy/package.json +++ b/packages/plugins/policy/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/plugin-policy", - "version": "3.0.0-beta.34", + "version": "3.0.0", "description": "ZenStack Policy Plugin", "type": "module", "scripts": { diff --git a/packages/schema/package.json b/packages/schema/package.json index 4bfe6911..70dcf353 100644 --- a/packages/schema/package.json +++ b/packages/schema/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/schema", - "version": "3.0.0-beta.34", + "version": "3.0.0", "description": "ZenStack Runtime Schema", "type": "module", "scripts": { diff --git a/packages/sdk/package.json b/packages/sdk/package.json index c0986e7e..afe9f7e3 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/sdk", - "version": "3.0.0-beta.34", + "version": "3.0.0", "description": "ZenStack SDK", "type": "module", "scripts": { diff --git a/packages/server/package.json b/packages/server/package.json index 00539080..4abe793a 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/server", - "version": "3.0.0-beta.34", + "version": "3.0.0", "description": "ZenStack automatic CRUD API handlers and server adapters", "type": "module", "scripts": { diff --git a/packages/testtools/package.json b/packages/testtools/package.json index a60475ae..a79a527c 100644 --- a/packages/testtools/package.json +++ b/packages/testtools/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/testtools", - "version": "3.0.0-beta.34", + "version": "3.0.0", "description": "ZenStack Test Tools", "type": "module", "scripts": { diff --git a/packages/zod/package.json b/packages/zod/package.json index 48e78f0b..47c1a71e 100644 --- a/packages/zod/package.json +++ b/packages/zod/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/zod", - "version": "3.0.0-beta.34", + "version": "3.0.0", "description": "", "type": "module", "main": "index.js", diff --git a/samples/next.js/package.json b/samples/next.js/package.json index 3746c18c..08d2945e 100644 --- a/samples/next.js/package.json +++ b/samples/next.js/package.json @@ -1,6 +1,6 @@ { "name": "next.js", - "version": "3.0.0-beta.34", + "version": "3.0.0", "private": true, "scripts": { "generate": "zen generate --lite", diff --git a/samples/orm/package.json b/samples/orm/package.json index b5f52e50..e5d02a16 100644 --- a/samples/orm/package.json +++ b/samples/orm/package.json @@ -1,6 +1,6 @@ { "name": "sample-blog", - "version": "3.0.0-beta.34", + "version": "3.0.0", "description": "", "main": "index.js", "private": true, diff --git a/tests/e2e/package.json b/tests/e2e/package.json index 6cc90470..201a9211 100644 --- a/tests/e2e/package.json +++ b/tests/e2e/package.json @@ -1,6 +1,6 @@ { "name": "e2e", - "version": "3.0.0-beta.34", + "version": "3.0.0", "private": true, "type": "module", "scripts": { diff --git a/tests/regression/package.json b/tests/regression/package.json index 38b5372b..c3568f37 100644 --- a/tests/regression/package.json +++ b/tests/regression/package.json @@ -1,6 +1,6 @@ { "name": "regression", - "version": "3.0.0-beta.34", + "version": "3.0.0", "private": true, "type": "module", "scripts": { diff --git a/tests/runtimes/bun/package.json b/tests/runtimes/bun/package.json index 606e6577..cf799384 100644 --- a/tests/runtimes/bun/package.json +++ b/tests/runtimes/bun/package.json @@ -1,6 +1,6 @@ { "name": "bun-e2e", - "version": "3.0.0-beta.34", + "version": "3.0.0", "private": true, "type": "module", "scripts": { diff --git a/tests/runtimes/edge-runtime/package.json b/tests/runtimes/edge-runtime/package.json index d576c9be..85669a53 100644 --- a/tests/runtimes/edge-runtime/package.json +++ b/tests/runtimes/edge-runtime/package.json @@ -1,6 +1,6 @@ { "name": "edge-runtime-e2e", - "version": "3.0.0-beta.34", + "version": "3.0.0", "private": true, "type": "module", "scripts": {