@mastra/clickhouse 1.15.2 → 1.16.0-alpha.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @mastra/clickhouse
2
2
 
3
+ ## 1.16.0-alpha.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Added support for filtering scores by metadata key-value pairs in listScores. ([#22047](https://github.com/mastra-ai/mastra/pull/22047))
8
+
9
+ ```typescript
10
+ const result = await storage.listScores({
11
+ filters: { metadata: { env: 'prod' } },
12
+ });
13
+ ```
14
+
15
+ Each top-level metadata key is matched with exact equality against the stored value. Nested objects and arrays compare structurally (key order doesn't matter) with no partial/subset matching, and an empty metadata filter is a no-op.
16
+
17
+ ### Patch Changes
18
+
19
+ - Updated dependencies [[`e737014`](https://github.com/mastra-ai/mastra/commit/e737014e0fc7035759762bb5b48baef1d6c0f6a7), [`d6ce34a`](https://github.com/mastra-ai/mastra/commit/d6ce34aeceb06ddf3d595a1eed5cc74f481a46a1), [`e6f8450`](https://github.com/mastra-ai/mastra/commit/e6f845074d478527026b18d85031b23353e1d0a4)]:
20
+ - @mastra/core@1.62.0-alpha.2
21
+
3
22
  ## 1.15.2
4
23
 
5
24
  ### Patch Changes
@@ -3,7 +3,7 @@ name: mastra-clickhouse
3
3
  description: Documentation for @mastra/clickhouse. Use when working with @mastra/clickhouse APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/clickhouse"
6
- version: "1.15.2"
6
+ version: "1.16.0-alpha.0"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.15.2",
2
+ "version": "1.16.0-alpha.0",
3
3
  "package": "@mastra/clickhouse",
4
4
  "exports": {},
5
5
  "modules": {}
package/dist/index.cjs CHANGED
@@ -4381,6 +4381,64 @@ function addStringMapFilters(column, values, keyPrefix, valuePrefix, out) {
4381
4381
  }
4382
4382
  }
4383
4383
  /**
4384
+ * Adds conditions asserting the JSON value at `pathRefs` inside `src` deep-equals `value`.
4385
+ *
4386
+ * Scalars (string/number/boolean/null) use type-checked typed extraction. Objects and
4387
+ * arrays are decomposed recursively into per-leaf comparisons plus length checks, so
4388
+ * nested values match structurally regardless of key serialization order while still
4389
+ * requiring complete (exact, not partial) equality — mirroring the in-memory
4390
+ * deep-equality semantics.
4391
+ */
4392
+ function addJsonValueConditions(src, pathRefs, value, valuePrefix, nextId, out) {
4393
+ const path = pathRefs.join(", ");
4394
+ if (value === null || value === void 0) out.conditions.push(`JSONHas(${src}, ${path}) AND JSONType(${src}, ${path}) = 'Null'`);
4395
+ else if (typeof value === "string") {
4396
+ const p = `${valuePrefix}_${nextId()}`;
4397
+ out.conditions.push(`JSONType(${src}, ${path}) = 'String' AND JSONExtractString(${src}, ${path}) = {${p}:String}`);
4398
+ out.params[p] = value;
4399
+ } else if (typeof value === "number") {
4400
+ const p = `${valuePrefix}_${nextId()}`;
4401
+ out.conditions.push(`JSONType(${src}, ${path}) IN ('Int64', 'UInt64', 'Double') AND JSONExtractFloat(${src}, ${path}) = {${p}:Float64}`);
4402
+ out.params[p] = value;
4403
+ } else if (typeof value === "boolean") {
4404
+ const p = `${valuePrefix}_${nextId()}`;
4405
+ out.conditions.push(`JSONType(${src}, ${path}) = 'Bool' AND JSONExtractBool(${src}, ${path}) = {${p}:UInt8}`);
4406
+ out.params[p] = value ? 1 : 0;
4407
+ } else if (Array.isArray(value)) {
4408
+ out.conditions.push(`JSONType(${src}, ${path}) = 'Array' AND JSONLength(${src}, ${path}) = ${value.length}`);
4409
+ value.forEach((item, idx) => {
4410
+ addJsonValueConditions(src, [...pathRefs, String(idx + 1)], item, valuePrefix, nextId, out);
4411
+ });
4412
+ } else {
4413
+ const entries = Object.entries(value).filter(([, v]) => v !== void 0);
4414
+ out.conditions.push(`JSONType(${src}, ${path}) = 'Object' AND JSONLength(${src}, ${path}) = ${entries.length}`);
4415
+ for (const [subKey, subValue] of entries) {
4416
+ const p = `${valuePrefix}_k_${nextId()}`;
4417
+ out.params[p] = subKey;
4418
+ addJsonValueConditions(src, [...pathRefs, `{${p}:String}`], subValue, valuePrefix, nextId, out);
4419
+ }
4420
+ }
4421
+ }
4422
+ /**
4423
+ * Adds key/value filters against a JSON-encoded string column (e.g. scores.metadata).
4424
+ * Emits predicates per requested key with exact-value deep equality for any JSON value,
4425
+ * mirroring the in-memory deep-equality semantics (structural, key-order independent).
4426
+ */
4427
+ function addJsonStringFilters(column, values, keyPrefix, valuePrefix, out) {
4428
+ if (values == null || typeof values !== "object") return;
4429
+ let id = 0;
4430
+ const nextId = () => id++;
4431
+ let i = 0;
4432
+ for (const [rawKey, rawValue] of Object.entries(values)) {
4433
+ if (rawValue === void 0) continue;
4434
+ const keyParam = `${keyPrefix}_${i}`;
4435
+ const src = `ifNull(${column}, '{}')`;
4436
+ out.params[keyParam] = rawKey;
4437
+ addJsonValueConditions(src, [`{${keyParam}:String}`], rawValue, valuePrefix, nextId, out);
4438
+ i++;
4439
+ }
4440
+ }
4441
+ /**
4384
4442
  * Adds shared context filter conditions (commonFilterFields) to the output.
4385
4443
  * Used by logs, metrics, scores, and feedback filter builders.
4386
4444
  */
@@ -4493,6 +4551,7 @@ function buildScoresFilterConditions(filters, tableAlias) {
4493
4551
  addEq(col("scoreSource"), filters.scoreSource, "scoreSource", "String", out);
4494
4552
  if (typeof filters.scorerId === "string") addEq(col("scorerId"), filters.scorerId, "scorerId", "String", out);
4495
4553
  else if (Array.isArray(filters.scorerId)) addIn(col("scorerId"), filters.scorerId, "scorerIds", out);
4554
+ addJsonStringFilters(col("metadata"), filters.metadata, "score_meta_k", "score_meta_v", out);
4496
4555
  return out;
4497
4556
  }
4498
4557
  function buildFeedbackFilterConditions(filters, tableAlias) {