Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "zenstack-v3",
"version": "3.0.0-beta.5",
"version": "3.0.0-beta.6",
"description": "ZenStack",
"packageManager": "[email protected]",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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.5",
"version": "3.0.0-beta.6",
"type": "module",
"author": {
"name": "ZenStack Team"
Expand Down
2 changes: 1 addition & 1 deletion packages/common-helpers/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/common-helpers",
"version": "3.0.0-beta.5",
"version": "3.0.0-beta.6",
"description": "ZenStack Common Helpers",
"type": "module",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion packages/create-zenstack/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "create-zenstack",
"version": "3.0.0-beta.5",
"version": "3.0.0-beta.6",
"description": "Create a new ZenStack project",
"type": "module",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion packages/dialects/sql.js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/kysely-sql-js",
"version": "3.0.0-beta.5",
"version": "3.0.0-beta.6",
"description": "Kysely dialect for sql.js",
"type": "module",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-config/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/eslint-config",
"version": "3.0.0-beta.5",
"version": "3.0.0-beta.6",
"type": "module",
"private": true,
"license": "MIT"
Expand Down
2 changes: 1 addition & 1 deletion packages/language/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@zenstackhq/language",
"description": "ZenStack ZModel language specification",
"version": "3.0.0-beta.5",
"version": "3.0.0-beta.6",
"license": "MIT",
"author": "ZenStack Team",
"files": [
Expand Down
59 changes: 53 additions & 6 deletions packages/language/res/stdlib.zmodel
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,6 @@ function autoincrement(): Int {
function dbgenerated(expr: String?): Any {
} @@@expressionContext([DefaultValue])

/**
* Gets entities value before an update. Only valid when used in a "update" policy rule.
*/
function future(): Any {
} @@@expressionContext([AccessPolicy])

/**
* Checks if the field value contains the search string. By default, the search is case-sensitive, and
* "LIKE" operator is used to match. If `caseInSensitive` is true, "ILIKE" operator is used if
Expand Down Expand Up @@ -663,3 +657,56 @@ attribute @meta(_ name: String, _ value: Any)
* Marks an attribute as deprecated.
*/
attribute @@@deprecated(_ message: String)

/* --- Policy Plugin --- */

/**
* Defines an access policy that allows a set of operations when the given condition is true.
*
* @param operation: comma-separated list of "create", "read", "update", "delete". Use "all" to denote all operations.
* @param condition: a boolean expression that controls if the operation should be allowed.
*/
attribute @@allow(_ operation: String @@@completionHint(["'create'", "'read'", "'update'", "'delete'", "'all'"]), _ condition: Boolean)

/**
* Defines an access policy that allows the annotated field to be read or updated.
* You can pass a third argument as `true` to make it override the model-level policies.
*
* @param operation: comma-separated list of "create", "read", "update", "delete". Use "all" to denote all operations.
* @param condition: a boolean expression that controls if the operation should be allowed.
* @param override: a boolean value that controls if the field-level policy should override the model-level policy.
*/
attribute @allow(_ operation: String @@@completionHint(["'create'", "'read'", "'update'", "'delete'", "'all'"]), _ condition: Boolean, _ override: Boolean?)

/**
* Defines an access policy that denies a set of operations when the given condition is true.
*
* @param operation: comma-separated list of "create", "read", "update", "delete". Use "all" to denote all operations.
* @param condition: a boolean expression that controls if the operation should be denied.
*/
attribute @@deny(_ operation: String @@@completionHint(["'create'", "'read'", "'update'", "'delete'", "'all'"]), _ condition: Boolean)

/**
* Defines an access policy that denies the annotated field to be read or updated.
*
* @param operation: comma-separated list of "create", "read", "update", "delete". Use "all" to denote all operations.
* @param condition: a boolean expression that controls if the operation should be denied.
*/
attribute @deny(_ operation: String @@@completionHint(["'create'", "'read'", "'update'", "'delete'", "'all'"]), _ condition: Boolean)

/**
* Checks if the current user can perform the given operation on the given field.
*
* @param field: The field to check access for
* @param operation: The operation to check access for. Can be "read", "create", "update", or "delete". If the operation is not provided,
* it defaults the operation of the containing policy rule.
*/
function check(field: Any, operation: String?): Boolean {
} @@@expressionContext([AccessPolicy])

/**
* Gets entities value before an update. Only valid when used in a "update" policy rule.
*/
function future(): Any {
} @@@expressionContext([AccessPolicy])

8 changes: 2 additions & 6 deletions packages/language/test/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { invariant } from '@zenstackhq/common-helpers';
import { glob } from 'glob';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
Expand All @@ -10,7 +9,7 @@ export async function loadSchema(schema: string) {
// create a temp file
const tempFile = path.join(os.tmpdir(), `zenstack-schema-${crypto.randomUUID()}.zmodel`);
fs.writeFileSync(tempFile, schema);
const r = await loadDocument(tempFile, getPluginModels());
const r = await loadDocument(tempFile);
expect(r).toSatisfy(
(r) => r.success,
`Failed to load schema: ${(r as any).errors?.map((e) => e.toString()).join(', ')}`,
Expand All @@ -23,7 +22,7 @@ export async function loadSchemaWithError(schema: string, error: string | RegExp
// create a temp file
const tempFile = path.join(os.tmpdir(), `zenstack-schema-${crypto.randomUUID()}.zmodel`);
fs.writeFileSync(tempFile, schema);
const r = await loadDocument(tempFile, getPluginModels());
const r = await loadDocument(tempFile);
expect(r.success).toBe(false);
invariant(!r.success);
if (typeof error === 'string') {
Expand All @@ -38,6 +37,3 @@ export async function loadSchemaWithError(schema: string, error: string | RegExp
);
}
}
function getPluginModels() {
return glob.sync(path.resolve(__dirname, '../../runtime/src/plugins/**/plugin.zmodel'));
}
2 changes: 1 addition & 1 deletion packages/runtime/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/runtime",
"version": "3.0.0-beta.5",
"version": "3.0.0-beta.6",
"description": "ZenStack Runtime",
"type": "module",
"scripts": {
Expand Down
43 changes: 0 additions & 43 deletions packages/runtime/src/plugins/policy/plugin.zmodel

This file was deleted.

3 changes: 1 addition & 2 deletions packages/runtime/test/scripts/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ async function generate(schemaPath: string) {
const generator = new TsSchemaGenerator();
const outputDir = path.dirname(schemaPath);
const tsPath = path.join(outputDir, 'schema.ts');
const pluginModelFiles = glob.sync(path.resolve(dir, '../../dist/**/plugin.zmodel'));
const result = await loadDocument(schemaPath, pluginModelFiles);
const result = await loadDocument(schemaPath);
if (!result.success) {
throw new Error(`Failed to load schema from ${schemaPath}: ${result.errors}`);
}
Expand Down
4 changes: 2 additions & 2 deletions packages/runtime/test/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { invariant } from '@zenstackhq/common-helpers';
import { loadDocument } from '@zenstackhq/language';
import type { Model } from '@zenstackhq/language/ast';
import { PrismaSchemaGenerator } from '@zenstackhq/sdk';
import { createTestProject, generateTsSchema, getPluginModules } from '@zenstackhq/testtools';
import { createTestProject, generateTsSchema } from '@zenstackhq/testtools';
import SQLite from 'better-sqlite3';
import { PostgresDialect, SqliteDialect, type LogEvent } from 'kysely';
import { execSync } from 'node:child_process';
Expand Down Expand Up @@ -113,7 +113,7 @@ export async function createTestClient<Schema extends SchemaDef>(
if (options?.usePrismaPush) {
invariant(typeof schema === 'string' || schemaFile, 'a schema file must be provided when using prisma db push');
if (!model) {
const r = await loadDocument(path.join(workDir, 'schema.zmodel'), getPluginModules());
const r = await loadDocument(path.join(workDir, 'schema.zmodel'));
if (!r.success) {
throw new Error(r.errors.join('\n'));
}
Expand Down
4 changes: 0 additions & 4 deletions packages/runtime/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { defineConfig } from 'tsup';
import fs from 'node:fs';

export default defineConfig({
entry: {
Expand All @@ -14,7 +13,4 @@ export default defineConfig({
clean: true,
dts: true,
format: ['cjs', 'esm'],
async onSuccess() {
fs.cpSync('src/plugins/policy/plugin.zmodel', 'dist/plugins/policy/plugin.zmodel');
},
});
2 changes: 1 addition & 1 deletion packages/sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/sdk",
"version": "3.0.0-beta.5",
"version": "3.0.0-beta.6",
"description": "ZenStack SDK",
"type": "module",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion packages/tanstack-query/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/tanstack-query",
"version": "3.0.0-beta.5",
"version": "3.0.0-beta.6",
"description": "",
"main": "index.js",
"type": "module",
Expand Down
2 changes: 1 addition & 1 deletion packages/testtools/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/testtools",
"version": "3.0.0-beta.5",
"version": "3.0.0-beta.6",
"description": "ZenStack Test Tools",
"type": "module",
"scripts": {
Expand Down
11 changes: 2 additions & 9 deletions packages/testtools/src/schema.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { loadDocument } from '@zenstackhq/language';
import { TsSchemaGenerator } from '@zenstackhq/sdk';
import type { SchemaDef } from '@zenstackhq/sdk/schema';
import { glob } from 'glob';
import { execSync } from 'node:child_process';
import fs from 'node:fs';
import path from 'node:path';
Expand Down Expand Up @@ -41,8 +40,7 @@ export async function generateTsSchema(
const noPrelude = schemaText.includes('datasource ');
fs.writeFileSync(zmodelPath, `${noPrelude ? '' : makePrelude(provider, dbUrl)}\n\n${schemaText}`);

const pluginModelFiles = getPluginModules();
const result = await loadDocument(zmodelPath, pluginModelFiles);
const result = await loadDocument(zmodelPath);
if (!result.success) {
throw new Error(`Failed to load schema from ${zmodelPath}: ${result.errors}`);
}
Expand All @@ -62,10 +60,6 @@ export async function generateTsSchema(
return { ...(await compileAndLoad(workDir)), model: result.model };
}

export function getPluginModules() {
return glob.sync(path.resolve(__dirname, '../../runtime/src/plugins/**/plugin.zmodel'));
}

async function compileAndLoad(workDir: string) {
execSync('npx tsc', {
cwd: workDir,
Expand All @@ -84,8 +78,7 @@ export function generateTsSchemaFromFile(filePath: string) {

export async function generateTsSchemaInPlace(schemaPath: string) {
const workDir = path.dirname(schemaPath);
const pluginModelFiles = glob.sync(path.resolve(__dirname, '../../runtime/src/plugins/**/plugin.zmodel'));
const result = await loadDocument(schemaPath, pluginModelFiles);
const result = await loadDocument(schemaPath);
if (!result.success) {
throw new Error(`Failed to load schema from ${schemaPath}: ${result.errors}`);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/typescript-config/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/typescript-config",
"version": "3.0.0-beta.5",
"version": "3.0.0-beta.6",
"private": true,
"license": "MIT"
}
2 changes: 1 addition & 1 deletion packages/vitest-config/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@zenstackhq/vitest-config",
"type": "module",
"version": "3.0.0-beta.5",
"version": "3.0.0-beta.6",
"private": true,
"license": "MIT",
"exports": {
Expand Down
2 changes: 1 addition & 1 deletion packages/zod/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/zod",
"version": "3.0.0-beta.5",
"version": "3.0.0-beta.6",
"description": "",
"type": "module",
"main": "index.js",
Expand Down
2 changes: 1 addition & 1 deletion samples/blog/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "sample-blog",
"version": "3.0.0-beta.5",
"version": "3.0.0-beta.6",
"description": "",
"main": "index.js",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "e2e",
"version": "3.0.0-beta.5",
"version": "3.0.0-beta.6",
"private": true,
"type": "module",
"scripts": {
Expand Down
4 changes: 1 addition & 3 deletions tests/regression/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@ async function main() {
async function generate(schemaPath: string) {
const generator = new TsSchemaGenerator();
const outputDir = path.dirname(schemaPath);
const tsPath = path.join(outputDir, 'schema.ts');
const pluginModelFiles = glob.sync(path.resolve(dir, '../../packages/runtime/dist/**/plugin.zmodel'));
const result = await loadDocument(schemaPath, pluginModelFiles);
const result = await loadDocument(schemaPath);
if (!result.success) {
throw new Error(`Failed to load schema from ${schemaPath}: ${result.errors}`);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/regression/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "regression",
"version": "3.0.0-beta.5",
"version": "3.0.0-beta.6",
"private": true,
"type": "module",
"scripts": {
Expand Down