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/config.js
CHANGED
|
@@ -21,6 +21,9 @@ _export(exports, {
|
|
|
21
21
|
get SUPPORTED_CONFIG_VERSION () {
|
|
22
22
|
return SUPPORTED_CONFIG_VERSION;
|
|
23
23
|
},
|
|
24
|
+
get anyPresetEmbeds () {
|
|
25
|
+
return anyPresetEmbeds;
|
|
26
|
+
},
|
|
24
27
|
get embedConfig () {
|
|
25
28
|
return embedConfig;
|
|
26
29
|
},
|
|
@@ -47,6 +50,18 @@ _export(exports, {
|
|
|
47
50
|
},
|
|
48
51
|
get migrateConfig () {
|
|
49
52
|
return migrateConfig;
|
|
53
|
+
},
|
|
54
|
+
get presetNames () {
|
|
55
|
+
return presetNames;
|
|
56
|
+
},
|
|
57
|
+
get presetSemanticEnabled () {
|
|
58
|
+
return presetSemanticEnabled;
|
|
59
|
+
},
|
|
60
|
+
get resolvePreset () {
|
|
61
|
+
return resolvePreset;
|
|
62
|
+
},
|
|
63
|
+
get resolveSearch () {
|
|
64
|
+
return resolveSearch;
|
|
50
65
|
}
|
|
51
66
|
});
|
|
52
67
|
var _nodefs = require("node:fs");
|
|
@@ -148,6 +163,42 @@ function _object_spread_props(target, source) {
|
|
|
148
163
|
}
|
|
149
164
|
return target;
|
|
150
165
|
}
|
|
166
|
+
function _object_without_properties(source, excluded) {
|
|
167
|
+
if (source == null) return {};
|
|
168
|
+
var target = {}, sourceKeys, key, i;
|
|
169
|
+
if (typeof Reflect !== "undefined" && Reflect.ownKeys) {
|
|
170
|
+
sourceKeys = Reflect.ownKeys(Object(source));
|
|
171
|
+
for(i = 0; i < sourceKeys.length; i++){
|
|
172
|
+
key = sourceKeys[i];
|
|
173
|
+
if (excluded.indexOf(key) >= 0) continue;
|
|
174
|
+
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
|
175
|
+
target[key] = source[key];
|
|
176
|
+
}
|
|
177
|
+
return target;
|
|
178
|
+
}
|
|
179
|
+
target = _object_without_properties_loose(source, excluded);
|
|
180
|
+
if (Object.getOwnPropertySymbols) {
|
|
181
|
+
sourceKeys = Object.getOwnPropertySymbols(source);
|
|
182
|
+
for(i = 0; i < sourceKeys.length; i++){
|
|
183
|
+
key = sourceKeys[i];
|
|
184
|
+
if (excluded.indexOf(key) >= 0) continue;
|
|
185
|
+
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
|
186
|
+
target[key] = source[key];
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return target;
|
|
190
|
+
}
|
|
191
|
+
function _object_without_properties_loose(source, excluded) {
|
|
192
|
+
if (source == null) return {};
|
|
193
|
+
var target = {}, sourceKeys = Object.getOwnPropertyNames(source), key, i;
|
|
194
|
+
for(i = 0; i < sourceKeys.length; i++){
|
|
195
|
+
key = sourceKeys[i];
|
|
196
|
+
if (excluded.indexOf(key) >= 0) continue;
|
|
197
|
+
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
|
198
|
+
target[key] = source[key];
|
|
199
|
+
}
|
|
200
|
+
return target;
|
|
201
|
+
}
|
|
151
202
|
function _sliced_to_array(arr, i) {
|
|
152
203
|
return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
|
|
153
204
|
}
|
|
@@ -168,25 +219,39 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
168
219
|
}
|
|
169
220
|
var CONFIG_FILENAME = 'sense.config.json';
|
|
170
221
|
var STATE_DIR = '.sense';
|
|
171
|
-
var SUPPORTED_CONFIG_VERSION =
|
|
172
|
-
// Each feature owns its tables, parse-time extraction, and reconcile step;
|
|
173
|
-
// links/sections/rank are opt-out
|
|
222
|
+
var SUPPORTED_CONFIG_VERSION = 3;
|
|
223
|
+
// Each feature owns its tables, parse-time extraction, and reconcile step; commands degrade when one is off.
|
|
224
|
+
// links/sections/rank are opt-out toggles in the top-level `features` block; embed is not a
|
|
225
|
+
// member of that block -- it is derived from whether any declared preset has semantic on.
|
|
174
226
|
var FEATURE_NAMES = [
|
|
175
227
|
'links',
|
|
176
228
|
'sections',
|
|
177
229
|
'rank',
|
|
178
230
|
'embed'
|
|
179
231
|
];
|
|
180
|
-
|
|
232
|
+
// v1 -> v2 migration only: the features v2 introduced as opt-out (embed was opt-in then).
|
|
233
|
+
var V2_OPT_OUT_NAMES = [
|
|
181
234
|
'links',
|
|
182
235
|
'sections',
|
|
183
236
|
'rank'
|
|
184
237
|
];
|
|
185
238
|
var DEFAULT_EMBED_MODEL = 'minishlab/potion-retrieval-32M';
|
|
239
|
+
function presetNames(cfg) {
|
|
240
|
+
return Object.keys(cfg.presets);
|
|
241
|
+
}
|
|
242
|
+
function presetSemanticEnabled(cfg, name) {
|
|
243
|
+
var _cfg_presets_name;
|
|
244
|
+
return ((_cfg_presets_name = cfg.presets[name]) === null || _cfg_presets_name === void 0 ? void 0 : _cfg_presets_name.semantic) !== false;
|
|
245
|
+
}
|
|
246
|
+
function anyPresetEmbeds(cfg) {
|
|
247
|
+
return presetNames(cfg).some(function(name) {
|
|
248
|
+
return presetSemanticEnabled(cfg, name);
|
|
249
|
+
});
|
|
250
|
+
}
|
|
186
251
|
function featureEnabled(cfg, name) {
|
|
187
|
-
var _cfg_features
|
|
188
|
-
if (name === 'embed') return
|
|
189
|
-
var enabled = ((
|
|
252
|
+
var _cfg_features;
|
|
253
|
+
if (name === 'embed') return anyPresetEmbeds(cfg);
|
|
254
|
+
var enabled = ((_cfg_features = cfg.features) === null || _cfg_features === void 0 ? void 0 : _cfg_features[name]) !== false;
|
|
190
255
|
if (name === 'rank') return enabled && featureEnabled(cfg, 'links');
|
|
191
256
|
return enabled;
|
|
192
257
|
}
|
|
@@ -206,39 +271,166 @@ function featureStates(cfg) {
|
|
|
206
271
|
};
|
|
207
272
|
}
|
|
208
273
|
function embedConfig(cfg) {
|
|
209
|
-
var
|
|
210
|
-
|
|
211
|
-
var e = (
|
|
212
|
-
if (!e) return null;
|
|
213
|
-
var o = e === true ? {} : e;
|
|
274
|
+
var _cfg_embed, _e_model, _e_type;
|
|
275
|
+
if (!anyPresetEmbeds(cfg)) return null;
|
|
276
|
+
var e = (_cfg_embed = cfg.embed) !== null && _cfg_embed !== void 0 ? _cfg_embed : {};
|
|
214
277
|
return {
|
|
215
|
-
model: (
|
|
216
|
-
type: (
|
|
217
|
-
url:
|
|
218
|
-
key:
|
|
278
|
+
model: (_e_model = e.model) !== null && _e_model !== void 0 ? _e_model : DEFAULT_EMBED_MODEL,
|
|
279
|
+
type: (_e_type = e.type) !== null && _e_type !== void 0 ? _e_type : 'static',
|
|
280
|
+
url: e.url,
|
|
281
|
+
key: e.key
|
|
219
282
|
};
|
|
220
283
|
}
|
|
221
284
|
function featureSignature(cfg) {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
var e = embedConfig(cfg);
|
|
225
|
-
return "embed:".concat(e === null || e === void 0 ? void 0 : e.type, ":").concat(e === null || e === void 0 ? void 0 : e.model);
|
|
285
|
+
var globalPart = enabledFeatures(cfg).filter(function(name) {
|
|
286
|
+
return name !== 'embed';
|
|
226
287
|
}).join(',');
|
|
288
|
+
var e = embedConfig(cfg);
|
|
289
|
+
var embedPart = e ? "embed:".concat(e.type, ":").concat(e.model) : 'embed:off';
|
|
290
|
+
// One keyed segment per preset so a rebuild notice can name exactly which preset moved.
|
|
291
|
+
var presetsPart = _to_consumable_array(presetNames(cfg)).sort().map(function(name) {
|
|
292
|
+
var _p_exclude;
|
|
293
|
+
var p = cfg.presets[name];
|
|
294
|
+
var include = _to_consumable_array(p.include).sort().join('+');
|
|
295
|
+
var exclude = _to_consumable_array((_p_exclude = p.exclude) !== null && _p_exclude !== void 0 ? _p_exclude : []).sort().join('+');
|
|
296
|
+
return "preset:".concat(name, ":").concat(include, ":").concat(exclude, ":").concat(p.semantic === false ? 'off' : 'on');
|
|
297
|
+
}).join('|');
|
|
298
|
+
return [
|
|
299
|
+
"features:".concat(globalPart),
|
|
300
|
+
embedPart,
|
|
301
|
+
presetsPart
|
|
302
|
+
].join('|');
|
|
303
|
+
}
|
|
304
|
+
function resolvePreset(cfg, name) {
|
|
305
|
+
var presetName = name !== null && name !== void 0 ? name : 'default';
|
|
306
|
+
var preset = cfg.presets[presetName];
|
|
307
|
+
if (!preset) throw new _errorsts.SenseError('PRESET_UNKNOWN', 'unknown preset "'.concat(presetName, '"; declared presets: ').concat(presetNames(cfg).join(', ')));
|
|
308
|
+
return {
|
|
309
|
+
name: presetName,
|
|
310
|
+
preset: preset
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
function resolveSearch(cfg) {
|
|
314
|
+
var opts = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
|
|
315
|
+
var _ref, _opts_k, _opts_where, _opts_include;
|
|
316
|
+
var _resolvePreset = resolvePreset(cfg, opts.preset), presetName = _resolvePreset.name, preset = _resolvePreset.preset;
|
|
317
|
+
var k = (_ref = (_opts_k = opts.k) !== null && _opts_k !== void 0 ? _opts_k : preset.k) !== null && _ref !== void 0 ? _ref : 10;
|
|
318
|
+
var where = (_opts_where = opts.where) !== null && _opts_where !== void 0 ? _opts_where : preset.where;
|
|
319
|
+
// An explicit include (CLI --include, or a saved search's own `include`) is a full ad hoc
|
|
320
|
+
// scope override -- it replaces the preset's include/exclude pair rather than layering on
|
|
321
|
+
// top of it, the same "replaces, doesn't AND" rule --where already uses.
|
|
322
|
+
var include = (_opts_include = opts.include) !== null && _opts_include !== void 0 ? _opts_include : preset.include;
|
|
323
|
+
var exclude = opts.include ? undefined : preset.exclude;
|
|
324
|
+
var semantic = opts.semantic !== undefined ? opts.semantic : preset.semantic !== false;
|
|
325
|
+
return {
|
|
326
|
+
presetName: presetName,
|
|
327
|
+
k: k,
|
|
328
|
+
where: where,
|
|
329
|
+
include: include,
|
|
330
|
+
exclude: exclude,
|
|
331
|
+
semantic: semantic
|
|
332
|
+
};
|
|
227
333
|
}
|
|
228
334
|
// Pure per-version steps; loadConfig chains them from the file's version up to SUPPORTED_CONFIG_VERSION.
|
|
335
|
+
// Intermediate shapes predate the current Config type (v1 has no features block, v2 has
|
|
336
|
+
// scan/find not presets/search), so steps work loosely-typed and only the final result is cast
|
|
337
|
+
// back to Config.
|
|
229
338
|
var MIGRATIONS = {
|
|
230
339
|
// v1 -> v2: features block introduced, opt-out features enabled (matches the old implicit
|
|
231
340
|
// behavior of `links` etc. not existing). embed stays absent -- opt-in.
|
|
232
341
|
1: function(cfg) {
|
|
233
342
|
return _object_spread_props(_object_spread({}, cfg), {
|
|
234
343
|
version: 2,
|
|
235
|
-
features: Object.fromEntries(
|
|
344
|
+
features: Object.fromEntries(V2_OPT_OUT_NAMES.map(function(name) {
|
|
236
345
|
return [
|
|
237
346
|
name,
|
|
238
347
|
true
|
|
239
348
|
];
|
|
240
349
|
}))
|
|
241
350
|
});
|
|
351
|
+
},
|
|
352
|
+
// v2 -> v3: mechanical-minimal, by decision -- only what keeps an existing config loading.
|
|
353
|
+
// No restructuring, no preset inference, no query rewriting; real trees get hand-migrated
|
|
354
|
+
// separately to actually use presets.
|
|
355
|
+
2: function(cfg) {
|
|
356
|
+
var _prevDefaults_find;
|
|
357
|
+
var scan = cfg.scan, defaults = cfg.defaults, features = cfg.features, checks = cfg.checks, queries = cfg.queries, rest = _object_without_properties(cfg, [
|
|
358
|
+
"scan",
|
|
359
|
+
"defaults",
|
|
360
|
+
"features",
|
|
361
|
+
"checks",
|
|
362
|
+
"queries"
|
|
363
|
+
]);
|
|
364
|
+
var scanInclude = scan.include;
|
|
365
|
+
var nextQueries = {};
|
|
366
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
367
|
+
try {
|
|
368
|
+
for(var _iterator = Object.entries(queries !== null && queries !== void 0 ? queries : {})[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
369
|
+
var _step_value = _sliced_to_array(_step.value, 2), name = _step_value[0], value = _step_value[1];
|
|
370
|
+
if (typeof value === 'string') {
|
|
371
|
+
nextQueries[name] = value;
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
var entry = value;
|
|
375
|
+
var search = {
|
|
376
|
+
search: entry.find
|
|
377
|
+
};
|
|
378
|
+
if (entry.k !== undefined) search.k = entry.k;
|
|
379
|
+
if (entry.where !== undefined) search.where = entry.where;
|
|
380
|
+
// semantic: true was opt-in; it is now the default, so it drops. semantic: false is kept.
|
|
381
|
+
if (entry.semantic === false) search.semantic = false;
|
|
382
|
+
nextQueries[name] = search;
|
|
383
|
+
}
|
|
384
|
+
} catch (err) {
|
|
385
|
+
_didIteratorError = true;
|
|
386
|
+
_iteratorError = err;
|
|
387
|
+
} finally{
|
|
388
|
+
try {
|
|
389
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
390
|
+
_iterator.return();
|
|
391
|
+
}
|
|
392
|
+
} finally{
|
|
393
|
+
if (_didIteratorError) {
|
|
394
|
+
throw _iteratorError;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
var prevDefaults = defaults;
|
|
399
|
+
var defaultWhere = prevDefaults === null || prevDefaults === void 0 ? void 0 : (_prevDefaults_find = prevDefaults.find) === null || _prevDefaults_find === void 0 ? void 0 : _prevDefaults_find.where;
|
|
400
|
+
// features.embed: true/absent -> simply removed (v3 default is on). An explicit `false`
|
|
401
|
+
// becomes semantic: false on every preset this migration produces -- there is only ever
|
|
402
|
+
// one (`default`), since v2 has no notion of multiple scopes, but the rule is written to
|
|
403
|
+
// apply to "every migrated preset" rather than hardcoded to `default` in case a later
|
|
404
|
+
// migration step ever produces more than one.
|
|
405
|
+
var prevFeatures = features !== null && features !== void 0 ? features : {};
|
|
406
|
+
var embedWasOff = prevFeatures.embed === false;
|
|
407
|
+
// Object form carried provider settings (model/type/url/key), not a toggle -- they move
|
|
408
|
+
// to the v3 top-level `embed` block verbatim; dropping them would silently switch an
|
|
409
|
+
// api tree back to the built-in static model.
|
|
410
|
+
var embedProvider = _type_of(prevFeatures.embed) === 'object' && prevFeatures.embed !== null ? prevFeatures.embed : undefined;
|
|
411
|
+
var _embed = prevFeatures.embed, restFeatures = _object_without_properties(prevFeatures, [
|
|
412
|
+
"embed"
|
|
413
|
+
]);
|
|
414
|
+
var defaultPreset = {
|
|
415
|
+
include: scanInclude
|
|
416
|
+
};
|
|
417
|
+
if (defaultWhere !== undefined) defaultPreset.where = defaultWhere;
|
|
418
|
+
if (embedWasOff) defaultPreset.semantic = false;
|
|
419
|
+
// checks (assertions over saved queries) was removed in v3; its queries still run under
|
|
420
|
+
// `queries`, just without the pass/fail assertion -- reachable now only as a saved query.
|
|
421
|
+
if (checks !== undefined) {
|
|
422
|
+
console.error('sense: v2 "checks" was removed in v3 (sense check no longer asserts on saved queries); its queries are carried over under "queries" -- a returned row set is now the reader\'s judgment');
|
|
423
|
+
}
|
|
424
|
+
var result = _object_spread_props(_object_spread({}, rest), {
|
|
425
|
+
version: 3,
|
|
426
|
+
presets: {
|
|
427
|
+
default: defaultPreset
|
|
428
|
+
},
|
|
429
|
+
queries: nextQueries
|
|
430
|
+
});
|
|
431
|
+
if (embedProvider !== undefined) result.embed = embedProvider;
|
|
432
|
+
if (Object.keys(restFeatures).length > 0) result.features = restFeatures;
|
|
433
|
+
return result;
|
|
242
434
|
}
|
|
243
435
|
};
|
|
244
436
|
function migrateConfig(cfg) {
|
|
@@ -259,17 +451,20 @@ function starterConfig() {
|
|
|
259
451
|
return {
|
|
260
452
|
$schema: 'https://unpkg.com/sensemaking/schema.json',
|
|
261
453
|
version: SUPPORTED_CONFIG_VERSION,
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
454
|
+
presets: {
|
|
455
|
+
default: {
|
|
456
|
+
include: [
|
|
457
|
+
'**/*.md'
|
|
458
|
+
],
|
|
459
|
+
k: 10
|
|
460
|
+
},
|
|
461
|
+
large: {
|
|
462
|
+
include: [
|
|
463
|
+
'**/*.md'
|
|
464
|
+
],
|
|
465
|
+
k: 20
|
|
466
|
+
}
|
|
266
467
|
},
|
|
267
|
-
features: Object.fromEntries(OPT_OUT_NAMES.map(function(name) {
|
|
268
|
-
return [
|
|
269
|
-
name,
|
|
270
|
-
true
|
|
271
|
-
];
|
|
272
|
-
})),
|
|
273
468
|
queries: {}
|
|
274
469
|
};
|
|
275
470
|
}
|
|
@@ -293,124 +488,248 @@ function findConfigPath(startDir) {
|
|
|
293
488
|
}
|
|
294
489
|
// Shape check for hand-edited files: a typo'd config fails with a named error, not a
|
|
295
490
|
// TypeError from whatever code touched the missing field first. `queries` is optional
|
|
296
|
-
// on disk (absent = none); `
|
|
297
|
-
//
|
|
298
|
-
//
|
|
299
|
-
//
|
|
300
|
-
//
|
|
491
|
+
// on disk (absent = none); `presets` has no usable default.
|
|
492
|
+
// Unknown top-level keys are reported as a soft warning (cli.ts prints it) rather than an
|
|
493
|
+
// error, so a config carrying a stray field still runs -- but unknown keys inside a preset,
|
|
494
|
+
// features, embed, or saved-query block are hard errors: those blocks are small and fully
|
|
495
|
+
// owned, so a typo there is far more likely a mistake than a forward-compat field.
|
|
301
496
|
var KNOWN_KEYS = new Set([
|
|
302
497
|
'$schema',
|
|
303
498
|
'version',
|
|
304
|
-
'
|
|
499
|
+
'presets',
|
|
305
500
|
'features',
|
|
306
|
-
'
|
|
307
|
-
'checks',
|
|
501
|
+
'embed',
|
|
308
502
|
'queries'
|
|
309
503
|
]);
|
|
310
|
-
var
|
|
311
|
-
'include'
|
|
504
|
+
var KNOWN_PRESET_KEYS = new Set([
|
|
505
|
+
'include',
|
|
506
|
+
'exclude',
|
|
507
|
+
'k',
|
|
508
|
+
'semantic',
|
|
509
|
+
'where'
|
|
510
|
+
]);
|
|
511
|
+
var KNOWN_FEATURE_KEYS = new Set([
|
|
512
|
+
'links',
|
|
513
|
+
'sections',
|
|
514
|
+
'rank'
|
|
515
|
+
]);
|
|
516
|
+
var KNOWN_EMBED_KEYS = new Set([
|
|
517
|
+
'model',
|
|
518
|
+
'type',
|
|
519
|
+
'url',
|
|
520
|
+
'key'
|
|
521
|
+
]);
|
|
522
|
+
var SAVED_SEARCH_KEYS = new Set([
|
|
523
|
+
'search',
|
|
524
|
+
'preset',
|
|
525
|
+
'include',
|
|
526
|
+
'where',
|
|
527
|
+
'k',
|
|
528
|
+
'semantic'
|
|
312
529
|
]);
|
|
313
530
|
function unknownConfigKeys(cfg) {
|
|
314
|
-
|
|
531
|
+
return Object.keys(cfg).filter(function(k) {
|
|
315
532
|
return !KNOWN_KEYS.has(k);
|
|
316
|
-
}).map(function(k) {
|
|
317
|
-
return k;
|
|
318
533
|
});
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
var
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
534
|
+
}
|
|
535
|
+
function isNonEmptyStringArray(value) {
|
|
536
|
+
return Array.isArray(value) && value.length > 0 && value.every(function(g) {
|
|
537
|
+
return typeof g === 'string' && g.length > 0;
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
// Pre-v3 shape check, just enough for migrateConfig to run safely (it reads scan.include
|
|
541
|
+
// directly). The full v3 shape is checked by validateConfig once migration has produced it.
|
|
542
|
+
function validateLegacyScan(parsed, configPath) {
|
|
543
|
+
var cfg = (typeof parsed === "undefined" ? "undefined" : _type_of(parsed)) === 'object' && parsed !== null && !Array.isArray(parsed) ? parsed : null;
|
|
544
|
+
var scan = cfg === null || cfg === void 0 ? void 0 : cfg.scan;
|
|
545
|
+
if (!cfg || !scan || !isNonEmptyStringArray(scan.include)) {
|
|
546
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": scan.include must be a non-empty array of glob strings"));
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
function validateFeaturesBlock(value, configPath) {
|
|
550
|
+
if ((typeof value === "undefined" ? "undefined" : _type_of(value)) !== 'object' || value === null || Array.isArray(value)) {
|
|
551
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": features must be an object of name -> boolean"));
|
|
552
|
+
}
|
|
553
|
+
var block = value;
|
|
554
|
+
var unknown = Object.keys(block).filter(function(k) {
|
|
555
|
+
return !KNOWN_FEATURE_KEYS.has(k);
|
|
556
|
+
});
|
|
557
|
+
if (unknown.length > 0) {
|
|
558
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": features has unknown key(s) ").concat(unknown.join(', '), '; embed is not a features key -- see the top-level "embed" block and each preset\'s "semantic"'));
|
|
559
|
+
}
|
|
560
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
561
|
+
try {
|
|
562
|
+
for(var _iterator = Object.entries(block)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
563
|
+
var _step_value = _sliced_to_array(_step.value, 2), name = _step_value[0], v = _step_value[1];
|
|
564
|
+
if (typeof v !== 'boolean') {
|
|
565
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": features.").concat(name, " must be a boolean"));
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
} catch (err) {
|
|
569
|
+
_didIteratorError = true;
|
|
570
|
+
_iteratorError = err;
|
|
571
|
+
} finally{
|
|
572
|
+
try {
|
|
573
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
574
|
+
_iterator.return();
|
|
575
|
+
}
|
|
576
|
+
} finally{
|
|
577
|
+
if (_didIteratorError) {
|
|
578
|
+
throw _iteratorError;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
function validateEmbedBlock(value, configPath) {
|
|
584
|
+
if ((typeof value === "undefined" ? "undefined" : _type_of(value)) !== 'object' || value === null || Array.isArray(value)) {
|
|
585
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ': embed must be an object of { model?, type?: "static"|"api", url?, key? }'));
|
|
586
|
+
}
|
|
587
|
+
var embed = value;
|
|
588
|
+
var unknown = Object.keys(embed).filter(function(k) {
|
|
589
|
+
return !KNOWN_EMBED_KEYS.has(k);
|
|
590
|
+
});
|
|
591
|
+
if (unknown.length > 0) {
|
|
592
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": embed has unknown key(s) ").concat(unknown.join(', ')));
|
|
593
|
+
}
|
|
594
|
+
if (embed.model !== undefined && typeof embed.model !== 'string') {
|
|
595
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": embed.model must be a string"));
|
|
596
|
+
}
|
|
597
|
+
if (embed.type !== undefined && embed.type !== 'static' && embed.type !== 'api') {
|
|
598
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ': embed.type must be "static" or "api"'));
|
|
599
|
+
}
|
|
600
|
+
if (embed.url !== undefined && typeof embed.url !== 'string') {
|
|
601
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": embed.url must be a string"));
|
|
602
|
+
}
|
|
603
|
+
if (embed.key !== undefined && typeof embed.key !== 'string') {
|
|
604
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": embed.key must be a string"));
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
function validatePreset(name, value, configPath) {
|
|
608
|
+
if ((typeof value === "undefined" ? "undefined" : _type_of(value)) !== 'object' || value === null || Array.isArray(value)) {
|
|
609
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": presets.").concat(name, " must be an object"));
|
|
610
|
+
}
|
|
611
|
+
var preset = value;
|
|
612
|
+
var unknown = Object.keys(preset).filter(function(k) {
|
|
613
|
+
return !KNOWN_PRESET_KEYS.has(k);
|
|
614
|
+
});
|
|
615
|
+
if (unknown.length > 0) {
|
|
616
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": presets.").concat(name, " has unknown key(s) ").concat(unknown.join(', '), "; a preset takes include, exclude, k, semantic, where"));
|
|
617
|
+
}
|
|
618
|
+
if (!isNonEmptyStringArray(preset.include)) {
|
|
619
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": presets.").concat(name, ".include must be a non-empty array of glob strings"));
|
|
620
|
+
}
|
|
621
|
+
if (preset.exclude !== undefined && !isNonEmptyStringArray(preset.exclude)) {
|
|
622
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": presets.").concat(name, ".exclude must be a non-empty array of glob strings"));
|
|
623
|
+
}
|
|
624
|
+
if (preset.k !== undefined && (typeof preset.k !== 'number' || !Number.isInteger(preset.k) || preset.k <= 0)) {
|
|
625
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": presets.").concat(name, ".k must be a positive integer"));
|
|
626
|
+
}
|
|
627
|
+
if (preset.semantic !== undefined && typeof preset.semantic !== 'boolean') {
|
|
628
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": presets.").concat(name, ".semantic must be a boolean"));
|
|
629
|
+
}
|
|
630
|
+
if (preset.where !== undefined && typeof preset.where !== 'string') {
|
|
631
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": presets.").concat(name, ".where must be a SQL condition string"));
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
// A queries.<name> entry: a SQL string, { sql }, or a saved search { search, preset?, include?, where?, k?, semantic? }.
|
|
635
|
+
function validateSavedQuery(name, value, configPath) {
|
|
636
|
+
if (typeof value === 'string') return;
|
|
637
|
+
if ((typeof value === "undefined" ? "undefined" : _type_of(value)) !== 'object' || value === null || Array.isArray(value)) {
|
|
638
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": queries.").concat(name, " must be a SQL string, { sql }, or { search, preset?, include?, where?, k?, semantic? }"));
|
|
639
|
+
}
|
|
640
|
+
var entry = value;
|
|
641
|
+
if ('sql' in entry) {
|
|
642
|
+
var unknown = Object.keys(entry).filter(function(k) {
|
|
643
|
+
return k !== 'sql';
|
|
644
|
+
});
|
|
645
|
+
if (unknown.length > 0) {
|
|
646
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": queries.").concat(name, " has unknown key(s) ").concat(unknown.join(', '), "; a { sql } query takes only sql"));
|
|
647
|
+
}
|
|
648
|
+
if (typeof entry.sql !== 'string' || entry.sql.trim() === '') {
|
|
649
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": queries.").concat(name, ".sql must be a non-empty string"));
|
|
650
|
+
}
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
if ('search' in entry) {
|
|
654
|
+
var unknown1 = Object.keys(entry).filter(function(k) {
|
|
655
|
+
return !SAVED_SEARCH_KEYS.has(k);
|
|
656
|
+
});
|
|
657
|
+
if (unknown1.length > 0) {
|
|
658
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": queries.").concat(name, " has unknown key(s) ").concat(unknown1.join(', '), "; a saved search takes search, preset, include, where, k, semantic"));
|
|
659
|
+
}
|
|
660
|
+
// A saved query saves a question; a scope without a question is just flags.
|
|
661
|
+
if (typeof entry.search !== 'string' || entry.search.trim() === '') {
|
|
662
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": queries.").concat(name, ".search must be non-empty text"));
|
|
663
|
+
}
|
|
664
|
+
if (entry.preset !== undefined && (typeof entry.preset !== 'string' || entry.preset.length === 0)) {
|
|
665
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": queries.").concat(name, ".preset must be a preset name"));
|
|
666
|
+
}
|
|
667
|
+
if (entry.include !== undefined && !isNonEmptyStringArray(entry.include)) {
|
|
668
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": queries.").concat(name, ".include must be a non-empty array of glob strings"));
|
|
669
|
+
}
|
|
670
|
+
if (entry.where !== undefined && typeof entry.where !== 'string') {
|
|
671
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": queries.").concat(name, ".where must be a SQL condition string"));
|
|
672
|
+
}
|
|
673
|
+
if (entry.k !== undefined && (typeof entry.k !== 'number' || !Number.isInteger(entry.k) || entry.k <= 0)) {
|
|
674
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": queries.").concat(name, ".k must be a positive integer"));
|
|
675
|
+
}
|
|
676
|
+
if (entry.semantic !== undefined && typeof entry.semantic !== 'boolean') {
|
|
677
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": queries.").concat(name, ".semantic must be a boolean"));
|
|
678
|
+
}
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": queries.").concat(name, " must be a SQL string, { sql }, or { search, preset?, include?, where?, k?, semantic? }"));
|
|
338
682
|
}
|
|
339
683
|
function validateConfig(parsed, configPath) {
|
|
340
|
-
var _cfg_features;
|
|
341
|
-
var _defaults_find;
|
|
342
684
|
if ((typeof parsed === "undefined" ? "undefined" : _type_of(parsed)) !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
343
685
|
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": config must be a JSON object"));
|
|
344
686
|
}
|
|
345
687
|
var cfg = parsed;
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
688
|
+
// `checks` (assertions over saved queries) was removed in v3, not merely deprecated: a
|
|
689
|
+
// hand-written v3 config still carrying it gets a named rejection rather than a silent
|
|
690
|
+
// "unknown key" warning, since silence here would hide that the assertion behavior it
|
|
691
|
+
// implies no longer exists.
|
|
692
|
+
if (cfg.checks !== undefined) {
|
|
693
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": checks was removed in v3 -- sense check no longer asserts on saved queries; a returned row set is the reader's judgment"));
|
|
351
694
|
}
|
|
352
|
-
|
|
353
|
-
if (_type_of(
|
|
354
|
-
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
}
|
|
362
|
-
var checks = cfg.checks;
|
|
363
|
-
if (checks !== undefined) {
|
|
364
|
-
var _cfg_queries;
|
|
365
|
-
if ((typeof checks === "undefined" ? "undefined" : _type_of(checks)) !== 'object' || checks === null || Array.isArray(checks) || !Object.values(checks).every(function(v) {
|
|
366
|
-
return v === 'empty';
|
|
367
|
-
})) {
|
|
368
|
-
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ': checks must be an object of query name -> "empty"'));
|
|
695
|
+
var presets = cfg.presets;
|
|
696
|
+
if (!presets || (typeof presets === "undefined" ? "undefined" : _type_of(presets)) !== 'object' || Array.isArray(presets) || Object.keys(presets).length === 0) {
|
|
697
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": presets must be a non-empty object of preset name -> { include, exclude?, k?, semantic?, where? }"));
|
|
698
|
+
}
|
|
699
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
700
|
+
try {
|
|
701
|
+
for(var _iterator = Object.entries(presets)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
702
|
+
var _step_value = _sliced_to_array(_step.value, 2), name = _step_value[0], value = _step_value[1];
|
|
703
|
+
validatePreset(name, value, configPath);
|
|
369
704
|
}
|
|
370
|
-
|
|
371
|
-
|
|
705
|
+
} catch (err) {
|
|
706
|
+
_didIteratorError = true;
|
|
707
|
+
_iteratorError = err;
|
|
708
|
+
} finally{
|
|
372
709
|
try {
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
if (queries[name] === undefined) throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ': checks names "').concat(name, '", which is not a saved query'));
|
|
710
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
711
|
+
_iterator.return();
|
|
376
712
|
}
|
|
377
|
-
} catch (err) {
|
|
378
|
-
_didIteratorError = true;
|
|
379
|
-
_iteratorError = err;
|
|
380
713
|
} finally{
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
_iterator.return();
|
|
384
|
-
}
|
|
385
|
-
} finally{
|
|
386
|
-
if (_didIteratorError) {
|
|
387
|
-
throw _iteratorError;
|
|
388
|
-
}
|
|
714
|
+
if (_didIteratorError) {
|
|
715
|
+
throw _iteratorError;
|
|
389
716
|
}
|
|
390
717
|
}
|
|
391
718
|
}
|
|
392
|
-
if (
|
|
393
|
-
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath,
|
|
719
|
+
if (presets.default === undefined) {
|
|
720
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ': presets must include a "default" preset'));
|
|
721
|
+
}
|
|
722
|
+
if (cfg.queries === undefined) cfg.queries = {};
|
|
723
|
+
if (_type_of(cfg.queries) !== 'object' || cfg.queries === null || Array.isArray(cfg.queries)) {
|
|
724
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": queries must be an object of name -> SQL string, { sql }, or saved search"));
|
|
394
725
|
}
|
|
726
|
+
var queries = cfg.queries;
|
|
395
727
|
var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
|
|
396
728
|
try {
|
|
397
|
-
var
|
|
398
|
-
var
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
var embed = value;
|
|
402
|
-
var shapeOk = name === 'embed' && (typeof value === "undefined" ? "undefined" : _type_of(value)) === 'object' && value !== null && !Array.isArray(value) && [
|
|
403
|
-
'model',
|
|
404
|
-
'url',
|
|
405
|
-
'key'
|
|
406
|
-
].every(function(f) {
|
|
407
|
-
return embed[f] === undefined || typeof embed[f] === 'string';
|
|
408
|
-
}) && (embed.type === undefined || embed.type === 'static' || embed.type === 'api');
|
|
409
|
-
if (!shapeOk) {
|
|
410
|
-
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": features.").concat(name, " must be a boolean").concat(name === 'embed' ? ' or { model?, type?: "static"|"api", url?, key? }' : ''));
|
|
411
|
-
}
|
|
412
|
-
};
|
|
413
|
-
for(var _iterator1 = Object.entries((_cfg_features = cfg.features) !== null && _cfg_features !== void 0 ? _cfg_features : {})[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true)_loop();
|
|
729
|
+
for(var _iterator1 = Object.entries(queries)[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
|
|
730
|
+
var _step_value1 = _sliced_to_array(_step1.value, 2), name1 = _step_value1[0], value1 = _step_value1[1];
|
|
731
|
+
validateSavedQuery(name1, value1, configPath);
|
|
732
|
+
}
|
|
414
733
|
} catch (err) {
|
|
415
734
|
_didIteratorError1 = true;
|
|
416
735
|
_iteratorError1 = err;
|
|
@@ -425,6 +744,12 @@ function validateConfig(parsed, configPath) {
|
|
|
425
744
|
}
|
|
426
745
|
}
|
|
427
746
|
}
|
|
747
|
+
if (cfg.features !== undefined) {
|
|
748
|
+
validateFeaturesBlock(cfg.features, configPath);
|
|
749
|
+
}
|
|
750
|
+
if (cfg.embed !== undefined) {
|
|
751
|
+
validateEmbedBlock(cfg.embed, configPath);
|
|
752
|
+
}
|
|
428
753
|
return cfg;
|
|
429
754
|
}
|
|
430
755
|
function loadConfig(explicitPath) {
|
|
@@ -441,19 +766,33 @@ function loadConfig(explicitPath) {
|
|
|
441
766
|
}
|
|
442
767
|
var raw = (0, _nodefs.readFileSync)(configPath, 'utf8');
|
|
443
768
|
var parsed = JSON.parse(raw);
|
|
769
|
+
// Ahead of both the version gate and legacy/current shape checks: a non-object file (or
|
|
770
|
+
// an array -- typeof [] is also 'object') is malformed at every version, so it gets one
|
|
771
|
+
// error regardless of which branch would otherwise run.
|
|
772
|
+
if ((typeof parsed === "undefined" ? "undefined" : _type_of(parsed)) !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
773
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": config must be a JSON object"));
|
|
774
|
+
}
|
|
444
775
|
// Version gate before shape validation: a config written by a newer sense should fail
|
|
445
776
|
// with "requires a newer sense", not with shape errors its own version may not have.
|
|
446
777
|
var version = (typeof parsed === "undefined" ? "undefined" : _type_of(parsed)) === 'object' && parsed !== null && typeof parsed.version === 'number' ? parsed.version : 1;
|
|
447
778
|
if (version > SUPPORTED_CONFIG_VERSION) {
|
|
448
779
|
throw new _errorsts.SenseError('CONFIG_VERSION_UNSUPPORTED', "config version ".concat(version, " requires a newer sense"));
|
|
449
780
|
}
|
|
450
|
-
|
|
781
|
+
// validateConfig only understands the current v3 shape (presets, saved-query object
|
|
782
|
+
// shapes); a pre-v3 file on disk is scan/find-shaped and must migrate before it can pass
|
|
783
|
+
// that check. Validate just enough of the old shape to migrate safely, migrate, then run
|
|
784
|
+
// the full v3 validateConfig on the migrated result -- the shape that actually lands on
|
|
785
|
+
// disk and in ResolvedConfig.
|
|
786
|
+
var cfg;
|
|
451
787
|
var migratedFrom;
|
|
452
788
|
if (version < SUPPORTED_CONFIG_VERSION) {
|
|
453
|
-
|
|
454
|
-
|
|
789
|
+
validateLegacyScan(parsed, configPath);
|
|
790
|
+
var result = migrateConfig(parsed);
|
|
791
|
+
cfg = validateConfig(result.cfg, configPath);
|
|
455
792
|
migratedFrom = result.from;
|
|
456
793
|
(0, _nodefs.writeFileSync)(configPath, "".concat(JSON.stringify(cfg, null, 2), "\n"));
|
|
794
|
+
} else {
|
|
795
|
+
cfg = validateConfig(parsed, configPath);
|
|
457
796
|
}
|
|
458
797
|
var unknownKeys = unknownConfigKeys(cfg);
|
|
459
798
|
return _object_spread_props(_object_spread({}, cfg), {
|