Skip to content

Commit 4115244

Browse files
authored
refactor: move e2e orm tests to e2e project, fix bundle issues (#285)
* refactor: move e2e orm tests to e2e project, fix bundle issues * add missing package * include all tests * more fixes * update lockfile * extract policy plugin to its own package * fix lint * addressing review comments
1 parent 6eaf1cd commit 4115244

File tree

169 files changed

+820
-444
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

169 files changed

+820
-444
lines changed

packages/cli/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
"@zenstackhq/testtools": "workspace:*",
5454
"@zenstackhq/typescript-config": "workspace:*",
5555
"@zenstackhq/vitest-config": "workspace:*",
56-
"better-sqlite3": "^12.2.0",
56+
"better-sqlite3": "catalog:",
5757
"tmp": "catalog:"
5858
}
5959
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import config from '@zenstackhq/eslint-config/base.js';
2+
3+
/** @type {import("eslint").Linter.Config} */
4+
export default config;
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"name": "@zenstackhq/plugin-policy",
3+
"version": "3.0.0-beta.8",
4+
"description": "ZenStack Policy Plugin",
5+
"type": "module",
6+
"scripts": {
7+
"build": "tsc --noEmit && tsup-node",
8+
"watch": "tsup-node --watch",
9+
"lint": "eslint src --ext ts",
10+
"pack": "pnpm pack"
11+
},
12+
"keywords": [],
13+
"author": "ZenStack Team",
14+
"license": "MIT",
15+
"files": [
16+
"dist"
17+
],
18+
"exports": {
19+
".": {
20+
"import": {
21+
"types": "./dist/index.d.ts",
22+
"default": "./dist/index.js"
23+
},
24+
"require": {
25+
"types": "./dist/index.d.cts",
26+
"default": "./dist/index.cjs"
27+
}
28+
},
29+
"./package.json": {
30+
"import": "./package.json",
31+
"require": "./package.json"
32+
}
33+
},
34+
"dependencies": {
35+
"@zenstackhq/common-helpers": "workspace:*",
36+
"@zenstackhq/sdk": "workspace:*",
37+
"@zenstackhq/runtime": "workspace:*",
38+
"ts-pattern": "catalog:"
39+
},
40+
"peerDependencies": {
41+
"kysely": "catalog:"
42+
},
43+
"devDependencies": {
44+
"@types/better-sqlite3": "^7.6.13",
45+
"@types/pg": "^8.0.0",
46+
"@zenstackhq/eslint-config": "workspace:*",
47+
"@zenstackhq/typescript-config": "workspace:*",
48+
"@zenstackhq/vitest-config": "workspace:*"
49+
}
50+
}

packages/runtime/src/plugins/policy/column-collector.ts renamed to packages/plugins/policy/src/column-collector.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { ColumnNode, OperationNode } from 'kysely';
2-
import { DefaultOperationNodeVisitor } from '../../utils/default-operation-node-visitor';
2+
import { DefaultOperationNodeVisitor } from '@zenstackhq/sdk';
33

