Skip to content

Commit 5c74f71

Browse files
author
zho
committed
#15-fix validation logic for array type
1 parent 52ba00d commit 5c74f71

3 files changed

Lines changed: 25 additions & 22 deletions

File tree

src/server/metadata-filter.ts

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ function isPrimitiveFilterValue(value: unknown): boolean {
3030
return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean';
3131
}
3232

33-
/** True if value is an array of primitives (required for $in/$nin). */
33+
/** True if value is an array of string (required for $in/$nin). */
3434
function isPrimitiveArray(value: unknown): boolean {
35-
return Array.isArray(value) && value.every((item) => isPrimitiveFilterValue(item));
35+
return Array.isArray(value) && value.every((item) => typeof item === 'string');
3636
}
3737

3838
/** Recursively validate a filter value; returns an error string or null if valid. */
@@ -50,25 +50,27 @@ function validateMetadataFilterValue(value: unknown, path: string[]): string | n
5050
}
5151

5252
for (const [key, nestedValue] of Object.entries(value)) {
53-
if (key.startsWith('$')) {
54-
if (!ALLOWED_FILTER_OPERATORS.has(key)) {
55-
return `Unsupported filter operator "${key}" at "${path.join('.')}".`;
56-
}
57-
if ((key === '$in' || key === '$nin') && !isPrimitiveArray(nestedValue)) {
58-
return `Operator "${key}" at "${path.join('.')}" must use an array of primitive values.`;
59-
}
60-
if (
61-
(key === '$eq' ||
62-
key === '$ne' ||
63-
key === '$gt' ||
64-
key === '$gte' ||
65-
key === '$lt' ||
66-
key === '$lte') &&
67-
!isPrimitiveFilterValue(nestedValue)
68-
) {
69-
return `Operator "${key}" at "${path.join('.')}" must use a primitive value.`;
70-
}
53+
if (!key.startsWith('$')) {
54+
return `Unsupported filter operator "${key}" at "${path.join('.')}".`;
7155
}
56+
if (!ALLOWED_FILTER_OPERATORS.has(key)) {
57+
return `Unsupported filter operator "${key}" at "${path.join('.')}".`;
58+
}
59+
if ((key === '$in' || key === '$nin') && !isPrimitiveArray(nestedValue)) {
60+
return `Operator "${key}" at "${path.join('.')}" must use an array of primitive values.`;
61+
}
62+
if (
63+
(key === '$eq' ||
64+
key === '$ne' ||
65+
key === '$gt' ||
66+
key === '$gte' ||
67+
key === '$lt' ||
68+
key === '$lte') &&
69+
!isPrimitiveFilterValue(nestedValue)
70+
) {
71+
return `Operator "${key}" at "${path.join('.')}" must use a primitive value.`;
72+
}
73+
7274

7375
const nestedError = validateMetadataFilterValue(nestedValue, [...path, key]);
7476
if (nestedError) {

src/server/namespace-router.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export function rankNamespacesByQuery(
5656
namespaces: NamespaceInfo[],
5757
topN: number
5858
): RankedNamespace[] {
59+
const limit = Math.max(1, Math.floor(topN));
5960
return namespaces
6061
.map((ns) => {
6162
const fields = Object.keys(ns.metadata ?? {});
@@ -73,5 +74,5 @@ export function rankNamespacesByQuery(
7374
// targeted namespaces are chosen over large catch-all ones.
7475
return a.record_count - b.record_count;
7576
})
76-
.slice(0, topN);
77+
.slice(0, limit);
7778
}

src/server/url-generation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ function generatorMailing(metadata: Record<string, unknown>): UrlGenerationResul
3030
};
3131
}
3232
return {
33-
url: `https://lists.boost.org/archives/list/${docIdOrThread}/`,
33+
url: `https://lists.boost.org/archives/list/${encodeURIComponent(docIdOrThread)}/`,
3434
method: 'generated.mailing',
3535
};
3636
}

0 commit comments

Comments
 (0)