@bunbase-ae/js 2.13.3-next.300.4a69028 → 2.13.3-next.304.484953e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/admin.ts +10 -8
- package/src/collection.ts +12 -8
- package/src/types.ts +4 -2
package/package.json
CHANGED
package/src/admin.ts
CHANGED
|
@@ -650,23 +650,25 @@ class AdminCollectionsClient {
|
|
|
650
650
|
if (opts.includeDeleted) params.include_deleted = "true";
|
|
651
651
|
if (opts.search) params.search = opts.search;
|
|
652
652
|
if (opts.filter) {
|
|
653
|
+
// Encode filters as a single ?filter=[{field,op,value}, …] JSON array.
|
|
654
|
+
// See buildQueryString in collection.ts for the rationale (issue #533):
|
|
655
|
+
// the bracket form silently corrupts values containing commas.
|
|
656
|
+
const fieldFilters: { field: string; op: string; value: unknown }[] = [];
|
|
653
657
|
for (const [key, value] of Object.entries(opts.filter)) {
|
|
654
658
|
if (value === undefined || value === null) continue;
|
|
655
|
-
if (
|
|
656
|
-
|
|
659
|
+
if (Array.isArray(value)) {
|
|
660
|
+
fieldFilters.push({ field: key, op: "in", value });
|
|
661
|
+
} else if (typeof value === "object") {
|
|
657
662
|
for (const [op, opVal] of Object.entries(value as Record<string, unknown>)) {
|
|
658
663
|
if (opVal !== undefined && opVal !== null) {
|
|
659
|
-
|
|
664
|
+
fieldFilters.push({ field: key, op, value: opVal });
|
|
660
665
|
}
|
|
661
666
|
}
|
|
662
|
-
} else if (Array.isArray(value)) {
|
|
663
|
-
// Array shorthand: { stage: ["a", "b"] } → filter[stage][in]=a,b
|
|
664
|
-
params[`filter[${key}][in]`] = value.join(",");
|
|
665
667
|
} else {
|
|
666
|
-
|
|
667
|
-
params[`filter[${key}]`] = String(value);
|
|
668
|
+
fieldFilters.push({ field: key, op: "eq", value });
|
|
668
669
|
}
|
|
669
670
|
}
|
|
671
|
+
if (fieldFilters.length) params.filter = JSON.stringify(fieldFilters);
|
|
670
672
|
}
|
|
671
673
|
return this.http.request<AdminListResult<T & AdminRecord>>(
|
|
672
674
|
"GET",
|
package/src/collection.ts
CHANGED
|
@@ -161,24 +161,28 @@ export function buildQueryString<T extends Record<string, unknown> = Record<stri
|
|
|
161
161
|
const params: Record<string, string> = {};
|
|
162
162
|
|
|
163
163
|
if (query.filter) {
|
|
164
|
+
// Encode filters as a single ?filter=[{field,op,value}, …] JSON array.
|
|
165
|
+
// The bracket form (?filter[field][op]=value) joins array values on ",", which
|
|
166
|
+
// silently corrupts any value containing a comma — see issue #533. The JSON
|
|
167
|
+
// form preserves array values verbatim and is parsed by the server's
|
|
168
|
+
// parseFilterJson (apps/server/src/routes/_filterParams.ts).
|
|
169
|
+
const fieldFilters: { field: string; op: string; value: unknown }[] = [];
|
|
164
170
|
for (const [field, value] of Object.entries(query.filter)) {
|
|
165
171
|
if (value === undefined || value === null) continue;
|
|
166
172
|
|
|
167
|
-
if (
|
|
168
|
-
|
|
173
|
+
if (Array.isArray(value)) {
|
|
174
|
+
fieldFilters.push({ field, op: "in", value });
|
|
175
|
+
} else if (typeof value === "object") {
|
|
169
176
|
for (const [op, opVal] of Object.entries(value as Record<string, unknown>)) {
|
|
170
177
|
if (opVal !== undefined && opVal !== null) {
|
|
171
|
-
|
|
178
|
+
fieldFilters.push({ field, op, value: opVal });
|
|
172
179
|
}
|
|
173
180
|
}
|
|
174
|
-
} else if (Array.isArray(value)) {
|
|
175
|
-
// Array shorthand: { stage: ["a", "b"] } → filter[stage][in]=a,b
|
|
176
|
-
params[`filter[${field}][in]`] = value.join(",");
|
|
177
181
|
} else {
|
|
178
|
-
|
|
179
|
-
params[`filter[${field}]`] = String(value);
|
|
182
|
+
fieldFilters.push({ field, op: "eq", value });
|
|
180
183
|
}
|
|
181
184
|
}
|
|
185
|
+
if (fieldFilters.length) params.filter = JSON.stringify(fieldFilters);
|
|
182
186
|
}
|
|
183
187
|
|
|
184
188
|
if (query.sort) params.sort = query.sort;
|
package/src/types.ts
CHANGED
|
@@ -166,8 +166,10 @@ export type FilterFieldValue<V> = V | FilterArrayShorthandValue<V> | FilterOpera
|
|
|
166
166
|
* filter: { rfid_tag: { in: ["a", "b"] } }
|
|
167
167
|
* filter: { score: { gte: 0, lte: 100 } }
|
|
168
168
|
*/
|
|
169
|
-
//
|
|
170
|
-
//
|
|
169
|
+
// Wire format: a single ?filter=[{field,op,value}, …] JSON entry.
|
|
170
|
+
// Simple { status: "published" } → [{ field: "status", op: "eq", value: "published" }]
|
|
171
|
+
// Operator { age: { gte: 18 } } → [{ field: "age", op: "gte", value: 18 }]
|
|
172
|
+
// Array { id: ["a", "b"] } → [{ field: "id", op: "in", value: ["a", "b"] }]
|
|
171
173
|
export type Filter<T = Record<string, unknown>> = {
|
|
172
174
|
[K in Exclude<keyof T, keyof BunBaseRecord>]?: FilterFieldValue<T[K]>;
|
|
173
175
|
} & {
|