fix(web): support PostgREST not(col, is) so archived session lists load
Independent Staging Quality Gate / validate (push) Successful in 10m31s
Independent Staging Quality Gate / publish (push) Successful in 3m37s

Local Postgres not() only handled eq/cs, so archived=1 threw and the sidebar archive view returned 500. Compile is not null/true/false instead of inequality.
This commit is contained in:
jesse-ux
2026-09-21 17:45:07 +08:00
parent 70d595e361
commit df329fa96c
8 changed files with 137 additions and 9 deletions
@@ -20,6 +20,7 @@ type Filter =
| Readonly<{ kind: "like"; column: string; value: unknown }>
| Readonly<{ kind: "in"; column: string; value: readonly unknown[] }>
| Readonly<{ kind: "is"; column: string; value: unknown }>
| Readonly<{ kind: "isNot"; column: string; value: unknown }>
| Readonly<{ kind: "notContains"; column: string; value: unknown }>
| Readonly<{ kind: "or"; expression: string }>;
@@ -46,6 +47,19 @@ function identifier(value: string): string {
return `"${normalized}"`;
}
export function compileUnaryIsClause(
column: string,
value: unknown,
negated: boolean,
): string {
const quoted = identifier(column);
const target = value === null ? "null" : value === true ? "true" : value === false ? "false" : null;
if (target === null) {
throw new Error(negated ? "unsupported not filter" : "unsupported is filter");
}
return `${quoted} is${negated ? " not" : ""} ${target}`;
}
export function formatOrderClause(
ordering: readonly { column: string; ascending: boolean }[],
): string {
@@ -388,6 +402,11 @@ class LocalPostgresQueryBuilder implements PromiseLike<QueryResult> {
this.filters.push({ kind: "neq", column, value });
return this;
}
if (operator === "is") {
compileUnaryIsClause(column, value, true);
this.filters.push({ kind: "isNot", column, value });
return this;
}
if (operator !== "cs") throw new Error("unsupported not filter");
this.filters.push({ kind: "notContains", column, value });
return this;
@@ -451,10 +470,10 @@ class LocalPostgresQueryBuilder implements PromiseLike<QueryResult> {
}
const column = identifier(filter.column);
if (filter.kind === "is") {
if (filter.value === null) return `${column} is null`;
if (filter.value === true) return `${column} is true`;
if (filter.value === false) return `${column} is false`;
throw new Error("unsupported is filter");
return compileUnaryIsClause(filter.column, filter.value, false);
}
if (filter.kind === "isNot") {
return compileUnaryIsClause(filter.column, filter.value, true);
}
if (filter.kind === "in") {
if (filter.value.length === 0) return "false";