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
Expand Up @@ -2,7 +2,7 @@
"name": "zenstack-v3",
"displayName": "ZenStack",
"description": "ZenStack",
"version": "3.9.5",
"version": "3.9.6",
"type": "module",
"author": {
"name": "ZenStack Team",
Expand Down
2 changes: 1 addition & 1 deletion packages/auth-adapters/better-auth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@zenstackhq/better-auth",
"displayName": "ZenStack Better Auth Adapter",
"description": "ZenStack Better Auth Adapter. This adapter is modified from better-auth's Prisma adapter.",
"version": "3.9.5",
"version": "3.9.6",
"type": "module",
"author": {
"name": "ZenStack Team",
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@zenstackhq/cli",
"displayName": "ZenStack CLI",
"description": "FullStack database toolkit with built-in access control and automatic API generation.",
"version": "3.9.5",
"version": "3.9.6",
"type": "module",
"author": {
"name": "ZenStack Team",
Expand Down
2 changes: 1 addition & 1 deletion packages/clients/client-helpers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@zenstackhq/client-helpers",
"displayName": "ZenStack Client Helpers",
"description": "Helpers for implementing clients that consume ZenStack's CRUD service",
"version": "3.9.5",
"version": "3.9.6",
"type": "module",
"author": {
"name": "ZenStack Team",
Expand Down
2 changes: 1 addition & 1 deletion packages/clients/fetch-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@zenstackhq/fetch-client",
"displayName": "ZenStack Fetch Client",
"description": "Simple fetch-based client for consuming ZenStack's RPC-style CRUD API",
"version": "3.9.5",
"version": "3.9.6",
"type": "module",
"author": {
"name": "ZenStack Team",
Expand Down
2 changes: 1 addition & 1 deletion packages/clients/tanstack-query/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@zenstackhq/tanstack-query",
"displayName": "ZenStack TanStack Query Integration",
"description": "TanStack Query Client for consuming ZenStack v3's CRUD service",
"version": "3.9.5",
"version": "3.9.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
Expand Up @@ -2,7 +2,7 @@
"name": "@zenstackhq/common-helpers",
"displayName": "ZenStack Common Helpers",
"description": "ZenStack Common Helpers",
"version": "3.9.5",
"version": "3.9.6",
"type": "module",
"author": {
"name": "ZenStack Team",
Expand Down
2 changes: 1 addition & 1 deletion packages/config/eslint-config/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/eslint-config",
"version": "3.9.5",
"version": "3.9.6",
"type": "module",
"private": true,
"license": "MIT"
Expand Down
2 changes: 1 addition & 1 deletion packages/config/tsdown-config/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/tsdown-config",
"version": "3.9.5",
"version": "3.9.6",
"private": true,
"type": "module",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion packages/config/typescript-config/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/typescript-config",
"version": "3.9.5",
"version": "3.9.6",
"private": true,
"license": "MIT"
}
2 changes: 1 addition & 1 deletion packages/config/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.9.5",
"version": "3.9.6",
"private": true,
"license": "MIT",
"exports": {
Expand Down
2 changes: 1 addition & 1 deletion packages/create-zenstack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "create-zenstack",
"displayName": "Create ZenStack",
"description": "Create a new ZenStack project",
"version": "3.9.5",
"version": "3.9.6",
"type": "module",
"author": {
"name": "ZenStack Team",
Expand Down
2 changes: 1 addition & 1 deletion packages/ide/vscode/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "zenstack-v3",
"publisher": "zenstack",
"version": "3.9.5",
"version": "3.9.6",
"displayName": "ZenStack V3 Language Tools",
"description": "VSCode extension for ZenStack (v3) ZModel language",
"private": true,
Expand Down
2 changes: 1 addition & 1 deletion packages/language/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@zenstackhq/language",
"displayName": "ZenStack Language Tooling",
"description": "ZenStack ZModel language specification",
"version": "3.9.5",
"version": "3.9.6",
"type": "module",
"author": {
"name": "ZenStack Team",
Expand Down
2 changes: 1 addition & 1 deletion packages/orm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@zenstackhq/orm",
"displayName": "ZenStack ORM",
"description": "ZenStack ORM",
"version": "3.9.5",
"version": "3.9.6",
"type": "module",
"author": {
"name": "ZenStack Team",
Expand Down
38 changes: 32 additions & 6 deletions packages/orm/src/client/executor/name-mapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
type OrderByItemNode,
PrimitiveValueListNode,
type QueryId,
RawNode,
ReferenceNode,
ReturningNode,
SelectAllNode,
Expand Down Expand Up @@ -810,6 +811,15 @@ export class QueryNameMapper extends OperationNodeTransformer {
if (mappedValue) {
return mappedValue;
}
} else if (
this.isOperationNode(value) &&
ValueNode.is(value) &&
Array.isArray(value.value) &&
value.value.every((v) => typeof v === 'string')
) {
return ValueNode.create(value.value.map((v) => enumValueMapping[v] ?? v));
} else if (Array.isArray(value) && value.every((v) => typeof v === 'string')) {
return value.map((v) => enumValueMapping[v] ?? v);
}

return value;
Expand Down Expand Up @@ -839,23 +849,39 @@ export class QueryNameMapper extends OperationNodeTransformer {
return selection;
}

const shouldUseArray = fieldDef.array;

const eb = expressionBuilder();
const caseBuilder = eb.case();
const caseNode = shouldUseArray ? ColumnNode.create('t') : node;
let caseWhen: CaseWhenBuilder<any, any, any, any> | undefined;

for (const [key, value] of Object.entries(enumValueMapping)) {
if (!caseWhen) {
caseWhen = caseBuilder.when(new ExpressionWrapper(node), '=', value).then(key);
caseWhen = eb.case().when(new ExpressionWrapper(caseNode), '=', value).then(key);
} else {
caseWhen = caseWhen.when(new ExpressionWrapper(node), '=', value).then(key);
caseWhen = caseWhen.when(new ExpressionWrapper(caseNode), '=', value).then(key);
}
}

// the explicit cast to "text" is needed to address postgres's case-when type inference issue
const finalExpr = caseWhen!.else(this.dialect.castText(new ExpressionWrapper(node))).end();
const caseExpr = caseWhen!.else(this.dialect.castText(new ExpressionWrapper(caseNode))).end();

if (!shouldUseArray) {
if (aliasName) {
return caseExpr.as(aliasName).toOperationNode() as SelectionNodeChild;
} else {
return caseExpr.toOperationNode() as SelectionNodeChild;
}
}

const arrayExpr = new ExpressionWrapper(
RawNode.create(['ARRAY(SELECT ', ' FROM unnest( ', ' ) AS t)'], [caseExpr.toOperationNode(), node]),
);

if (aliasName) {
return finalExpr.as(aliasName).toOperationNode() as SelectionNodeChild;
return arrayExpr.as(aliasName).toOperationNode() as SelectionNodeChild;
} else {
return finalExpr.toOperationNode() as SelectionNodeChild;
return arrayExpr.toOperationNode() as SelectionNodeChild;
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/plugins/policy/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@zenstackhq/plugin-policy",
"displayName": "ZenStack Access Policy Plugin",
"description": "ZenStack plugin that enforces access control policies defined in the schema",
"version": "3.9.5",
"version": "3.9.6",
"type": "module",
"author": {
"name": "ZenStack Team",
Expand Down
38 changes: 27 additions & 11 deletions packages/plugins/policy/src/policy-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
AndNode,
BinaryOperationNode,
ColumnNode,
DefaultInsertValueNode,
DeleteQueryNode,
expressionBuilder,
ExpressionWrapper,
Expand All @@ -33,6 +34,7 @@ import {
sql,
TableNode,
UpdateQueryNode,
ValueListNode,
ValueNode,
ValuesNode,
WhereNode,
Expand Down Expand Up @@ -921,6 +923,16 @@ export class PolicyHandler<Schema extends SchemaDef> extends OperationNodeTransf
const valueRows = node.values
? this.unwrapCreateValueRows(node.values, mutationModel, fields, isManyToManyJoinTable)
: [[]];

if (!isManyToManyJoinTable) {
// A create filter built only from `auth()` doesn't reference the row being inserted,
// so it holds for every row alike and checking it per row re-asks the same question.
const filter = this.buildPolicyFilter(mutationModel, undefined, 'create');
if (isTrueNode(filter)) {
return;
}
}

for (const values of valueRows) {
if (isManyToManyJoinTable) {
await this.enforcePreCreatePolicyForManyToManyJoinTable(
Expand Down Expand Up @@ -1060,10 +1072,16 @@ export class PolicyHandler<Schema extends SchemaDef> extends OperationNodeTransf
fields: string[],
isManyToManyJoinTable: boolean,
) {
// Whether row items are operation nodes is determined by the row node's kind:
// `ValueListNode` items are always nodes, `PrimitiveValueListNode` items are always
// raw values. Never inspect an item's shape, because user data (e.g., Json values)
// may legitimately carry a `kind` key.
if (ValuesNode.is(node)) {
return node.values.map((v) => this.unwrapCreateValueRow(v.values, model, fields, isManyToManyJoinTable));
return node.values.map((v) =>
this.unwrapCreateValueRow(v.values, model, fields, isManyToManyJoinTable, ValueListNode.is(v)),
);
} else if (PrimitiveValueListNode.is(node)) {
return [this.unwrapCreateValueRow(node.values, model, fields, isManyToManyJoinTable)];
return [this.unwrapCreateValueRow(node.values, model, fields, isManyToManyJoinTable, false)];
} else {
invariant(false, `Unexpected node kind: ${node.kind} for unwrapping create values`);
}
Expand All @@ -1074,27 +1092,25 @@ export class PolicyHandler<Schema extends SchemaDef> extends OperationNodeTransf
model: string,
fields: string[],
isImplicitManyToManyJoinTable: boolean,
itemsAreNodes: boolean,
) {
invariant(data.length === fields.length, 'data length must match fields length');
const result: { node: OperationNode; raw: unknown }[] = [];
for (let i = 0; i < data.length; i++) {
const item = data[i]!;
if (typeof item === 'object' && item && 'kind' in item) {
if (item.kind === 'DefaultInsertValueNode') {
if (itemsAreNodes) {
const itemNode = item as OperationNode;
if (DefaultInsertValueNode.is(itemNode)) {
result.push({ node: ValueNode.create(null), raw: null });
continue;
}
const fieldDef = QueryUtils.requireField(this.client.$schema, model, fields[i]!);
invariant(item.kind === 'ValueNode', 'expecting a ValueNode');
invariant(ValueNode.is(itemNode), `expecting a ValueNode, got ${itemNode.kind}`);
result.push({
node: ValueNode.create(
this.dialect.transformInput(
(item as ValueNode).value,
fieldDef.type as BuiltinType,
!!fieldDef.array,
),
this.dialect.transformInput(itemNode.value, fieldDef.type as BuiltinType, !!fieldDef.array),
),
raw: (item as ValueNode).value,
raw: itemNode.value,
});
} else {
let value: unknown = item;
Expand Down
2 changes: 1 addition & 1 deletion packages/plugins/soft-delete/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@zenstackhq/plugin-soft-delete",
"displayName": "ZenStack Soft Delete Plugin",
"description": "ZenStack plugin that implements soft-delete by intercepting Kysely queries",
"version": "3.9.5",
"version": "3.9.6",
"type": "module",
"author": {
"name": "ZenStack Team",
Expand Down
2 changes: 1 addition & 1 deletion packages/schema/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@zenstackhq/schema",
"displayName": "ZenStack Schema Object Model",
"description": "TypeScript representation of ZModel schema",
"version": "3.9.5",
"version": "3.9.6",
"type": "module",
"author": {
"name": "ZenStack Team",
Expand Down
2 changes: 1 addition & 1 deletion packages/sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@zenstackhq/sdk",
"displayName": "ZenStack SDK",
"description": "Utilities for building ZenStack plugins",
"version": "3.9.5",
"version": "3.9.6",
"type": "module",
"author": {
"name": "ZenStack Team",
Expand Down
2 changes: 1 addition & 1 deletion packages/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@zenstackhq/server",
"displayName": "ZenStack Automatic CRUD Server",
"description": "ZenStack automatic CRUD API handlers and server adapters for popular frameworks",
"version": "3.9.5",
"version": "3.9.6",
"type": "module",
"author": {
"name": "ZenStack Team",
Expand Down
2 changes: 1 addition & 1 deletion packages/testtools/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@zenstackhq/testtools",
"displayName": "ZenStack Test Tools",
"description": "ZenStack Test Tools",
"version": "3.9.5",
"version": "3.9.6",
"type": "module",
"author": {
"name": "ZenStack Team",
Expand Down
2 changes: 1 addition & 1 deletion packages/zod/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@zenstackhq/zod",
"displayName": "ZenStack Zod Integration",
"description": "Automatically deriving Zod schemas from ZModel schemas",
"version": "3.9.5",
"version": "3.9.6",
"type": "module",
"author": {
"name": "ZenStack Team",
Expand Down
2 changes: 1 addition & 1 deletion samples/orm/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "sample-orm",
"version": "3.9.5",
"version": "3.9.6",
"description": "",
"main": "index.js",
"private": true,
Expand Down
2 changes: 1 addition & 1 deletion samples/taskforge/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "taskforge",
"version": "3.9.5",
"version": "3.9.6",
"type": "module",
"private": true,
"description": "A CLI for a team collaboration / project-tracking platform, built on ZenStack v3 (ORM) and better-auth.",
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.9.5",
"version": "3.9.6",
"private": true,
"type": "module",
"scripts": {
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.9.5",
"version": "3.9.6",
"private": true,
"type": "module",
"scripts": {
Expand Down
Loading
Loading