44
/**
55
* Collects all column names from a query.

packages/runtime/src/plugins/policy/expression-evaluator.ts renamed to packages/plugins/policy/src/expression-evaluator.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
type LiteralExpression,
1111
type MemberExpression,
1212
type UnaryExpression,
13-
} from '../../schema';
13+
} from '@zenstackhq/runtime/schema';
1414

1515
type ExpressionEvaluatorContext = {
1616
auth?: any;

packages/runtime/src/plugins/policy/expression-transformer.ts renamed to packages/plugins/policy/src/expression-transformer.ts

Lines changed: 42 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,31 @@
11
import { invariant } from '@zenstackhq/common-helpers';
2+
import {
3+
getCrudDialect,
4+
InternalError,
5+
QueryError,
6+
QueryUtils,
7+
type BaseCrudDialect,
8+
type ClientContract,
9+
type CRUD_EXT,
10+
} from '@zenstackhq/runtime';
11+
import type {
12+
BinaryExpression,
13+
BinaryOperator,
14+
BuiltinType,
15+
FieldDef,
16+
GetModels,
17+
LiteralExpression,
18+
MemberExpression,
19+
UnaryExpression,
20+
} from '@zenstackhq/runtime/schema';
21+
import {
22+
ExpressionUtils,
23+
type ArrayExpression,
24+
type CallExpression,
25+
type Expression,
26+
type FieldExpression,
27+
type SchemaDef,
28+
} from '@zenstackhq/runtime/schema';
229
import {
330
AliasNode,
431
BinaryOperationNode,
@@ -20,35 +47,6 @@ import {
2047
type OperationNode,
2148
} from 'kysely';
2249
import { match } from 'ts-pattern';
23-
import type { ClientContract, CRUD_EXT } from '../../client/contract';
24-
import { getCrudDialect } from '../../client/crud/dialects';
25-
import type { BaseCrudDialect } from '../../client/crud/dialects/base-dialect';
26-
import { InternalError, QueryError } from '../../client/errors';
27-
import {
28-
getManyToManyRelation,
29-
getModel,
30-
getRelationForeignKeyFieldPairs,
31-
requireField,
32-
requireIdFields,
33-
} from '../../client/query-utils';
34-
import type {
35-
BinaryExpression,
36-
BinaryOperator,
37-
BuiltinType,
38-
FieldDef,
39-
GetModels,
40-
LiteralExpression,
41-
MemberExpression,
42-
UnaryExpression,
43-
} from '../../schema';
44-
import {
45-
ExpressionUtils,
46-
type ArrayExpression,
47-
type CallExpression,
48-
type Expression,
49-
type FieldExpression,
50-
type SchemaDef,
51-
} from '../../schema';
5250
import { ExpressionEvaluator } from './expression-evaluator';
5351
import { conjunction, disjunction, falseNode, isBeforeInvocation, logicalNot, trueNode } from './utils';
5452

@@ -124,7 +122,7 @@ export class ExpressionTransformer<Schema extends SchemaDef> {
124122

125123
@expr('field')
126124
private _field(expr: FieldExpression, context: ExpressionTransformerContext<Schema>) {
127-
const fieldDef = requireField(this.schema, context.model, expr.field);
125+
const fieldDef = QueryUtils.requireField(this.schema, context.model, expr.field);
128126
if (!fieldDef.relation) {
129127
return this.createColumnRef(expr.field, context);
130128
} else {
@@ -226,15 +224,15 @@ export class ExpressionTransformer<Schema extends SchemaDef> {
226224
invariant(ExpressionUtils.isNull(expr.right), 'only null comparison is supported for relation field');
227225
const leftRelDef = this.getFieldDefFromFieldRef(expr.left, context.model);
228226
invariant(leftRelDef, 'failed to get relation field definition');
229-
const idFields = requireIdFields(this.schema, leftRelDef.type);
227+
const idFields = QueryUtils.requireIdFields(this.schema, leftRelDef.type);
230228
normalizedLeft = this.makeOrAppendMember(normalizedLeft, idFields[0]!);
231229
}
232230
let normalizedRight: Expression = expr.right;
233231
if (this.isRelationField(expr.right, context.model)) {
234232
invariant(ExpressionUtils.isNull(expr.left), 'only null comparison is supported for relation field');
235233
const rightRelDef = this.getFieldDefFromFieldRef(expr.right, context.model);
236234
invariant(rightRelDef, 'failed to get relation field definition');
237-
const idFields = requireIdFields(this.schema, rightRelDef.type);
235+
const idFields = QueryUtils.requireIdFields(this.schema, rightRelDef.type);
238236
normalizedRight = this.makeOrAppendMember(normalizedRight, idFields[0]!);
239237
}
240238
return { normalizedLeft, normalizedRight };
@@ -265,10 +263,10 @@ export class ExpressionTransformer<Schema extends SchemaDef> {
265263
ExpressionUtils.isMember(expr.left) && ExpressionUtils.isField(expr.left.receiver),
266264
'left operand must be member access with field receiver',
267265
);
268-
const fieldDef = requireField(this.schema, context.model, expr.left.receiver.field);
266+
const fieldDef = QueryUtils.requireField(this.schema, context.model, expr.left.receiver.field);
269267
newContextModel = fieldDef.type;
270268
for (const member of expr.left.members) {
271-
const memberDef = requireField(this.schema, newContextModel, member);
269+
const memberDef = QueryUtils.requireField(this.schema, newContextModel, member);
272270
newContextModel = memberDef.type;
273271
}
274272
}
@@ -318,7 +316,7 @@ export class ExpressionTransformer<Schema extends SchemaDef> {
318316
if (ExpressionUtils.isNull(other)) {
319317
return this.transformValue(expr.op === '==' ? !this.auth : !!this.auth, 'Boolean');
320318
} else {
321-
const authModel = getModel(this.schema, this.authType);
319+
const authModel = QueryUtils.getModel(this.schema, this.authType);
322320
if (!authModel) {
323321
throw new QueryError(
324322
`Unsupported use of \`auth()\` in policy of model "${context.model}", comparing with \`auth()\` is only possible when auth type is a model`,
@@ -481,7 +479,7 @@ export class ExpressionTransformer<Schema extends SchemaDef> {
481479
return this._field(ExpressionUtils.field(expr.members[0]!), context);
482480
} else {
483481
// transform the first segment into a relation access, then continue with the rest of the members
484-
const firstMemberFieldDef = requireField(this.schema, context.model, expr.members[0]!);
482+
const firstMemberFieldDef = QueryUtils.requireField(this.schema, context.model, expr.members[0]!);
485483
receiver = this.transformRelationAccess(expr.members[0]!, firstMemberFieldDef.type, restContext);
486484
members = expr.members.slice(1);
487485
}
@@ -493,7 +491,7 @@ export class ExpressionTransformer<Schema extends SchemaDef> {
493491

494492
let startType: string;
495493
if (ExpressionUtils.isField(expr.receiver)) {
496-
const receiverField = requireField(this.schema, context.model, expr.receiver.field);
494+
const receiverField = QueryUtils.requireField(this.schema, context.model, expr.receiver.field);
497495
startType = receiverField.type;
498496
} else {
499497
// "this." case, start type is the model of the context
@@ -504,7 +502,7 @@ export class ExpressionTransformer<Schema extends SchemaDef> {
504502
const memberFields: { fromModel: string; fieldDef: FieldDef }[] = [];
505503
let currType = startType;
506504
for (const member of members) {
507-
const fieldDef = requireField(this.schema, currType, member);
505+
const fieldDef = QueryUtils.requireField(this.schema, currType, member);
508506
memberFields.push({ fieldDef, fromModel: currType });
509507
currType = fieldDef.type;
510508
}
@@ -561,7 +559,7 @@ export class ExpressionTransformer<Schema extends SchemaDef> {
561559
}
562560

563561
const field = expr.members[0]!;
564-
const fieldDef = requireField(this.schema, receiverType, field);
562+
const fieldDef = QueryUtils.requireField(this.schema, receiverType, field);
565563
const fieldValue = receiver[field] ?? null;
566564
return this.transformValue(fieldValue, fieldDef.type as BuiltinType);
567565
}
@@ -571,13 +569,13 @@ export class ExpressionTransformer<Schema extends SchemaDef> {
571569
relationModel: string,
572570
context: ExpressionTransformerContext<Schema>,
573571
): SelectQueryNode {
574-
const m2m = getManyToManyRelation(this.schema, context.model, field);
572+
const m2m = QueryUtils.getManyToManyRelation(this.schema, context.model, field);
575573
if (m2m) {
576574
return this.transformManyToManyRelationAccess(m2m, context);
577575
}
578576

579577
const fromModel = context.model;
580-
const { keyPairs, ownedByModel } = getRelationForeignKeyFieldPairs(this.schema, fromModel, field);
578+
const { keyPairs, ownedByModel } = QueryUtils.getRelationForeignKeyFieldPairs(this.schema, fromModel, field);
581579

582580
let condition: OperationNode;
583581
if (ownedByModel) {
@@ -614,7 +612,7 @@ export class ExpressionTransformer<Schema extends SchemaDef> {
614612
}
615613

616614
private transformManyToManyRelationAccess(
617-
m2m: NonNullable<ReturnType<typeof getManyToManyRelation>>,
615+
m2m: NonNullable<ReturnType<typeof QueryUtils.getManyToManyRelation>>,
618616
context: ExpressionTransformerContext<Schema>,
619617
) {
620618
const eb = expressionBuilder<any, any>();
@@ -672,13 +670,13 @@ export class ExpressionTransformer<Schema extends SchemaDef> {
672670

673671
private getFieldDefFromFieldRef(expr: Expression, model: GetModels<Schema>): FieldDef | undefined {
674672
if (ExpressionUtils.isField(expr)) {
675-
return requireField(this.schema, model, expr.field);
673+
return QueryUtils.requireField(this.schema, model, expr.field);
676674
} else if (
677675
ExpressionUtils.isMember(expr) &&
678676
expr.members.length === 1 &&
679677
ExpressionUtils.isThis(expr.receiver)
680678
) {
681-
return requireField(this.schema, model, expr.members[0]!);
679+
return QueryUtils.requireField(this.schema, model, expr.members[0]!);
682680
} else {
683681
return undefined;
684682
}

packages/runtime/src/plugins/policy/functions.ts renamed to packages/plugins/policy/src/functions.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import { invariant } from '@zenstackhq/common-helpers';
2+
import type { ZModelFunction, ZModelFunctionContext } from '@zenstackhq/runtime';
3+
import { CRUD, QueryUtils } from '@zenstackhq/runtime';
24
import { ExpressionWrapper, ValueNode, type Expression, type ExpressionBuilder } from 'kysely';
3-
import { CRUD } from '../../client/contract';
4-
import { extractFieldName } from '../../client/kysely-utils';
5-
import type { ZModelFunction, ZModelFunctionContext } from '../../client/options';
6-
import { buildJoinPairs, requireField } from '../../client/query-utils';
75
import { PolicyHandler } from './policy-handler';
86

97
/**
@@ -31,9 +29,9 @@ export const check: ZModelFunction<any> = (
3129
}
3230

3331
// first argument must be a field reference
34-
const fieldName = extractFieldName(arg1Node);
32+
const fieldName = QueryUtils.extractFieldName(arg1Node);
3533
invariant(fieldName, 'Failed to extract field name from the first argument of "check" function');
36-
const fieldDef = requireField(client.$schema, model, fieldName);
34+
const fieldDef = QueryUtils.requireField(client.$schema, model, fieldName);
3735
invariant(fieldDef.relation, `Field "${fieldName}" is not a relation field in model "${model}"`);
3836
invariant(!fieldDef.array, `Field "${fieldName}" is a to-many relation, which is not supported by "check"`);
3937
const relationModel = fieldDef.type;
@@ -43,7 +41,7 @@ export const check: ZModelFunction<any> = (
4341
const policyHandler = new PolicyHandler(client);
4442

4543
// join with parent model
46-
const joinPairs = buildJoinPairs(client.$schema, model, modelAlias, fieldName, relationModel);
44+
const joinPairs = QueryUtils.buildJoinPairs(client.$schema, model, modelAlias, fieldName, relationModel);
4745
const joinCondition =
4846
joinPairs.length === 1
4947
? eb(eb.ref(joinPairs[0]![0]), '=', eb.ref(joinPairs[0]![1]))
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
export * from './errors';
21
export * from './plugin';

packages/runtime/src/plugins/policy/plugin.ts renamed to packages/plugins/policy/src/plugin.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { type OnKyselyQueryArgs, type RuntimePlugin } from '../../client/plugin';
2-
import type { SchemaDef } from '../../schema';
1+
import { type OnKyselyQueryArgs, type RuntimePlugin } from '@zenstackhq/runtime';
2+
import type { SchemaDef } from '@zenstackhq/runtime/schema';
33
import { check } from './functions';
44
import { PolicyHandler } from './policy-handler';
55

0 commit comments

Comments
 (0)