sensemaking 0.7.2 → 0.9.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/README.md +90 -61
- package/dist/cjs/cli/check.js +367 -0
- package/dist/cjs/cli/check.js.map +1 -0
- package/dist/cjs/{commands → cli}/index.js +2 -2
- package/dist/cjs/cli/index.js.map +1 -0
- package/dist/cjs/{commands → cli}/init.js +3 -0
- package/dist/cjs/cli/init.js.map +1 -0
- package/dist/cjs/{commands → cli}/map.js +2 -2
- package/dist/cjs/cli/map.js.map +1 -0
- package/dist/cjs/{commands → cli}/named.d.cts +1 -1
- package/dist/cjs/{commands → cli}/named.d.ts +1 -1
- package/dist/cjs/cli/named.js +219 -0
- package/dist/cjs/cli/named.js.map +1 -0
- package/dist/cjs/{commands → cli}/peek.js +2 -2
- package/dist/cjs/cli/peek.js.map +1 -0
- package/dist/cjs/cli/query.js.map +1 -0
- package/dist/cjs/cli/rebuild.js.map +1 -0
- package/dist/cjs/cli/search.d.cts +3 -0
- package/dist/cjs/cli/search.d.ts +3 -0
- package/dist/cjs/{commands/find.js → cli/search.js} +9 -8
- package/dist/cjs/cli/search.js.map +1 -0
- package/dist/cjs/{commands → cli}/shared.d.cts +1 -0
- package/dist/{esm/commands → cjs/cli}/shared.d.ts +1 -0
- package/dist/cjs/{commands → cli}/shared.js +9 -0
- package/dist/cjs/cli/shared.js.map +1 -0
- package/dist/cjs/{commands → cli}/status.js +36 -13
- package/dist/cjs/cli/status.js.map +1 -0
- package/dist/cjs/{commands → cli}/types.d.cts +3 -1
- package/dist/{esm/commands → cjs/cli}/types.d.ts +3 -1
- package/dist/cjs/cli/watch.js.map +1 -0
- package/dist/cjs/cli.js +42 -17
- package/dist/cjs/cli.js.map +1 -1
- package/dist/{esm/verbs.d.ts → cjs/commands.d.cts} +15 -5
- package/dist/cjs/{verbs.d.cts → commands.d.ts} +15 -5
- package/dist/cjs/{verbs.js → commands.js} +329 -39
- package/dist/cjs/commands.js.map +1 -0
- package/dist/cjs/config.d.cts +45 -12
- package/dist/cjs/config.d.ts +45 -12
- package/dist/cjs/config.js +464 -125
- package/dist/cjs/config.js.map +1 -1
- package/dist/cjs/db.d.cts +1 -1
- package/dist/cjs/db.d.ts +1 -1
- package/dist/cjs/db.js +293 -76
- package/dist/cjs/db.js.map +1 -1
- package/dist/cjs/errors.d.cts +1 -1
- package/dist/cjs/errors.d.ts +1 -1
- package/dist/cjs/errors.js.map +1 -1
- package/dist/cjs/features/embed.js +19 -3
- package/dist/cjs/features/embed.js.map +1 -1
- package/dist/cjs/features/links.js +201 -24
- package/dist/cjs/features/links.js.map +1 -1
- package/dist/cjs/features/rank.js +8 -1
- package/dist/cjs/features/rank.js.map +1 -1
- package/dist/cjs/features/types.d.cts +12 -4
- package/dist/cjs/features/types.d.ts +12 -4
- package/dist/cjs/index.d.cts +3 -3
- package/dist/cjs/index.d.ts +3 -3
- package/dist/cjs/index.js +9 -6
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/output.d.cts +16 -0
- package/dist/cjs/output.d.ts +16 -0
- package/dist/cjs/output.js +27 -5
- package/dist/cjs/output.js.map +1 -1
- package/dist/cjs/progress.d.cts +5 -0
- package/dist/cjs/progress.d.ts +5 -0
- package/dist/cjs/progress.js +54 -0
- package/dist/cjs/progress.js.map +1 -0
- package/dist/cjs/scan.d.cts +4 -0
- package/dist/cjs/scan.d.ts +4 -0
- package/dist/cjs/scan.js +87 -6
- package/dist/cjs/scan.js.map +1 -1
- package/dist/esm/{commands → cli}/check.js +41 -22
- package/dist/esm/cli/check.js.map +1 -0
- package/dist/esm/{commands → cli}/index.js +1 -1
- package/dist/esm/cli/index.js.map +1 -0
- package/dist/esm/{commands → cli}/init.js +3 -0
- package/dist/esm/cli/init.js.map +1 -0
- package/dist/esm/{commands → cli}/map.js +1 -1
- package/dist/esm/cli/map.js.map +1 -0
- package/dist/esm/{commands → cli}/named.d.ts +1 -1
- package/dist/esm/cli/named.js +41 -0
- package/dist/esm/cli/named.js.map +1 -0
- package/dist/esm/{commands → cli}/peek.js +1 -1
- package/dist/esm/cli/peek.js.map +1 -0
- package/dist/esm/cli/query.js.map +1 -0
- package/dist/esm/cli/rebuild.js.map +1 -0
- package/dist/esm/cli/search.d.ts +3 -0
- package/dist/esm/cli/search.js +16 -0
- package/dist/esm/cli/search.js.map +1 -0
- package/dist/{cjs/commands → esm/cli}/shared.d.ts +1 -0
- package/dist/esm/{commands → cli}/shared.js +9 -0
- package/dist/esm/cli/shared.js.map +1 -0
- package/dist/esm/{commands → cli}/status.js +17 -11
- package/dist/esm/cli/status.js.map +1 -0
- package/dist/{cjs/commands → esm/cli}/types.d.ts +3 -1
- package/dist/esm/cli/types.js.map +1 -0
- package/dist/esm/cli/watch.js.map +1 -0
- package/dist/esm/cli.js +24 -6
- package/dist/esm/cli.js.map +1 -1
- package/dist/{cjs/verbs.d.ts → esm/commands.d.ts} +15 -5
- package/dist/esm/commands.js +386 -0
- package/dist/esm/commands.js.map +1 -0
- package/dist/esm/config.d.ts +45 -12
- package/dist/esm/config.js +367 -93
- package/dist/esm/config.js.map +1 -1
- package/dist/esm/db.d.ts +1 -1
- package/dist/esm/db.js +126 -17
- package/dist/esm/db.js.map +1 -1
- package/dist/esm/errors.d.ts +1 -1
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/features/embed.js +18 -2
- package/dist/esm/features/embed.js.map +1 -1
- package/dist/esm/features/links.js +130 -20
- package/dist/esm/features/links.js.map +1 -1
- package/dist/esm/features/rank.js +8 -1
- package/dist/esm/features/rank.js.map +1 -1
- package/dist/esm/features/types.d.ts +12 -4
- package/dist/esm/features/types.js.map +1 -1
- package/dist/esm/index.d.ts +3 -3
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/output.d.ts +16 -0
- package/dist/esm/output.js +20 -5
- package/dist/esm/output.js.map +1 -1
- package/dist/esm/progress.d.ts +5 -0
- package/dist/esm/progress.js +44 -0
- package/dist/esm/progress.js.map +1 -0
- package/dist/esm/scan.d.ts +4 -0
- package/dist/esm/scan.js +37 -6
- package/dist/esm/scan.js.map +1 -1
- package/package.json +12 -2
- package/schema.json +85 -50
- package/skills/sense/EXAMPLES.md +16 -12
- package/skills/sense/SKILL.md +74 -55
- package/skills/sense-setup/EXAMPLES.md +121 -0
- package/skills/sense-setup/SKILL.md +73 -54
- package/dist/cjs/commands/check.js +0 -143
- package/dist/cjs/commands/check.js.map +0 -1
- package/dist/cjs/commands/find.d.cts +0 -3
- package/dist/cjs/commands/find.d.ts +0 -3
- package/dist/cjs/commands/find.js.map +0 -1
- package/dist/cjs/commands/index.js.map +0 -1
- package/dist/cjs/commands/init.js.map +0 -1
- package/dist/cjs/commands/map.js.map +0 -1
- package/dist/cjs/commands/named.js +0 -23
- package/dist/cjs/commands/named.js.map +0 -1
- package/dist/cjs/commands/peek.js.map +0 -1
- package/dist/cjs/commands/query.js.map +0 -1
- package/dist/cjs/commands/rebuild.js.map +0 -1
- package/dist/cjs/commands/shared.js.map +0 -1
- package/dist/cjs/commands/status.js.map +0 -1
- package/dist/cjs/commands/watch.js.map +0 -1
- package/dist/cjs/verbs.js.map +0 -1
- package/dist/esm/commands/check.js.map +0 -1
- package/dist/esm/commands/find.d.ts +0 -3
- package/dist/esm/commands/find.js +0 -15
- package/dist/esm/commands/find.js.map +0 -1
- package/dist/esm/commands/index.js.map +0 -1
- package/dist/esm/commands/init.js.map +0 -1
- package/dist/esm/commands/map.js.map +0 -1
- package/dist/esm/commands/named.js +0 -12
- package/dist/esm/commands/named.js.map +0 -1
- package/dist/esm/commands/peek.js.map +0 -1
- package/dist/esm/commands/query.js.map +0 -1
- package/dist/esm/commands/rebuild.js.map +0 -1
- package/dist/esm/commands/shared.js.map +0 -1
- package/dist/esm/commands/status.js.map +0 -1
- package/dist/esm/commands/types.js.map +0 -1
- package/dist/esm/commands/watch.js.map +0 -1
- package/dist/esm/verbs.js +0 -190
- package/dist/esm/verbs.js.map +0 -1
- /package/dist/cjs/{commands → cli}/check.d.cts +0 -0
- /package/dist/cjs/{commands → cli}/check.d.ts +0 -0
- /package/dist/cjs/{commands → cli}/index.d.cts +0 -0
- /package/dist/cjs/{commands → cli}/index.d.ts +0 -0
- /package/dist/cjs/{commands → cli}/init.d.cts +0 -0
- /package/dist/cjs/{commands → cli}/init.d.ts +0 -0
- /package/dist/cjs/{commands → cli}/map.d.cts +0 -0
- /package/dist/cjs/{commands → cli}/map.d.ts +0 -0
- /package/dist/cjs/{commands → cli}/peek.d.cts +0 -0
- /package/dist/cjs/{commands → cli}/peek.d.ts +0 -0
- /package/dist/cjs/{commands → cli}/query.d.cts +0 -0
- /package/dist/cjs/{commands → cli}/query.d.ts +0 -0
- /package/dist/cjs/{commands → cli}/query.js +0 -0
- /package/dist/cjs/{commands → cli}/rebuild.d.cts +0 -0
- /package/dist/cjs/{commands → cli}/rebuild.d.ts +0 -0
- /package/dist/cjs/{commands → cli}/rebuild.js +0 -0
- /package/dist/cjs/{commands → cli}/status.d.cts +0 -0
- /package/dist/cjs/{commands → cli}/status.d.ts +0 -0
- /package/dist/cjs/{commands → cli}/types.js +0 -0
- /package/dist/cjs/{commands → cli}/types.js.map +0 -0
- /package/dist/cjs/{commands → cli}/watch.d.cts +0 -0
- /package/dist/cjs/{commands → cli}/watch.d.ts +0 -0
- /package/dist/cjs/{commands → cli}/watch.js +0 -0
- /package/dist/esm/{commands → cli}/check.d.ts +0 -0
- /package/dist/esm/{commands → cli}/index.d.ts +0 -0
- /package/dist/esm/{commands → cli}/init.d.ts +0 -0
- /package/dist/esm/{commands → cli}/map.d.ts +0 -0
- /package/dist/esm/{commands → cli}/peek.d.ts +0 -0
- /package/dist/esm/{commands → cli}/query.d.ts +0 -0
- /package/dist/esm/{commands → cli}/query.js +0 -0
- /package/dist/esm/{commands → cli}/rebuild.d.ts +0 -0
- /package/dist/esm/{commands → cli}/rebuild.js +0 -0
- /package/dist/esm/{commands → cli}/status.d.ts +0 -0
- /package/dist/esm/{commands → cli}/types.js +0 -0
- /package/dist/esm/{commands → cli}/watch.d.ts +0 -0
- /package/dist/esm/{commands → cli}/watch.js +0 -0
package/dist/cjs/db.js
CHANGED
|
@@ -38,22 +38,57 @@ var _nodefs = require("node:fs");
|
|
|
38
38
|
var _nodepath = require("node:path");
|
|
39
39
|
var _nodesqlite = require("node:sqlite");
|
|
40
40
|
var _configts = require("./config.js");
|
|
41
|
+
var _errorsts = require("./errors.js");
|
|
41
42
|
var _indexts = require("./features/index.js");
|
|
43
|
+
var _progressts = require("./progress.js");
|
|
42
44
|
var _scants = require("./scan.js");
|
|
43
45
|
function _array_like_to_array(arr, len) {
|
|
44
46
|
if (len == null || len > arr.length) len = arr.length;
|
|
45
47
|
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
|
46
48
|
return arr2;
|
|
47
49
|
}
|
|
50
|
+
function _array_with_holes(arr) {
|
|
51
|
+
if (Array.isArray(arr)) return arr;
|
|
52
|
+
}
|
|
48
53
|
function _array_without_holes(arr) {
|
|
49
54
|
if (Array.isArray(arr)) return _array_like_to_array(arr);
|
|
50
55
|
}
|
|
51
56
|
function _iterable_to_array(iter) {
|
|
52
57
|
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
|
|
53
58
|
}
|
|
59
|
+
function _iterable_to_array_limit(arr, i) {
|
|
60
|
+
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
|
|
61
|
+
if (_i == null) return;
|
|
62
|
+
var _arr = [];
|
|
63
|
+
var _n = true;
|
|
64
|
+
var _d = false;
|
|
65
|
+
var _s, _e;
|
|
66
|
+
try {
|
|
67
|
+
for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
|
|
68
|
+
_arr.push(_s.value);
|
|
69
|
+
if (i && _arr.length === i) break;
|
|
70
|
+
}
|
|
71
|
+
} catch (err) {
|
|
72
|
+
_d = true;
|
|
73
|
+
_e = err;
|
|
74
|
+
} finally{
|
|
75
|
+
try {
|
|
76
|
+
if (!_n && _i["return"] != null) _i["return"]();
|
|
77
|
+
} finally{
|
|
78
|
+
if (_d) throw _e;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return _arr;
|
|
82
|
+
}
|
|
83
|
+
function _non_iterable_rest() {
|
|
84
|
+
throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
85
|
+
}
|
|
54
86
|
function _non_iterable_spread() {
|
|
55
87
|
throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
56
88
|
}
|
|
89
|
+
function _sliced_to_array(arr, i) {
|
|
90
|
+
return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
|
|
91
|
+
}
|
|
57
92
|
function _to_consumable_array(arr) {
|
|
58
93
|
return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
|
|
59
94
|
}
|
|
@@ -65,8 +100,20 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
65
100
|
if (n === "Map" || n === "Set") return Array.from(n);
|
|
66
101
|
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
|
|
67
102
|
}
|
|
103
|
+
// path/_mtime/_size are core: every reparse legitimately rewrites them. Every other
|
|
104
|
+
// RESERVED_COLUMNS entry that shows up as a real frontmatter column (currently only
|
|
105
|
+
// rank's `_rank`) is feature-owned -- scan.ts already refuses to let frontmatter set it,
|
|
106
|
+
// so it must never appear in the upsert below, or a reparse would blow its last computed
|
|
107
|
+
// value away with NULL on every touch, not just the reconciles that recompute it.
|
|
108
|
+
var CORE_FRONTMATTER_COLUMNS = new Set([
|
|
109
|
+
'path',
|
|
110
|
+
'_mtime',
|
|
111
|
+
'_size'
|
|
112
|
+
]);
|
|
68
113
|
var DB_FILENAME = 'cache.db';
|
|
69
|
-
var SCHEMA_VERSION = '
|
|
114
|
+
var SCHEMA_VERSION = '8';
|
|
115
|
+
// SQLite's compile-time SQLITE_MAX_COLUMN, default 2000 (https://www.sqlite.org/limits.html).
|
|
116
|
+
var MAX_FRONTMATTER_COLUMNS = 2000;
|
|
70
117
|
function quoteIdent(name) {
|
|
71
118
|
return '"'.concat(name.split('"').join('""'), '"');
|
|
72
119
|
}
|
|
@@ -105,6 +152,14 @@ function getColumns(db) {
|
|
|
105
152
|
function ensureSchema(db, cfg) {
|
|
106
153
|
db.exec('CREATE TABLE IF NOT EXISTS frontmatter ("path" TEXT PRIMARY KEY, "_mtime" REAL, "_size" INTEGER)');
|
|
107
154
|
db.exec("CREATE VIRTUAL TABLE IF NOT EXISTS content USING fts5(title, summary, text, path UNINDEXED, tokenize = 'porter unicode61')");
|
|
155
|
+
// Coverage, not ownership: a path can appear under several presets. Rebuilt per-file
|
|
156
|
+
// alongside frontmatter/content at reconcile so status/map can report matched/embedded
|
|
157
|
+
// counts per preset without recomputing globs at read time.
|
|
158
|
+
// path leads the PK so the per-doc delete in reconcile is an index hit -- keyed the other
|
|
159
|
+
// way it scans the whole table per doc, which made cold builds quadratic (measured 3x cost
|
|
160
|
+
// per note-count doubling at 13k/26k). Coverage-by-preset reads get their own index.
|
|
161
|
+
db.exec('CREATE TABLE IF NOT EXISTS preset_files ("path" TEXT, preset TEXT, PRIMARY KEY ("path", preset))');
|
|
162
|
+
db.exec('CREATE INDEX IF NOT EXISTS preset_files_preset ON preset_files(preset)');
|
|
108
163
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
109
164
|
try {
|
|
110
165
|
for(var _iterator = (0, _indexts.activeFeatures)(cfg)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
@@ -173,16 +228,26 @@ function reconcile(db, cfg, baseDir) {
|
|
|
173
228
|
var newColumns = [];
|
|
174
229
|
var parsedDocs = [];
|
|
175
230
|
var warnings = [];
|
|
231
|
+
// Bulk reparses (a sync, a cold build) are the long silences a query can hit; short
|
|
232
|
+
// reconciles stay silent (progress() has a threshold).
|
|
233
|
+
var report = (0, _progressts.progress)('reparsing files', toReparse.length);
|
|
234
|
+
var parsedCount = 0;
|
|
176
235
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
177
236
|
try {
|
|
178
|
-
|
|
237
|
+
var _loop = function() {
|
|
179
238
|
var file = _step.value;
|
|
180
239
|
var _warnings;
|
|
181
|
-
|
|
240
|
+
// A doc only gets extract/store from features that apply to it (currently: embed, via
|
|
241
|
+
// FileStat.embed -- true iff a covering preset has semantic on).
|
|
242
|
+
var fileFeatures = features.filter(function(feature) {
|
|
243
|
+
return !feature.enabledForFile || feature.enabledForFile(cfg, file);
|
|
244
|
+
});
|
|
245
|
+
var _parseFile = (0, _scants.parseFile)(file, fileFeatures), doc = _parseFile.doc, fileWarnings = _parseFile.warnings;
|
|
246
|
+
report.tick(++parsedCount);
|
|
182
247
|
(_warnings = warnings).push.apply(_warnings, _to_consumable_array(fileWarnings));
|
|
183
|
-
var
|
|
248
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
184
249
|
try {
|
|
185
|
-
for(var
|
|
250
|
+
for(var _iterator = Object.keys(doc.data)[Symbol.iterator](), _step1; !(_iteratorNormalCompletion = (_step1 = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
186
251
|
var key = _step1.value;
|
|
187
252
|
if (!seenColumns.has(key)) {
|
|
188
253
|
seenColumns.add(key);
|
|
@@ -190,21 +255,22 @@ function reconcile(db, cfg, baseDir) {
|
|
|
190
255
|
}
|
|
191
256
|
}
|
|
192
257
|
} catch (err) {
|
|
193
|
-
|
|
194
|
-
|
|
258
|
+
_didIteratorError = true;
|
|
259
|
+
_iteratorError = err;
|
|
195
260
|
} finally{
|
|
196
261
|
try {
|
|
197
|
-
if (!
|
|
198
|
-
|
|
262
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
263
|
+
_iterator.return();
|
|
199
264
|
}
|
|
200
265
|
} finally{
|
|
201
|
-
if (
|
|
202
|
-
throw
|
|
266
|
+
if (_didIteratorError) {
|
|
267
|
+
throw _iteratorError;
|
|
203
268
|
}
|
|
204
269
|
}
|
|
205
270
|
}
|
|
206
271
|
parsedDocs.push(doc);
|
|
207
|
-
}
|
|
272
|
+
};
|
|
273
|
+
for(var _iterator = toReparse[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true)_loop();
|
|
208
274
|
} catch (err) {
|
|
209
275
|
_didIteratorError = true;
|
|
210
276
|
_iteratorError = err;
|
|
@@ -219,90 +285,129 @@ function reconcile(db, cfg, baseDir) {
|
|
|
219
285
|
}
|
|
220
286
|
}
|
|
221
287
|
}
|
|
288
|
+
report.finish();
|
|
222
289
|
var allColumns = _to_consumable_array(seenColumns);
|
|
223
|
-
|
|
290
|
+
// Fence before ALTERing: SQLite's own failure past this point is a raw
|
|
291
|
+
// "too many columns on sqlite_altertab_frontmatter" with no indication of the boundary or the levers.
|
|
292
|
+
if (allColumns.length > MAX_FRONTMATTER_COLUMNS) {
|
|
293
|
+
throw new _errorsts.SenseError('COLUMN_LIMIT', "frontmatter would need ".concat(allColumns.length, " columns, crossing SQLite's compile-time SQLITE_MAX_COLUMN limit (default ").concat(MAX_FRONTMATTER_COLUMNS, "; see https://www.sqlite.org/limits.html). Narrow the presets' include globs so fewer/other files are indexed, or fix whatever is generating unbounded frontmatter keys."));
|
|
294
|
+
}
|
|
295
|
+
// Columns the frontmatter upsert actually writes: core + parsed frontmatter keys, never a
|
|
296
|
+
// feature-owned reserved column (see CORE_FRONTMATTER_COLUMNS above).
|
|
297
|
+
var writableColumns = allColumns.filter(function(c) {
|
|
298
|
+
return CORE_FRONTMATTER_COLUMNS.has(c) || !_scants.RESERVED_COLUMNS.has(c);
|
|
299
|
+
});
|
|
300
|
+
// ON CONFLICT UPDATE (not OR REPLACE) keeps the row's rowid stable across reparses --
|
|
301
|
+
// content rows are coupled to that rowid below.
|
|
302
|
+
var insertSql = "INSERT INTO frontmatter (".concat(writableColumns.map(quoteIdent).join(', '), ") VALUES (").concat(writableColumns.map(function() {
|
|
224
303
|
return '?';
|
|
225
|
-
}).join(', '),
|
|
304
|
+
}).join(', '), ') ON CONFLICT("path") DO UPDATE SET ').concat(writableColumns.filter(function(c) {
|
|
305
|
+
return c !== 'path';
|
|
306
|
+
}).map(function(c) {
|
|
307
|
+
return "".concat(quoteIdent(c), " = excluded.").concat(quoteIdent(c));
|
|
308
|
+
}).join(', '));
|
|
309
|
+
var added = toReparse.filter(function(f) {
|
|
310
|
+
return !existing.has(f.relPath);
|
|
311
|
+
}).map(function(f) {
|
|
312
|
+
return f.relPath;
|
|
313
|
+
});
|
|
314
|
+
var delta = {
|
|
315
|
+
files: files,
|
|
316
|
+
reparsed: parsedDocs.map(function(d) {
|
|
317
|
+
return d.relPath;
|
|
318
|
+
}),
|
|
319
|
+
added: added,
|
|
320
|
+
vanished: vanished
|
|
321
|
+
};
|
|
322
|
+
var txStart = Date.now();
|
|
226
323
|
db.exec('BEGIN');
|
|
227
324
|
try {
|
|
228
325
|
var _feature_afterReconcile;
|
|
229
|
-
var
|
|
326
|
+
var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
|
|
230
327
|
try {
|
|
231
|
-
for(var
|
|
232
|
-
var col =
|
|
328
|
+
for(var _iterator1 = newColumns[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
|
|
329
|
+
var col = _step1.value;
|
|
233
330
|
db.exec("ALTER TABLE frontmatter ADD COLUMN ".concat(quoteIdent(col)));
|
|
234
331
|
}
|
|
235
332
|
} catch (err) {
|
|
236
|
-
|
|
237
|
-
|
|
333
|
+
_didIteratorError1 = true;
|
|
334
|
+
_iteratorError1 = err;
|
|
238
335
|
} finally{
|
|
239
336
|
try {
|
|
240
|
-
if (!
|
|
241
|
-
|
|
337
|
+
if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
|
|
338
|
+
_iterator1.return();
|
|
242
339
|
}
|
|
243
340
|
} finally{
|
|
244
|
-
if (
|
|
245
|
-
throw
|
|
341
|
+
if (_didIteratorError1) {
|
|
342
|
+
throw _iteratorError1;
|
|
246
343
|
}
|
|
247
344
|
}
|
|
248
345
|
}
|
|
249
|
-
// FTS5 has no upsert, so delete-before-insert into `content
|
|
250
|
-
|
|
346
|
+
// FTS5 has no upsert, so delete-before-insert into `content`; coupled to the
|
|
347
|
+
// frontmatter rowid (indexed via its PRIMARY KEY) instead of the UNINDEXED `path`
|
|
348
|
+
// column, which a per-row DELETE would otherwise scan the whole table to find.
|
|
349
|
+
var delBody = db.prepare('DELETE FROM content WHERE rowid = (SELECT rowid FROM frontmatter WHERE "path" = ?)');
|
|
350
|
+
var delPresetFiles = db.prepare('DELETE FROM preset_files WHERE "path" = ?');
|
|
351
|
+
var insertPresetFile = db.prepare('INSERT INTO preset_files ("path", preset) VALUES (?, ?)');
|
|
251
352
|
if (vanished.length > 0) {
|
|
252
353
|
var del = db.prepare('DELETE FROM frontmatter WHERE "path" = ?');
|
|
253
|
-
var
|
|
354
|
+
var _iteratorNormalCompletion2 = true, _didIteratorError2 = false, _iteratorError2 = undefined;
|
|
254
355
|
try {
|
|
255
|
-
for(var
|
|
256
|
-
var path =
|
|
356
|
+
for(var _iterator2 = vanished[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true){
|
|
357
|
+
var path = _step2.value;
|
|
257
358
|
var _feature_remove;
|
|
258
|
-
|
|
359
|
+
// content delete must run first: it looks up the frontmatter rowid by path, which
|
|
360
|
+
// the frontmatter delete below would otherwise have already removed.
|
|
259
361
|
delBody.run(path);
|
|
260
|
-
|
|
362
|
+
del.run(path);
|
|
363
|
+
delPresetFiles.run(path);
|
|
364
|
+
var _iteratorNormalCompletion3 = true, _didIteratorError3 = false, _iteratorError3 = undefined;
|
|
261
365
|
try {
|
|
262
|
-
for(var
|
|
263
|
-
var feature =
|
|
264
|
-
(_feature_remove = feature.remove) === null || _feature_remove === void 0 ? void 0 : _feature_remove.call(feature, db, path);
|
|
366
|
+
for(var _iterator3 = features[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true){
|
|
367
|
+
var feature = _step3.value;
|
|
368
|
+
(_feature_remove = feature.remove) === null || _feature_remove === void 0 ? void 0 : _feature_remove.call(feature, db, path, delta);
|
|
265
369
|
}
|
|
266
370
|
} catch (err) {
|
|
267
|
-
|
|
268
|
-
|
|
371
|
+
_didIteratorError3 = true;
|
|
372
|
+
_iteratorError3 = err;
|
|
269
373
|
} finally{
|
|
270
374
|
try {
|
|
271
|
-
if (!
|
|
272
|
-
|
|
375
|
+
if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
|
|
376
|
+
_iterator3.return();
|
|
273
377
|
}
|
|
274
378
|
} finally{
|
|
275
|
-
if (
|
|
276
|
-
throw
|
|
379
|
+
if (_didIteratorError3) {
|
|
380
|
+
throw _iteratorError3;
|
|
277
381
|
}
|
|
278
382
|
}
|
|
279
383
|
}
|
|
280
384
|
}
|
|
281
385
|
} catch (err) {
|
|
282
|
-
|
|
283
|
-
|
|
386
|
+
_didIteratorError2 = true;
|
|
387
|
+
_iteratorError2 = err;
|
|
284
388
|
} finally{
|
|
285
389
|
try {
|
|
286
|
-
if (!
|
|
287
|
-
|
|
390
|
+
if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
|
|
391
|
+
_iterator2.return();
|
|
288
392
|
}
|
|
289
393
|
} finally{
|
|
290
|
-
if (
|
|
291
|
-
throw
|
|
394
|
+
if (_didIteratorError2) {
|
|
395
|
+
throw _iteratorError2;
|
|
292
396
|
}
|
|
293
397
|
}
|
|
294
398
|
}
|
|
295
399
|
}
|
|
296
400
|
if (parsedDocs.length > 0) {
|
|
297
401
|
var insert = db.prepare(insertSql);
|
|
298
|
-
var insertBody = db.prepare('INSERT INTO content (title, summary, text, "path") VALUES (?, ?, ?, ?)');
|
|
299
|
-
var
|
|
402
|
+
var insertBody = db.prepare('INSERT INTO content (rowid, title, summary, text, "path") VALUES ((SELECT rowid FROM frontmatter WHERE "path" = ?), ?, ?, ?, ?)');
|
|
403
|
+
var _iteratorNormalCompletion4 = true, _didIteratorError4 = false, _iteratorError4 = undefined;
|
|
300
404
|
try {
|
|
301
|
-
var
|
|
302
|
-
var doc =
|
|
303
|
-
var
|
|
405
|
+
var _loop1 = function() {
|
|
406
|
+
var doc = _step4.value;
|
|
407
|
+
var // Frontmatter upsert first: content's rowid lookup below depends on this row existing.
|
|
408
|
+
_insert;
|
|
304
409
|
var _feature_store;
|
|
305
|
-
var values =
|
|
410
|
+
var values = writableColumns.map(function(col) {
|
|
306
411
|
var _doc_data_col;
|
|
307
412
|
if (col === 'path') return doc.relPath;
|
|
308
413
|
if (col === '_mtime') return doc.mtimeMs;
|
|
@@ -310,9 +415,9 @@ function reconcile(db, cfg, baseDir) {
|
|
|
310
415
|
return (_doc_data_col = doc.data[col]) !== null && _doc_data_col !== void 0 ? _doc_data_col : null;
|
|
311
416
|
});
|
|
312
417
|
(_insert = insert).run.apply(_insert, _to_consumable_array(values));
|
|
313
|
-
// Delete-before-insert only for docs that have rows: an FTS5 DELETE by
|
|
314
|
-
//
|
|
315
|
-
//
|
|
418
|
+
// Delete-before-insert only for docs that have rows: an FTS5 DELETE by rowid on a
|
|
419
|
+
// cold build (empty table, nothing to delete) is wasted work, and doing it
|
|
420
|
+
// unconditionally previously made the crawl quadratic when it scanned by column --
|
|
316
421
|
// measured 4x time per note-count doubling at 13k/26k notes.
|
|
317
422
|
if (existing.has(doc.relPath)) {
|
|
318
423
|
var _feature_remove;
|
|
@@ -321,7 +426,7 @@ function reconcile(db, cfg, baseDir) {
|
|
|
321
426
|
try {
|
|
322
427
|
for(var _iterator = features[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
323
428
|
var feature = _step.value;
|
|
324
|
-
(_feature_remove = feature.remove) === null || _feature_remove === void 0 ? void 0 : _feature_remove.call(feature, db, doc.relPath);
|
|
429
|
+
(_feature_remove = feature.remove) === null || _feature_remove === void 0 ? void 0 : _feature_remove.call(feature, db, doc.relPath, delta);
|
|
325
430
|
}
|
|
326
431
|
} catch (err) {
|
|
327
432
|
_didIteratorError = true;
|
|
@@ -338,12 +443,17 @@ function reconcile(db, cfg, baseDir) {
|
|
|
338
443
|
}
|
|
339
444
|
}
|
|
340
445
|
}
|
|
341
|
-
insertBody.run(doc.search.title, doc.search.summary, doc.search.text, doc.relPath);
|
|
446
|
+
insertBody.run(doc.relPath, doc.search.title, doc.search.summary, doc.search.text, doc.relPath);
|
|
447
|
+
// Coverage is glob-derived, not content-derived, but only reparsed/added docs are
|
|
448
|
+
// touched here: a preset edit changes featureSignature and forces a full rebuild
|
|
449
|
+
// (see open()), so an unchanged doc's coverage is already correct on disk. New docs
|
|
450
|
+
// have no rows to clear -- skipping the delete keeps cold builds linear.
|
|
451
|
+
if (existing.has(doc.relPath)) delPresetFiles.run(doc.relPath);
|
|
342
452
|
var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
|
|
343
453
|
try {
|
|
344
|
-
for(var _iterator1 =
|
|
345
|
-
var
|
|
346
|
-
|
|
454
|
+
for(var _iterator1 = doc.presets[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
|
|
455
|
+
var presetName = _step1.value;
|
|
456
|
+
insertPresetFile.run(doc.relPath, presetName);
|
|
347
457
|
}
|
|
348
458
|
} catch (err) {
|
|
349
459
|
_didIteratorError1 = true;
|
|
@@ -359,40 +469,60 @@ function reconcile(db, cfg, baseDir) {
|
|
|
359
469
|
}
|
|
360
470
|
}
|
|
361
471
|
}
|
|
472
|
+
var _iteratorNormalCompletion2 = true, _didIteratorError2 = false, _iteratorError2 = undefined;
|
|
473
|
+
try {
|
|
474
|
+
for(var _iterator2 = features[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true){
|
|
475
|
+
var feature1 = _step2.value;
|
|
476
|
+
(_feature_store = feature1.store) === null || _feature_store === void 0 ? void 0 : _feature_store.call(feature1, db, doc.relPath, doc.extracted[feature1.name], delta);
|
|
477
|
+
}
|
|
478
|
+
} catch (err) {
|
|
479
|
+
_didIteratorError2 = true;
|
|
480
|
+
_iteratorError2 = err;
|
|
481
|
+
} finally{
|
|
482
|
+
try {
|
|
483
|
+
if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
|
|
484
|
+
_iterator2.return();
|
|
485
|
+
}
|
|
486
|
+
} finally{
|
|
487
|
+
if (_didIteratorError2) {
|
|
488
|
+
throw _iteratorError2;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
}
|
|
362
492
|
};
|
|
363
|
-
for(var
|
|
493
|
+
for(var _iterator4 = parsedDocs[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true)_loop1();
|
|
364
494
|
} catch (err) {
|
|
365
|
-
|
|
366
|
-
|
|
495
|
+
_didIteratorError4 = true;
|
|
496
|
+
_iteratorError4 = err;
|
|
367
497
|
} finally{
|
|
368
498
|
try {
|
|
369
|
-
if (!
|
|
370
|
-
|
|
499
|
+
if (!_iteratorNormalCompletion4 && _iterator4.return != null) {
|
|
500
|
+
_iterator4.return();
|
|
371
501
|
}
|
|
372
502
|
} finally{
|
|
373
|
-
if (
|
|
374
|
-
throw
|
|
503
|
+
if (_didIteratorError4) {
|
|
504
|
+
throw _iteratorError4;
|
|
375
505
|
}
|
|
376
506
|
}
|
|
377
507
|
}
|
|
378
508
|
}
|
|
379
|
-
var
|
|
509
|
+
var _iteratorNormalCompletion5 = true, _didIteratorError5 = false, _iteratorError5 = undefined;
|
|
380
510
|
try {
|
|
381
|
-
for(var
|
|
382
|
-
var feature1 =
|
|
383
|
-
(_feature_afterReconcile = feature1.afterReconcile) === null || _feature_afterReconcile === void 0 ? void 0 : _feature_afterReconcile.call(feature1, db,
|
|
511
|
+
for(var _iterator5 = features[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true){
|
|
512
|
+
var feature1 = _step5.value;
|
|
513
|
+
(_feature_afterReconcile = feature1.afterReconcile) === null || _feature_afterReconcile === void 0 ? void 0 : _feature_afterReconcile.call(feature1, db, delta);
|
|
384
514
|
}
|
|
385
515
|
} catch (err) {
|
|
386
|
-
|
|
387
|
-
|
|
516
|
+
_didIteratorError5 = true;
|
|
517
|
+
_iteratorError5 = err;
|
|
388
518
|
} finally{
|
|
389
519
|
try {
|
|
390
|
-
if (!
|
|
391
|
-
|
|
520
|
+
if (!_iteratorNormalCompletion5 && _iterator5.return != null) {
|
|
521
|
+
_iterator5.return();
|
|
392
522
|
}
|
|
393
523
|
} finally{
|
|
394
|
-
if (
|
|
395
|
-
throw
|
|
524
|
+
if (_didIteratorError5) {
|
|
525
|
+
throw _iteratorError5;
|
|
396
526
|
}
|
|
397
527
|
}
|
|
398
528
|
}
|
|
@@ -401,12 +531,84 @@ function reconcile(db, cfg, baseDir) {
|
|
|
401
531
|
db.exec('ROLLBACK');
|
|
402
532
|
throw err;
|
|
403
533
|
}
|
|
534
|
+
// Reconcile's own write-transaction duration, for open()'s derived busy_timeout (F):
|
|
535
|
+
// keep the observed max so a big watcher reconcile's lock hold is what the next open bounds its wait against.
|
|
536
|
+
var durationMs = Date.now() - txStart;
|
|
537
|
+
var prevRaw = getMeta(db, 'reconcile_max_ms');
|
|
538
|
+
// -1, not 0, so a genuinely 0ms first reconcile (sub-millisecond, common on a tiny tree)
|
|
539
|
+
// still gets recorded instead of losing to the "nothing recorded yet" default.
|
|
540
|
+
var prevMax = prevRaw === null ? -1 : Number(prevRaw);
|
|
541
|
+
if (durationMs > prevMax) setMeta(db, 'reconcile_max_ms', String(durationMs));
|
|
404
542
|
return {
|
|
405
543
|
parsed: parsedDocs.length,
|
|
406
544
|
warnings: warnings
|
|
407
545
|
};
|
|
408
546
|
}
|
|
547
|
+
// Names what moved between two feature signatures (see config.featureSignature's format:
|
|
548
|
+
// global features, embed provider, then one segment per preset) for the rebuild notice.
|
|
549
|
+
function signatureDiff(before, after) {
|
|
550
|
+
// Segment keys: `features`, `embed`, `preset:<name>` (config.featureSignature's format).
|
|
551
|
+
var keyOf = function keyOf(part) {
|
|
552
|
+
return part.startsWith('preset:') ? part.split(':').slice(0, 2).join(':') : part.split(':')[0];
|
|
553
|
+
};
|
|
554
|
+
var parse = function parse(sig) {
|
|
555
|
+
return new Map(sig.split('|').map(function(part) {
|
|
556
|
+
return [
|
|
557
|
+
keyOf(part),
|
|
558
|
+
part
|
|
559
|
+
];
|
|
560
|
+
}));
|
|
561
|
+
};
|
|
562
|
+
var a = parse(before);
|
|
563
|
+
var b = parse(after);
|
|
564
|
+
var changed = new Set();
|
|
565
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
566
|
+
try {
|
|
567
|
+
for(var _iterator = b[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
568
|
+
var _step_value = _sliced_to_array(_step.value, 2), key = _step_value[0], val = _step_value[1];
|
|
569
|
+
if (a.get(key) !== val) changed.add(key);
|
|
570
|
+
}
|
|
571
|
+
} catch (err) {
|
|
572
|
+
_didIteratorError = true;
|
|
573
|
+
_iteratorError = err;
|
|
574
|
+
} finally{
|
|
575
|
+
try {
|
|
576
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
577
|
+
_iterator.return();
|
|
578
|
+
}
|
|
579
|
+
} finally{
|
|
580
|
+
if (_didIteratorError) {
|
|
581
|
+
throw _iteratorError;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
|
|
586
|
+
try {
|
|
587
|
+
for(var _iterator1 = a.keys()[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
|
|
588
|
+
var key1 = _step1.value;
|
|
589
|
+
if (!b.has(key1)) changed.add(key1);
|
|
590
|
+
}
|
|
591
|
+
} catch (err) {
|
|
592
|
+
_didIteratorError1 = true;
|
|
593
|
+
_iteratorError1 = err;
|
|
594
|
+
} finally{
|
|
595
|
+
try {
|
|
596
|
+
if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
|
|
597
|
+
_iterator1.return();
|
|
598
|
+
}
|
|
599
|
+
} finally{
|
|
600
|
+
if (_didIteratorError1) {
|
|
601
|
+
throw _iteratorError1;
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
var label = function label(key) {
|
|
606
|
+
return key === 'embed' ? 'embed settings' : key.startsWith('preset:') ? 'preset "'.concat(key.slice(7), '"') : 'features';
|
|
607
|
+
};
|
|
608
|
+
return changed.size === 0 ? 'features' : _to_consumable_array(changed).map(label).join(', ');
|
|
609
|
+
}
|
|
409
610
|
function open(cfg) {
|
|
611
|
+
var _getMeta;
|
|
410
612
|
var stateDir = (0, _nodepath.join)(cfg.baseDir, _configts.STATE_DIR);
|
|
411
613
|
(0, _nodefs.mkdirSync)(stateDir, {
|
|
412
614
|
recursive: true
|
|
@@ -427,6 +629,14 @@ function open(cfg) {
|
|
|
427
629
|
var features = getMeta(db, 'features');
|
|
428
630
|
var wantFeatures = (0, _configts.featureSignature)(cfg);
|
|
429
631
|
if (version !== null && version !== SCHEMA_VERSION || features !== null && features !== wantFeatures) {
|
|
632
|
+
// Indexing derives from presets, so a config edit rebuilding the cache must say so and
|
|
633
|
+
// name what changed -- silent rebuilds make derived indexing look like a hang or a bug.
|
|
634
|
+
if (version !== null && version !== SCHEMA_VERSION) {
|
|
635
|
+
console.error('sense: cache format changed (new sensemaking version); rebuilding the index');
|
|
636
|
+
} else {
|
|
637
|
+
var changed = signatureDiff(features !== null && features !== void 0 ? features : '', wantFeatures);
|
|
638
|
+
console.error("sense: config change (".concat(changed, ") rebuilds the index"));
|
|
639
|
+
}
|
|
430
640
|
db.close();
|
|
431
641
|
(0, _nodefs.rmSync)(stateDir, {
|
|
432
642
|
recursive: true,
|
|
@@ -435,6 +645,13 @@ function open(cfg) {
|
|
|
435
645
|
return open(cfg);
|
|
436
646
|
}
|
|
437
647
|
ensureSchema(db, cfg);
|
|
648
|
+
// Derived from reconcile's own recorded max (F): 3x the largest reconcile this cache has
|
|
649
|
+
// ever held its write transaction for, floored at the 30s default and capped at 10min so
|
|
650
|
+
// one pathological build can't pin every later open to an unbounded wait. Installed
|
|
651
|
+
// before reconcile() below -- this open's own reconcile is exactly the operation that
|
|
652
|
+
// races a concurrent watcher's transaction and needs the derived wait.
|
|
653
|
+
var recordedMaxMs = Number((_getMeta = getMeta(db, 'reconcile_max_ms')) !== null && _getMeta !== void 0 ? _getMeta : '0');
|
|
654
|
+
db.exec("PRAGMA busy_timeout = ".concat(Math.min(Math.max(30000, 3 * recordedMaxMs), 600000)));
|
|
438
655
|
var _reconcile = reconcile(db, cfg, cfg.baseDir), parsed = _reconcile.parsed, warnings = _reconcile.warnings;
|
|
439
656
|
return {
|
|
440
657
|
db: db,
|