import { getAuth } from './helpers/getAuth'
import { globalValue } from './helpers/globalValue'
import { getEnvironment } from './state'
import type { TableName, Where } from './types'
import type { Condition, ExpressionBuilder } from '@rocicorp/zero'
// when true, serverWhere bypasses the client no-op so nested serverWhere
// calls inside permission builders actually evaluate on the client
let _evaluatingPermission = false
export function setEvaluatingPermission(value: boolean) {
_evaluatingPermission = value
}
export function where
>(
tableName: Table,
builder: Builder,
isServerOnly?: boolean
): Where
export function where>(
builder: Builder
): Where
export function where>(
a: Table | Builder,
b?: Builder,
isServerOnly = false
): Where | Builder {
const whereFn = (b || a) as any
const wrappedWhereFn = ((a: ExpressionBuilder, b = getAuth()) => {
if (getEnvironment() !== 'server' && isServerOnly && !_evaluatingPermission) {
// on client (web or native) where conditions always pass
return a.and()
}
const result = whereFn(a, b)
if (typeof result === 'boolean') {
if (result) {
return a.cmpLit(0, '=', 0)
} else {
return a.cmpLit(1, '=', 0)
}
}
return result
}) as Builder
// store the raw (unwrapped) builder so permission checks can evaluate it on client
WhereRawBuilderMap.set(wrappedWhereFn, whereFn)
if (b) {
WhereTableNameMap.set(wrappedWhereFn, a as Table)
}
return wrappedWhereFn
}
// permissions where:
const WhereTableNameMap = globalValue(
`on-zero:where-name`,
() => new WeakMap()
)
const WhereRawBuilderMap = globalValue(
`on-zero:where-raw`,
() => new WeakMap()
)
export function getWhereTableName(where: Where) {
return WhereTableNameMap.get(where)
}
// returns the raw builder that always evaluates (bypasses serverWhere client no-op)
export function getRawWhere(where: Where): Where | undefined {
return WhereRawBuilderMap.get(where)
}