sensemaking 0.23.0 → 0.23.1

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.
Files changed (39) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/store/batch.d.cts +4 -0
  3. package/dist/cjs/store/batch.d.ts +4 -0
  4. package/dist/cjs/store/batch.js +80 -0
  5. package/dist/cjs/store/batch.js.map +1 -0
  6. package/dist/cjs/store/duckdb/batch.d.cts +0 -4
  7. package/dist/cjs/store/duckdb/batch.d.ts +0 -4
  8. package/dist/cjs/store/duckdb/batch.js +5 -27
  9. package/dist/cjs/store/duckdb/batch.js.map +1 -1
  10. package/dist/cjs/store/turso/connection.d.cts +3 -0
  11. package/dist/cjs/store/turso/connection.d.ts +3 -0
  12. package/dist/cjs/store/turso/connection.js +300 -30
  13. package/dist/cjs/store/turso/connection.js.map +1 -1
  14. package/dist/cjs/store/turso/native.d.cts +4 -0
  15. package/dist/cjs/store/turso/native.d.ts +4 -0
  16. package/dist/cjs/store/turso/native.js +9 -0
  17. package/dist/cjs/store/turso/native.js.map +1 -1
  18. package/dist/cjs/store/turso/open.js +81 -8
  19. package/dist/cjs/store/turso/open.js.map +1 -1
  20. package/dist/cjs/store/turso/store.js +103 -1
  21. package/dist/cjs/store/turso/store.js.map +1 -1
  22. package/dist/esm/store/batch.d.ts +4 -0
  23. package/dist/esm/store/batch.js +21 -0
  24. package/dist/esm/store/batch.js.map +1 -0
  25. package/dist/esm/store/duckdb/batch.d.ts +0 -4
  26. package/dist/esm/store/duckdb/batch.js +2 -19
  27. package/dist/esm/store/duckdb/batch.js.map +1 -1
  28. package/dist/esm/store/turso/connection.d.ts +3 -0
  29. package/dist/esm/store/turso/connection.js +58 -3
  30. package/dist/esm/store/turso/connection.js.map +1 -1
  31. package/dist/esm/store/turso/native.d.ts +4 -0
  32. package/dist/esm/store/turso/native.js +8 -0
  33. package/dist/esm/store/turso/native.js.map +1 -1
  34. package/dist/esm/store/turso/open.js +5 -5
  35. package/dist/esm/store/turso/open.js.map +1 -1
  36. package/dist/esm/store/turso/store.js +29 -2
  37. package/dist/esm/store/turso/store.js.map +1 -1
  38. package/package.json +1 -1
  39. package/skills/sense-setup/SKILL.md +1 -1
package/README.md CHANGED
@@ -93,7 +93,7 @@ ORDER BY bm25(content, 10.0, 5.0, 1.0) LIMIT 10
93
93
  |---|---|
94
94
  | `presets` | named bundles of `include`/`exclude` globs, `k` (result count), `signals` (which engines this scope searches with, `words`, `links`, `vectors`; every signal whose prerequisites hold, unless the preset lists them exhaustively), `where` (a standing SQL filter). A file is indexed if any preset includes it, embedded if a model is named and some covering preset's `signals` include `vectors`; `status` shows each preset's coverage. |
95
95
  | `embed` | the model vectors are built with. Naming one gives the tree vectors; omitting the block means none at all, whatever the presets say. `sense download` fetches it. |
