@mindstudio-ai/agent 0.1.162 → 0.1.164

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 ADDED
@@ -0,0 +1,47 @@
1
+ # Changelog
2
+
3
+ What changed in `@mindstudio-ai/agent`, newest first, each version under its own heading. An entry says what's new, what's fixed, and what changed behavior, with what an app's code should be checked for. An entry whose version npm doesn't have yet is still open: a later change adds to it.
4
+
5
+ Versions before 0.1.163 aren't recorded here.
6
+
7
+ ## 0.1.164
8
+
9
+ ### New
10
+
11
+ - The package carries this changelog, `CHANGELOG.md`, from this version on. Its entries start at 0.1.163.
12
+
13
+ ### Fixed
14
+
15
+ - Filters on a column typed with a named type compile again. A column like `category: DocumentCategory` is stored as a json column. In 0.1.163, `===`, `!==` and `[...].includes(o.category)` with strings on it read the whole table into JS, and `o.category.includes('x')` failed the query with `malformed JSON` once a row held a plain string.
16
+ - `o.field == null` on a json column also matches a row whose text is `null`, which reads back as null. That happens when the string `'null'` was written.
17
+
18
+ ## 0.1.163
19
+
20
+ Published by release v1.0.2832.
21
+
22
+ ### Changed behavior
23
+
24
+ A filter that compiles to SQL now selects exactly the rows its function would in JavaScript, NULL columns included. Before, some compiled to SQL that answered differently, and which answer an app got depended on whether the filter compiled.
25
+
26
+ - `!==` and `!=` keep rows where the column is NULL, as in JS (`null !== 'archived'` is true). They used to drop them. That includes `removeAll`, which now deletes those rows too. Check: a `filter`, `count` or `removeAll` with `!==` on a column that can be empty, where empty rows should be left out. Add `o.status != null &&`.
27
+ - `<`, `<=`, `>` and `>=` give JS's answer for a NULL column: `o.n < 5` keeps a row with no `n`, since `null < 5` is true in JS. So does `!(…)`: `!(o.status === 'a')` keeps empty rows. Check: comparisons on a nullable number column where empty rows should be left out.
28
+ - `o.text.includes('x')` is case-sensitive, as JS's `includes` is, and `_` and `%` in the needle are literal characters. It used to be a case-insensitive SQL `LIKE`, in which a needle holding `_` or `%` matched nothing. Check: a search box written as `o.name.includes(q)` that relies on case-insensitive matching. Keep a lowercased copy of the field and compare `o.nameLower.includes(q.toLowerCase())` with `q` passed in bindings, or use `db.sql()` with `LIKE` (and `ESCAPE`).
29
+ - `o.tags.includes('x')` on a json array column is array membership, as in JS. It used to be a substring of the column's JSON text, so `'x'` also matched `'xy'`.
30
+ - A bare field reads by JS truthiness for its type: `o.name` is false for `''`, `o.count` for `0`, `!o.flag` is true for false and for an empty boolean. They used to compile to `= 1` and `= 0`, which was wrong for text and number columns.
31
+ - A computed `sortBy` (anything but `o => o.field`, such as `o => o.meta.date` or `o => o.name.toLowerCase()`) sorts. It used to be ignored whenever `take()` or `skip()` applied, so `.sortBy(computed).take(10)` returned 10 arbitrary rows. The rows are now sorted in JS after the filter runs in SQL, so `take()` reads every matching row first, and on a large table that can reach `result_too_large`. Check: a computed `sortBy` with `take()` on a table that grows. Sort by a column (`o => o.createdAt`) where you can.
32
+ - With no `sortBy`, `reverse()` and `last()` order by the reverse of the order rows were written in. They used to do nothing, so `last()` returned the first row.
33
+ - A filter SQL can't answer exactly runs in JS over every row instead, with a warning in the logs: a value of another type than its column (`o.amount > '100'`), a relational or loose comparison inside a JSON field (`o.stats.score > 50`, `o.meta.kind == 'x'`), and `.length`. The answer is right; the cost is reading the whole table.
34
+
35
+ ### New
36
+
37
+ - A comparison with a constant expression compiles: `o.createdAt > db.ago(db.days(30))`, `o.createdAt > Date.now() - 90 * 24 * 60 * 60 * 1000`, `o.amount > 50 * 100`. These used to read the whole table into JS.
38
+ - Comparisons compile either way round: `5000 < o.amount`.
39
+ - `.select(...columns)` on a query or table returns only those columns (`SELECT id, name`). Filters and sorts still see the whole row.
40
+ - Reads a method starts together against one database, such as a `Promise.all` of queries, go to the platform as one round trip. Each gets its own results, and identical reads in flight share one answer. `db.batch()` is still the way to run reads and writes together, in order, as one transaction.
41
+ - Every value in a compiled filter is a bound parameter, an `IN` list included, so a query's statement doesn't change with its values.
42
+
43
+ ### Fixed
44
+
45
+ - Filters in a deployed method's bundled code compile. esbuild prints `5000` as `5e3` and `'Zürich'` as `"Z\xFCrich"`, which the compiler couldn't read: a round number of 1,000 or more read the whole table into JS, and a string with a non-ASCII character or an escape matched nothing at all.
46
+ - `skip()` without `take()` failed with a SQL error.
47
+ - `[null, 'a'].includes(o.x)` didn't match rows where the field is empty.