Skip to content

Commit 22ed47c

Browse files
committed
refactor(z3): remove normalizeUndefined option
1 parent e3f1538 commit 22ed47c

File tree

2 files changed

+57
-78
lines changed

2 files changed

+57
-78
lines changed

packages/schema/src/plugins/enhancer/policy/policy-guard-generator.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -981,24 +981,24 @@ export class PolicyGenerator {
981981
? 'z3.Not(z3.Or(' +
982982
denies
983983
.map((deny) => {
984-
return transformer.transform(deny, false);
984+
return transformer.transform(deny);
985985
})
986986
.join(', ') +
987987
'))'
988988
: denies.length === 1
989-
? `z3.Not(${transformer.transform(denies[0], false)})`
989+
? `z3.Not(${transformer.transform(denies[0])})`
990990
: undefined;
991991
const allowStmt =
992992
allows.length > 1
993993
? 'z3.Or(' +
994994
allows
995995
.map((allow) => {
996-
return transformer.transform(allow, false);
996+
return transformer.transform(allow);
997997
})
998998
.join(', ') +
999999
')'
10001000
: allows.length === 1
1001-
? transformer.transform(allows[0], false)
1001+
? transformer.transform(allows[0])
10021002
: undefined;
10031003
let assertion;
10041004
if (denyStmt && allowStmt) {

packages/sdk/src/z3-expression-transformer.ts

Lines changed: 53 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,9 @@ export class Z3ExpressionTransformer {
6363

6464
/**
6565
* Transforms the given expression to a TypeScript expression.
66-
* @param normalizeUndefined if undefined values should be normalized to null
6766
* @returns
6867
*/
69-
transform(expr: Expression, normalizeUndefined = true): string {
70-
// let assertion = '';
71-
// let checkStrings: Record<string, string> = {};
68+
transform(expr: Expression): string {
7269
switch (expr.$type) {
7370
case StringLiteral:
7471
case NumberLiteral:
@@ -78,7 +75,7 @@ export class Z3ExpressionTransformer {
7875
return this.boolean(expr as BooleanLiteral);
7976

8077
case ArrayExpr:
81-
return this.array(expr as ArrayExpr, normalizeUndefined);
78+
return this.array(expr as ArrayExpr);
8279

8380
case NullExpr:
8481
return this.null();
@@ -90,17 +87,17 @@ export class Z3ExpressionTransformer {
9087
return this.reference(expr as ReferenceExpr);
9188

9289
case InvocationExpr:
93-
return this.invocation(expr as InvocationExpr, normalizeUndefined);
90+
return this.invocation(expr as InvocationExpr);
9491

9592
case MemberAccessExpr:
96-
return this.memberAccess(expr as MemberAccessExpr, normalizeUndefined);
93+
return this.memberAccess(expr as MemberAccessExpr);
9794

9895
case UnaryExpr:
99-
return this.unary(expr as UnaryExpr, normalizeUndefined);
96+
return this.unary(expr as UnaryExpr);
10097

10198
case BinaryExpr:
10299
// eslint-disable-next-line no-case-declarations
103-
const assertion = this.binary(expr as BinaryExpr, normalizeUndefined);
100+
const assertion = this.binary(expr as BinaryExpr);
104101
if (['&&', '||'].includes(expr.operator)) return assertion;
105102
// eslint-disable-next-line no-case-declarations
106103
const checkString =
@@ -124,7 +121,7 @@ export class Z3ExpressionTransformer {
124121
return this.options.thisExprContext ?? 'input';
125122
}
126123

127-
private memberAccess(expr: MemberAccessExpr, normalizeUndefined: boolean) {
124+
private memberAccess(expr: MemberAccessExpr) {
128125
if (!expr.member.ref) {
129126
throw new Z3ExpressionTransformerError(`Unresolved MemberAccessExpr`);
130127
}
@@ -137,16 +134,11 @@ export class Z3ExpressionTransformer {
137134
}
138135
return expr.member.ref.name;
139136
} else {
140-
if (normalizeUndefined) {
141-
// normalize field access to null instead of undefined to avoid accidentally use undefined in filter
142-
return `(${this.transform(expr.operand, normalizeUndefined)}?.${expr.member.ref.name} ?? null)`;
143-
} else {
144-
return `${this.transform(expr.operand, normalizeUndefined)}?.${expr.member.ref.name}`;
145-
}
137+
return `${this.transform(expr.operand)}?.${expr.member.ref.name}`;
146138
}
147139
}
148140

149-
private invocation(expr: InvocationExpr, normalizeUndefined: boolean) {
141+
private invocation(expr: InvocationExpr) {
150142
if (!expr.function.ref) {
151143
throw new Z3ExpressionTransformerError(`Unresolved InvocationExpr`);
152144
}
@@ -164,7 +156,7 @@ export class Z3ExpressionTransformer {
164156
}
165157

166158
const args = expr.args.map((arg) => arg.value);
167-
return handler.value.call(this, args, normalizeUndefined);
159+
return handler.value.call(this, args);
168160
}
169161

170162
// #region function invocation handlers
@@ -183,7 +175,7 @@ export class Z3ExpressionTransformer {
183175

184176
@func('length')
185177
private _length(args: Expression[]) {
186-
const field = this.transform(args[0], false); // TODO: false for inverse here?
178+
const field = this.transform(args[0]);
187179
const min = getLiteral<number>(args[1]);
188180
const max = getLiteral<number>(args[2]);
189181
let result: string;
@@ -198,81 +190,81 @@ export class Z3ExpressionTransformer {
198190
}
199191

200192
@func('contains')
201-
private _contains(args: Expression[], normalizeUndefined: boolean) {
202-
const field = this.transform(args[0], false);
193+
private _contains(args: Expression[]) {
194+
const field = this.transform(args[0]);
203195
const caseInsensitive = getLiteral<boolean>(args[2]) === true;
204196
let result: string;
205197
if (caseInsensitive) {
206-
result = `${field}?.toLowerCase().includes(${this.transform(args[1], normalizeUndefined)}?.toLowerCase())`;
198+
result = `${field}?.toLowerCase().includes(${this.transform(args[1])}?.toLowerCase())`;
207199
} else {
208-
result = `${field}?.includes(${this.transform(args[1], normalizeUndefined)})`;
200+
result = `${field}?.includes(${this.transform(args[1])})`;
209201
}
210202
return this.ensureBoolean(result);
211203
}
212204

213205
@func('startsWith')
214-
private _startsWith(args: Expression[], normalizeUndefined: boolean) {
215-
const field = this.transform(args[0], false);
216-
const result = `${field}?.startsWith(${this.transform(args[1], normalizeUndefined)})`;
206+
private _startsWith(args: Expression[]) {
207+
const field = this.transform(args[0]);
208+
const result = `${field}?.startsWith(${this.transform(args[1])})`;
217209
return this.ensureBoolean(result);
218210
}
219211

220212
@func('endsWith')
221-
private _endsWith(args: Expression[], normalizeUndefined: boolean) {
222-
const field = this.transform(args[0], false);
223-
const result = `${field}?.endsWith(${this.transform(args[1], normalizeUndefined)})`;
213+
private _endsWith(args: Expression[]) {
214+
const field = this.transform(args[0]);
215+
const result = `${field}?.endsWith(${this.transform(args[1])})`;
224216
return this.ensureBoolean(result);
225217
}
226218

227219
@func('regex')
228220
private _regex(args: Expression[]) {
229-
const field = this.transform(args[0], false);
221+
const field = this.transform(args[0]);
230222
const pattern = getLiteral<string>(args[1]);
231223
return `new RegExp(${JSON.stringify(pattern)}).test(${field})`;
232224
}
233225

234226
@func('email')
235227
private _email(args: Expression[]) {
236-
const field = this.transform(args[0], false);
228+
const field = this.transform(args[0]);
237229
return `z.string().email().safeParse(${field}).success`;
238230
}
239231

240232
@func('datetime')
241233
private _datetime(args: Expression[]) {
242-
const field = this.transform(args[0], false);
234+
const field = this.transform(args[0]);
243235
return `z.string().datetime({ offset: true }).safeParse(${field}).success`;
244236
}
245237

246238
@func('url')
247239
private _url(args: Expression[]) {
248-
const field = this.transform(args[0], false);
240+
const field = this.transform(args[0]);
249241
return `z.string().url().safeParse(${field}).success`;
250242
}
251243

252244
@func('has')
253-
private _has(args: Expression[], normalizeUndefined: boolean) {
254-
const field = this.transform(args[0], false);
255-
const result = `${field}?.includes(${this.transform(args[1], normalizeUndefined)})`;
245+
private _has(args: Expression[]) {
246+
const field = this.transform(args[0]);
247+
const result = `${field}?.includes(${this.transform(args[1])})`;
256248
return this.ensureBoolean(result);
257249
}
258250

259251
@func('hasEvery')
260-
private _hasEvery(args: Expression[], normalizeUndefined: boolean) {
261-
const field = this.transform(args[0], false);
262-
const result = `${this.transform(args[1], normalizeUndefined)}?.every((item) => ${field}?.includes(item))`;
252+
private _hasEvery(args: Expression[]) {
253+
const field = this.transform(args[0]);
254+
const result = `${this.transform(args[1])}?.every((item) => ${field}?.includes(item))`;
263255
return this.ensureBoolean(result);
264256
}
265257

266258
@func('hasSome')
267-
private _hasSome(args: Expression[], normalizeUndefined: boolean) {
268-
const field = this.transform(args[0], false);
269-
const result = `${this.transform(args[1], normalizeUndefined)}?.some((item) => ${field}?.includes(item))`;
259+
private _hasSome(args: Expression[]) {
260+
const field = this.transform(args[0]);
261+
const result = `${this.transform(args[1])}?.some((item) => ${field}?.includes(item))`;
270262
return this.ensureBoolean(result);
271263
}
272264

273265
@func('isEmpty')
274266
private _isEmpty(args: Expression[]) {
275-
const field = this.transform(args[0], false);
267+
const field = this.transform(args[0]);
276268
const result = `(!${field} || ${field}?.length === 0)`;
277269
return this.ensureBoolean(result);
278270
}
@@ -304,8 +296,8 @@ export class Z3ExpressionTransformer {
304296
return 'null';
305297
}
306298

307-
private array(expr: ArrayExpr, normalizeUndefined: boolean) {
308-
return `[${expr.items.map((item) => this.transform(item, normalizeUndefined)).join(', ')}]`;
299+
private array(expr: ArrayExpr) {
300+
return `[${expr.items.map((item) => this.transform(item)).join(', ')}]`;
309301
}
310302

311303
private literal(expr: LiteralExpr) {
@@ -320,41 +312,35 @@ export class Z3ExpressionTransformer {
320312
return `z3.Bool.val(${expr.value})`;
321313
}
322314

323-
private unary(expr: UnaryExpr, normalizeUndefined: boolean): string {
324-
return `(${expr.operator} ${this.transform(expr.operand, normalizeUndefined)})`;
315+
private unary(expr: UnaryExpr): string {
316+
return `(${expr.operator} ${this.transform(expr.operand)})`;
325317
}
326318

327319
private isModelType(expr: Expression) {
328320
return isDataModel(expr.$resolvedType?.decl);
329321
}
330322

331-
private binary(expr: BinaryExpr, normalizeUndefined: boolean): string {
323+
private binary(expr: BinaryExpr): string {
332324
if (/* expr.left.$type === 'ReferenceExpr' && */ expr.right.$type === 'StringLiteral') return 'true';
333325

334-
let left = this.transform(expr.left, normalizeUndefined);
335-
let right = isBooleanLiteral(expr.right)
336-
? `${expr.right.value}`
337-
: this.transform(expr.right, normalizeUndefined);
326+
let left = this.transform(expr.left);
327+
let right = isBooleanLiteral(expr.right) ? `${expr.right.value}` : this.transform(expr.right);
338328
// if (isMemberAccessExpr(expr.left) && !isAuthInvocation(expr.left)) {
339329
// left = `args.${left}`;
340330
// }
341331
// if (isMemberAccessExpr(expr.right) && !isAuthInvocation(expr.right)) {
342332
// right = `args.${right}`;
343333
// }
344334
// if (this.isModelType(expr.left)) {
345-
// left = `(${left}.id ?? null)`;
335+
// left = `(${left}.id)`;
346336
// }
347337
// if (this.isModelType(expr.right)) {
348-
// right = `(${right}.id ?? null)`;
338+
// right = `(${right}.id)`;
349339
// }
350340
if (this.isModelType(expr.left) && this.isModelType(expr.right)) {
351341
// comparison between model type values, map to id comparison
352-
left = isAuthInvocation(expr.left)
353-
? `(${left}?.id ?? null)`
354-
: `((args.${left}?.id || args.${left}Id) ?? null)`;
355-
right = isAuthInvocation(expr.right)
356-
? `(${right}.id ?? null)`
357-
: `((args.${right}?.id || args.${right}Id) ?? null)`;
342+
left = isAuthInvocation(expr.left) ? `(${left}?.id)` : `((args.${left}?.id || args.${left}Id))`;
343+
right = isAuthInvocation(expr.right) ? `(${right}.id)` : `((args.${right}?.id || args.${right}Id))`;
358344
let assertion = `${left} ${expr.operator} ${right}`;
359345

360346
// only args values need implies
@@ -369,8 +355,8 @@ export class Z3ExpressionTransformer {
369355
}
370356

371357
if (isAuthInvocation(expr.left) || isAuthInvocation(expr.right)) {
372-
left = isAuthInvocation(expr.left) ? `(${left}?.id ?? null)` : left;
373-
right = isAuthInvocation(expr.right) ? `(${right}.id ?? null)` : right;
358+
left = isAuthInvocation(expr.left) ? `(${left}?.id)` : left;
359+
right = isAuthInvocation(expr.right) ? `(${right}.id)` : right;
374360
const assertion = `${left} ${expr.operator} ${right}`;
375361
if (this.needAuthCheck(expr)) {
376362
return this.withAuth(expr, assertion);
@@ -414,14 +400,7 @@ export class Z3ExpressionTransformer {
414400
.with('<=', () => `${left}.le(${right})`)
415401
.with('>', () => `${left}.gt(${right})`)
416402
.with('>=', () => `${left}.ge(${right})`)
417-
.with(
418-
'in',
419-
() =>
420-
`(${this.transform(expr.right, false)}?.includes(${this.transform(
421-
expr.left,
422-
normalizeUndefined
423-
)}) ?? false)`
424-
)
403+
.with('in', () => `(${this.transform(expr.right)}?.includes(${this.transform(expr.left)}) ?? false)`)
425404
// .with(P.union('==', '!='), () => {
426405
// if (isThisExpr(expr.left) || isThisExpr(expr.right)) {
427406
// // map equality comparison with `this` to id comparison
@@ -441,20 +420,20 @@ export class Z3ExpressionTransformer {
441420
// return _default;
442421
// }
443422
// })
444-
.with(P.union('?', '!', '^'), (op) => this.collectionPredicate(expr, op, normalizeUndefined))
423+
.with(P.union('?', '!', '^'), (op) => this.collectionPredicate(expr, op))
445424
.otherwise(() => _default)
446425
);
447426
}
448427

449-
private collectionPredicate(expr: BinaryExpr, operator: '?' | '!' | '^', normalizeUndefined: boolean) {
450-
const operand = this.transform(expr.left, normalizeUndefined);
428+
private collectionPredicate(expr: BinaryExpr, operator: '?' | '!' | '^') {
429+
const operand = this.transform(expr.left);
451430
const innerTransformer = new Z3ExpressionTransformer({
452431
...this.options,
453432
isPostGuard: false,
454433
fieldReferenceContext: '_item',
455434
thisExprContext: '_item',
456435
});
457-
const predicate = innerTransformer.transform(expr.right, normalizeUndefined);
436+
const predicate = innerTransformer.transform(expr.right);
458437

459438
return match(operator)
460439
.with('?', () => `!!((${operand})?.some((_item: any) => ${predicate}))`)

0 commit comments

Comments
 (0)