96
- | `store` | backing store engine: `sqlite` (default, zero-dependency, Node's built-in SQLite), or the experimental `duckdb` and `turso`. The first command that opens such a tree installs that engine's package on its own (`@duckdb/node-api`, a one-time native download of ~110 MB; `@tursodatabase/database`, much smaller). The same commands and table names run on all three; what does not port is FTS5 syntax. Under `duckdb` and `turso`, `search` text and raw `MATCH` reject FTS5's prefix (`foo*`), boolean (`AND`/`OR`/`NOT`), `NEAR`, initial-token (`^`), and column-filter (`title:foo`) operators with a named error that says how to rephrase or set `store` to `sqlite`; bare words and quoted phrases work on all three. Raw `sql` is a per-store dialect: the tables are portable, but sqlite's FTS5 `MATCH`/`snippet()`/`bm25()` do not run under `duckdb` or `turso`, so saved queries written in FTS5 syntax are sqlite dialect, and `has`/`basename`/`segment` are registered on `sqlite` and `duckdb` but not `turso`, whose client cannot register SQL functions. `sense watch` runs on all three; on `duckdb` and `turso`, which lock the cache file per connection, a concurrent command waits out the watcher's current cycle instead of failing. Each store keeps its own cache file (`.sense/cache.db`, `.sense/cache.duckdb`, `.sense/cache.turso.db`); switching stores is a rebuild, not a migration. Indexing speed is the other axis, and it does not follow from any of the above: sqlite builds a cold index fastest and turso slowest, by a wide margin on a large tree, and no setting closes that gap, since turso's engine costs more per write and more again to maintain each index. What turso buys instead is concurrent writers, non-blocking I/O and encryption, none of which a one-shot command uses, so reach for it for those rather than for speed. Per-store figures: [BENCHMARKING.md](BENCHMARKING.md). |
96
+ | `store` | backing store engine: `sqlite` (default, zero-dependency, Node's built-in SQLite), or the experimental `duckdb` and `turso`. The first command that opens such a tree installs that engine's package on its own (`@duckdb/node-api`, a one-time native download of ~110 MB; `@tursodatabase/database`, much smaller). The same commands and table names run on all three; what does not port is FTS5 syntax. Under `duckdb` and `turso`, `search` text and raw `MATCH` reject FTS5's prefix (`foo*`), boolean (`AND`/`OR`/`NOT`), `NEAR`, initial-token (`^`), and column-filter (`title:foo`) operators with a named error that says how to rephrase or set `store` to `sqlite`; bare words and quoted phrases work on all three. Raw `sql` is a per-store dialect: the tables are portable, but sqlite's FTS5 `MATCH`/`snippet()`/`bm25()` do not run under `duckdb` or `turso`, so saved queries written in FTS5 syntax are sqlite dialect, and `has`/`basename`/`segment` are registered on `sqlite` and `duckdb` but not `turso`, whose client cannot register SQL functions. `sense watch` runs on all three; on `duckdb` and `turso`, which lock the cache file per connection, a concurrent command waits out the watcher's current cycle instead of failing. Each store keeps its own cache file (`.sense/cache.db`, `.sense/cache.duckdb`, `.sense/cache.turso.db`); switching stores is a rebuild, not a migration. Indexing speed is the other axis, and it does not follow from any of the above: sqlite builds a cold index fastest and turso slowest, by a wide margin on a large tree, and no setting closes that gap, since turso's engine costs more per write and more again to maintain each index. What turso buys instead is concurrent access, non-blocking I/O and encryption, so reach for it for those rather than for speed. Per-store figures: [BENCHMARKING.md](BENCHMARKING.md). |
97
97
  | `queries` | entries runnable as `sense <name>`, each naming the verb it runs: `{ sql }` for SQL (`?` binds positional args) or `{ search }` for a ranked search with its settings baked in, so `sense hot` needs no flags. Running an entry validates it: a typo'd column errors and exits nonzero, and a parameterised entry validates with any argument, since preparing precedes binding. |
98
98
  | `version` | schema version; older configs auto-migrate on load, noted on stderr. |
99
99
 
@@ -0,0 +1,4 @@
1
+ export declare function rewriteInsert(sql: string, rowCount: number): {
2
+ sql: string;
3
+ width: number;
4
+ } | null;
@@ -0,0 +1,4 @@
1
+ export declare function rewriteInsert(sql: string, rowCount: number): {
2
+ sql: string;
3
+ width: number;
4
+ } | null;
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "rewriteInsert", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return rewriteInsert;
9
+ }
10
+ });
11
+ function _array_like_to_array(arr, len) {
12
+ if (len == null || len > arr.length) len = arr.length;
13
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
14
+ return arr2;
15
+ }
16
+ function _array_with_holes(arr) {
17
+ if (Array.isArray(arr)) return arr;
18
+ }
19
+ function _iterable_to_array_limit(arr, i) {
20
+ var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
21
+ if (_i == null) return;
22
+ var _arr = [];
23
+ var _n = true;
24
+ var _d = false;
25
+ var _s, _e;
26
+ try {
27
+ for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
28
+ _arr.push(_s.value);
29
+ if (i && _arr.length === i) break;
30
+ }
31
+ } catch (err) {
32
+ _d = true;
33
+ _e = err;
34
+ } finally{
35
+ try {
36
+ if (!_n && _i["return"] != null) _i["return"]();
37
+ } finally{
38
+ if (_d) throw _e;
39
+ }
40
+ }
41
+ return _arr;
42
+ }
43
+ function _non_iterable_rest() {
44
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
45
+ }
46
+ function _sliced_to_array(arr, i) {
47
+ return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
48
+ }
49
+ function _unsupported_iterable_to_array(o, minLen) {
50
+ if (!o) return;
51
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
52
+ var n = Object.prototype.toString.call(o).slice(8, -1);
53
+ if (n === "Object" && o.constructor) n = o.constructor.name;
54
+ if (n === "Map" || n === "Set") return Array.from(n);
55
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
56
+ }
57
+ // Rewrites a single-row parameterized INSERT into one multi-row statement. Engine-neutral string
58
+ // work, shared by duckdb (batch.ts's rewriteBatch) and turso (turso/connection.ts's runBatch).
59
+ var INSERT_RE = RegExp("^(INSERT\\s+(?:OR\\s+\\w+\\s+)?INTO\\s+\\S+\\s*\\([^)]*\\)\\s*VALUES\\s*)\\(([^()]*)\\)(.*)$", "is");
60
+ function placeholderCount(tuple) {
61
+ var _tuple_match;
62
+ return ((_tuple_match = tuple.match(/\?/g)) !== null && _tuple_match !== void 0 ? _tuple_match : []).length;
63
+ }
64
+ function rewriteInsert(sql, rowCount) {
65
+ var m = INSERT_RE.exec(sql.trim());
66
+ if (!m) return null;
67
+ var _m = _sliced_to_array(m, 4), head = _m[1], tuple = _m[2], tail = _m[3];
68
+ var width = placeholderCount(tuple);
69
+ if (width === 0) return null;
70
+ var rows = Array.from({
71
+ length: rowCount
72
+ }, function() {
73
+ return "(".concat(tuple, ")");
74
+ }).join(', ');
75
+ return {
76
+ sql: "".concat(head).concat(rows).concat(tail),
77
+ width: width
78
+ };
79
+ }
80
+ /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/batch.ts"],"sourcesContent":["// Rewrites a single-row parameterized INSERT into one multi-row statement. Engine-neutral string\n// work, shared by duckdb (batch.ts's rewriteBatch) and turso (turso/connection.ts's runBatch).\n\nconst INSERT_RE = /^(INSERT\\s+(?:OR\\s+\\w+\\s+)?INTO\\s+\\S+\\s*\\([^)]*\\)\\s*VALUES\\s*)\\(([^()]*)\\)(.*)$/is;\n\nfunction placeholderCount(tuple: string): number {\n return (tuple.match(/\\?/g) ?? []).length;\n}\n\nexport function rewriteInsert(sql: string, rowCount: number): { sql: string; width: number } | null {\n const m = INSERT_RE.exec(sql.trim());\n if (!m) return null;\n const [, head, tuple, tail] = m;\n const width = placeholderCount(tuple);\n if (width === 0) return null;\n const rows = Array.from({ length: rowCount }, () => `(${tuple})`).join(', ');\n return { sql: `${head}${rows}${tail}`, width };\n}\n"],"names":["rewriteInsert","INSERT_RE","placeholderCount","tuple","match","length","sql","rowCount","m","exec","trim","head","tail","width","rows","Array","from","join"],"mappings":";;;;+BASgBA;;;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAThB,iGAAiG;AACjG,+FAA+F;AAE/F,IAAMC,YAAY;AAElB,SAASC,iBAAiBC,KAAa;QAC7BA;IAAR,OAAO,EAACA,eAAAA,MAAMC,KAAK,CAAC,oBAAZD,0BAAAA,eAAsB,EAAE,EAAEE,MAAM;AAC1C;AAEO,SAASL,cAAcM,GAAW,EAAEC,QAAgB;IACzD,IAAMC,IAAIP,UAAUQ,IAAI,CAACH,IAAII,IAAI;IACjC,IAAI,CAACF,GAAG,OAAO;IACf,IAA8BA,sBAAAA,OAArBG,OAAqBH,OAAfL,QAAeK,OAARI,OAAQJ;IAC9B,IAAMK,QAAQX,iBAAiBC;IAC/B,IAAIU,UAAU,GAAG,OAAO;IACxB,IAAMC,OAAOC,MAAMC,IAAI,CAAC;QAAEX,QAAQE;IAAS,GAAG;eAAM,AAAC,IAAS,OAANJ,OAAM;OAAIc,IAAI,CAAC;IACvE,OAAO;QAAEX,KAAK,AAAC,GAASQ,OAAPH,MAAcC,OAAPE,MAAY,OAALF;QAAQC,OAAAA;IAAM;AAC/C"}
@@ -1,7 +1,3 @@
1
- export declare function rewriteInsert(sql: string, rowCount: number): {
2
- sql: string;
3
- width: number;
4
- } | null;
5
1
  export declare function rewriteUpdate(sql: string, rowCount: number): {
6
2
  sql: string;
7
3
  width: number;
@@ -1,7 +1,3 @@
1
- export declare function rewriteInsert(sql: string, rowCount: number): {
2
- sql: string;
3
- width: number;
4
- } | null;
5
1
  export declare function rewriteUpdate(sql: string, rowCount: number): {
6
2
  sql: string;
7
3
  width: number;
@@ -1,3 +1,6 @@
1
+ // Rewrites the store's single-row parameterized INSERT/UPDATE/DELETE into one multi-row statement --
2
+ // DuckDB's columnar engine pays for row-at-a-time writes, not just the round trip (PRINCIPLES: documented-means-tested).
3
+ // rewriteInsert itself lives in the shared ../batch.ts: turso folds INSERTs the same way (3.36 B).
1
4
  "use strict";
2
5
  Object.defineProperty(exports, "__esModule", {
3
6
  value: true
@@ -15,13 +18,11 @@ _export(exports, {
15
18
  get rewriteDelete () {
16
19
  return rewriteDelete;
17
20
  },
18
- get rewriteInsert () {
19
- return rewriteInsert;
20
- },
21
21
  get rewriteUpdate () {
22
22
  return rewriteUpdate;
23
23
  }
24
24
  });
25
+ var _batchts = require("../batch.js");
25
26
  function _array_like_to_array(arr, len) {
26
27
  if (len == null || len > arr.length) len = arr.length;
27
28
  for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
@@ -82,15 +83,8 @@ function _unsupported_iterable_to_array(o, minLen) {
82
83
  if (n === "Map" || n === "Set") return Array.from(n);
83
84
  if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
84
85
  }
85
- // Rewrites the store's single-row parameterized INSERT/UPDATE/DELETE into one multi-row statement --
86
- // DuckDB's columnar engine pays for row-at-a-time writes, not just the round trip (PRINCIPLES: documented-means-tested).
87
- var INSERT_RE = RegExp("^(INSERT\\s+(?:OR\\s+\\w+\\s+)?INTO\\s+\\S+\\s*\\([^)]*\\)\\s*VALUES\\s*)\\(([^()]*)\\)(.*)$", "is");
88
86
  var UPDATE_RE = RegExp("^UPDATE\\s+(\\S+)\\s+SET\\s+(.+?)\\s+WHERE\\s+(.+)$", "is");
89
87
  var DELETE_RE = RegExp("^DELETE\\s+FROM\\s+(\\S+)\\s+WHERE\\s+(.+)$", "is");
90
- function placeholderCount(tuple) {
91
- var _tuple_match;
92
- return ((_tuple_match = tuple.match(/\?/g)) !== null && _tuple_match !== void 0 ? _tuple_match : []).length;
93
- }
94
88
  // "a = ?, b = ?" or "a = ? AND b = ?" -> ["a", "b"]. A clause that doesn't fit yields a shorter
95
89
  // list, which rewriteUpdate/rewriteDelete reject as a width mismatch.
96
90
  function equalityColumns(clause, sep) {
@@ -134,22 +128,6 @@ function tuples(rowCount, width) {
134
128
  return row;
135
129
  }).join(', ');
136
130
  }
137
- function rewriteInsert(sql, rowCount) {
138
- var m = INSERT_RE.exec(sql.trim());
139
- if (!m) return null;
140
- var _m = _sliced_to_array(m, 4), head = _m[1], tuple = _m[2], tail = _m[3];
141
- var width = placeholderCount(tuple);
142
- if (width === 0) return null;
143
- var rows = Array.from({
144
- length: rowCount
145
- }, function() {
146
- return "(".concat(tuple, ")");
147
- }).join(', ');
148
- return {
149
- sql: "".concat(head).concat(rows).concat(tail),
150
- width: width
151
- };
152
- }
153
131
  function rewriteUpdate(sql, rowCount) {
154
132
  var m = UPDATE_RE.exec(sql.trim());
155
133
  if (!m) return null;
@@ -192,6 +170,6 @@ function rewriteDelete(sql, rowCount) {
192
170
  }
193
171
  function rewriteBatch(sql, rowCount) {
194
172
  var _ref, _rewriteInsert;
195
- return (_ref = (_rewriteInsert = rewriteInsert(sql, rowCount)) !== null && _rewriteInsert !== void 0 ? _rewriteInsert : rewriteUpdate(sql, rowCount)) !== null && _ref !== void 0 ? _ref : rewriteDelete(sql, rowCount);
173
+ return (_ref = (_rewriteInsert = (0, _batchts.rewriteInsert)(sql, rowCount)) !== null && _rewriteInsert !== void 0 ? _rewriteInsert : rewriteUpdate(sql, rowCount)) !== null && _ref !== void 0 ? _ref : rewriteDelete(sql, rowCount);
196
174
  }
197
175
  /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/batch.ts"],"sourcesContent":["// Rewrites the store's single-row parameterized INSERT/UPDATE/DELETE into one multi-row statement --\n// DuckDB's columnar engine pays for row-at-a-time writes, not just the round trip (PRINCIPLES: documented-means-tested).\n\nconst INSERT_RE = /^(INSERT\\s+(?:OR\\s+\\w+\\s+)?INTO\\s+\\S+\\s*\\([^)]*\\)\\s*VALUES\\s*)\\(([^()]*)\\)(.*)$/is;\nconst UPDATE_RE = /^UPDATE\\s+(\\S+)\\s+SET\\s+(.+?)\\s+WHERE\\s+(.+)$/is;\nconst DELETE_RE = /^DELETE\\s+FROM\\s+(\\S+)\\s+WHERE\\s+(.+)$/is;\n\nfunction placeholderCount(tuple: string): number {\n return (tuple.match(/\\?/g) ?? []).length;\n}\n\n// \"a = ?, b = ?\" or \"a = ? AND b = ?\" -> [\"a\", \"b\"]. A clause that doesn't fit yields a shorter\n// list, which rewriteUpdate/rewriteDelete reject as a width mismatch.\nfunction equalityColumns(clause: string, sep: RegExp): string[] | null {\n const parts = clause.split(sep).map((p) => p.trim());\n const cols: string[] = [];\n for (const part of parts) {\n const m = /^(.+?)=\\s*\\?$/.exec(part);\n if (!m) return null;\n cols.push(m[1].trim());\n }\n return cols;\n}\n\nfunction tuples(rowCount: number, width: number): string {\n const row = `(${Array.from({ length: width }, () => '?').join(', ')})`;\n return Array.from({ length: rowCount }, () => row).join(', ');\n}\n\nexport function rewriteInsert(sql: string, rowCount: number): { sql: string; width: number } | null {\n const m = INSERT_RE.exec(sql.trim());\n if (!m) return null;\n const [, head, tuple, tail] = m;\n const width = placeholderCount(tuple);\n if (width === 0) return null;\n const rows = Array.from({ length: rowCount }, () => `(${tuple})`).join(', ');\n return { sql: `${head}${rows}${tail}`, width };\n}\n\nexport function rewriteUpdate(sql: string, rowCount: number): { sql: string; width: number } | null {\n const m = UPDATE_RE.exec(sql.trim());\n if (!m) return null;\n const [, table, setClause, whereClause] = m;\n const setCols = equalityColumns(setClause, /,/);\n const whereCols = equalityColumns(whereClause, /\\bAND\\b/i);\n if (!setCols || !whereCols) return null;\n const dataCols = [...setCols, ...whereCols];\n const setAssign = setCols.map((c) => `${c} = data.${c}`).join(', ');\n const joinCond = whereCols.map((c) => `${table}.${c} = data.${c}`).join(' AND ');\n return { sql: `UPDATE ${table} SET ${setAssign} FROM (VALUES ${tuples(rowCount, dataCols.length)}) AS data(${dataCols.join(', ')}) WHERE ${joinCond}`, width: dataCols.length };\n}\n\nexport function rewriteDelete(sql: string, rowCount: number): { sql: string; width: number } | null {\n const m = DELETE_RE.exec(sql.trim());\n if (!m) return null;\n const [, table, whereClause] = m;\n const cols = equalityColumns(whereClause, /\\bAND\\b/i);\n if (!cols) return null;\n if (cols.length === 1) {\n return { sql: `DELETE FROM ${table} WHERE ${cols[0]} IN (${Array.from({ length: rowCount }, () => '?').join(', ')})`, width: 1 };\n }\n return { sql: `DELETE FROM ${table} WHERE (${cols.join(', ')}) IN (VALUES ${tuples(rowCount, cols.length)})`, width: cols.length };\n}\n\n// Tries each shape in turn; null means the caller should fall back to a per-row loop.\nexport function rewriteBatch(sql: string, rowCount: number): { sql: string; width: number } | null {\n return rewriteInsert(sql, rowCount) ?? rewriteUpdate(sql, rowCount) ?? rewriteDelete(sql, rowCount);\n}\n"],"names":["rewriteBatch","rewriteDelete","rewriteInsert","rewriteUpdate","INSERT_RE","UPDATE_RE","DELETE_RE","placeholderCount","tuple","match","length","equalityColumns","clause","sep","parts","split","map","p","trim","cols","part","m","exec","push","tuples","rowCount","width","row","Array","from","join","sql","head","tail","rows","table","setClause","whereClause","setCols","whereCols","dataCols","setAssign","c","joinCond"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/batch.ts"],"sourcesContent":["// Rewrites the store's single-row parameterized INSERT/UPDATE/DELETE into one multi-row statement --\n// DuckDB's columnar engine pays for row-at-a-time writes, not just the round trip (PRINCIPLES: documented-means-tested).\n// rewriteInsert itself lives in the shared ../batch.ts: turso folds INSERTs the same way (3.36 B).\n\nimport { rewriteInsert } from '../batch.ts';\n\nconst UPDATE_RE = /^UPDATE\\s+(\\S+)\\s+SET\\s+(.+?)\\s+WHERE\\s+(.+)$/is;\nconst DELETE_RE = /^DELETE\\s+FROM\\s+(\\S+)\\s+WHERE\\s+(.+)$/is;\n\n// \"a = ?, b = ?\" or \"a = ? AND b = ?\" -> [\"a\", \"b\"]. A clause that doesn't fit yields a shorter\n// list, which rewriteUpdate/rewriteDelete reject as a width mismatch.\nfunction equalityColumns(clause: string, sep: RegExp): string[] | null {\n const parts = clause.split(sep).map((p) => p.trim());\n const cols: string[] = [];\n for (const part of parts) {\n const m = /^(.+?)=\\s*\\?$/.exec(part);\n if (!m) return null;\n cols.push(m[1].trim());\n }\n return cols;\n}\n\nfunction tuples(rowCount: number, width: number): string {\n const row = `(${Array.from({ length: width }, () => '?').join(', ')})`;\n return Array.from({ length: rowCount }, () => row).join(', ');\n}\n\nexport function rewriteUpdate(sql: string, rowCount: number): { sql: string; width: number } | null {\n const m = UPDATE_RE.exec(sql.trim());\n if (!m) return null;\n const [, table, setClause, whereClause] = m;\n const setCols = equalityColumns(setClause, /,/);\n const whereCols = equalityColumns(whereClause, /\\bAND\\b/i);\n if (!setCols || !whereCols) return null;\n const dataCols = [...setCols, ...whereCols];\n const setAssign = setCols.map((c) => `${c} = data.${c}`).join(', ');\n const joinCond = whereCols.map((c) => `${table}.${c} = data.${c}`).join(' AND ');\n return { sql: `UPDATE ${table} SET ${setAssign} FROM (VALUES ${tuples(rowCount, dataCols.length)}) AS data(${dataCols.join(', ')}) WHERE ${joinCond}`, width: dataCols.length };\n}\n\nexport function rewriteDelete(sql: string, rowCount: number): { sql: string; width: number } | null {\n const m = DELETE_RE.exec(sql.trim());\n if (!m) return null;\n const [, table, whereClause] = m;\n const cols = equalityColumns(whereClause, /\\bAND\\b/i);\n if (!cols) return null;\n if (cols.length === 1) {\n return { sql: `DELETE FROM ${table} WHERE ${cols[0]} IN (${Array.from({ length: rowCount }, () => '?').join(', ')})`, width: 1 };\n }\n return { sql: `DELETE FROM ${table} WHERE (${cols.join(', ')}) IN (VALUES ${tuples(rowCount, cols.length)})`, width: cols.length };\n}\n\n// Tries each shape in turn; null means the caller should fall back to a per-row loop.\nexport function rewriteBatch(sql: string, rowCount: number): { sql: string; width: number } | null {\n return rewriteInsert(sql, rowCount) ?? rewriteUpdate(sql, rowCount) ?? rewriteDelete(sql, rowCount);\n}\n"],"names":["rewriteBatch","rewriteDelete","rewriteUpdate","UPDATE_RE","DELETE_RE","equalityColumns","clause","sep","parts","split","map","p","trim","cols","part","m","exec","push","tuples","rowCount","width","row","Array","from","length","join","sql","table","setClause","whereClause","setCols","whereCols","dataCols","setAssign","c","joinCond","rewriteInsert"],"mappings":"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"}
@@ -1,4 +1,7 @@
1
1
  import type { Database } from '@tursodatabase/database';
2
2
  import type { Connection } from '../types.js';
3
3
  export declare function checkpointWal(db: Database): Promise<void>;
4
+ export declare function cacheFilePath(conn: Connection): Promise<string | null>;
5
+ export declare function fileSize(path: string): Promise<number | null>;
6
+ export declare function reclaimSpace(path: string): Promise<void>;
4
7
  export declare function createConnection(db: Database): Connection;
@@ -1,4 +1,7 @@
1
1
  import type { Database } from '@tursodatabase/database';
2
2
  import type { Connection } from '../types.js';
3
3
  export declare function checkpointWal(db: Database): Promise<void>;
4
+ export declare function cacheFilePath(conn: Connection): Promise<string | null>;
5
+ export declare function fileSize(path: string): Promise<number | null>;
6
+ export declare function reclaimSpace(path: string): Promise<void>;
4
7
  export declare function createConnection(db: Database): Connection;