sensemaking 0.8.0 → 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 +48 -39
- package/dist/cjs/cli/check.js +24 -43
- package/dist/cjs/cli/check.js.map +1 -1
- package/dist/cjs/cli/index.js +2 -2
- package/dist/cjs/cli/index.js.map +1 -1
- package/dist/cjs/cli/named.js +18 -8
- package/dist/cjs/cli/named.js.map +1 -1
- package/dist/cjs/cli/search.d.cts +3 -0
- package/dist/cjs/cli/search.d.ts +3 -0
- package/dist/cjs/cli/{find.js → search.js} +7 -5
- package/dist/cjs/cli/search.js.map +1 -0
- package/dist/cjs/cli/shared.js.map +1 -1
- package/dist/cjs/cli/status.js +29 -12
- package/dist/cjs/cli/status.js.map +1 -1
- package/dist/cjs/cli/types.d.cts +3 -1
- package/dist/cjs/cli/types.d.ts +3 -1
- package/dist/cjs/cli.js +25 -5
- package/dist/cjs/cli.js.map +1 -1
- package/dist/cjs/commands.d.cts +11 -2
- package/dist/cjs/commands.d.ts +11 -2
- package/dist/cjs/commands.js +86 -21
- package/dist/cjs/commands.js.map +1 -1
- package/dist/cjs/config.d.cts +41 -14
- package/dist/cjs/config.d.ts +41 -14
- package/dist/cjs/config.js +448 -160
- 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 +208 -62
- 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 +12 -2
- package/dist/cjs/features/embed.js.map +1 -1
- package/dist/cjs/features/types.d.cts +2 -1
- package/dist/cjs/features/types.d.ts +2 -1
- package/dist/cjs/index.d.cts +3 -3
- package/dist/cjs/index.d.ts +3 -3
- package/dist/cjs/index.js +6 -3
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/output.d.cts +15 -0
- package/dist/cjs/output.d.ts +15 -0
- package/dist/cjs/output.js +26 -5
- package/dist/cjs/output.js.map +1 -1
- package/dist/cjs/scan.d.cts +3 -0
- package/dist/cjs/scan.d.ts +3 -0
- package/dist/cjs/scan.js +84 -4
- package/dist/cjs/scan.js.map +1 -1
- package/dist/esm/cli/check.js +20 -41
- package/dist/esm/cli/check.js.map +1 -1
- package/dist/esm/cli/index.js +1 -1
- package/dist/esm/cli/index.js.map +1 -1
- package/dist/esm/cli/named.js +17 -9
- package/dist/esm/cli/named.js.map +1 -1
- 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/esm/cli/shared.js +1 -1
- package/dist/esm/cli/shared.js.map +1 -1
- package/dist/esm/cli/status.js +10 -10
- package/dist/esm/cli/status.js.map +1 -1
- package/dist/esm/cli/types.d.ts +3 -1
- package/dist/esm/cli/types.js.map +1 -1
- package/dist/esm/cli.js +20 -4
- package/dist/esm/cli.js.map +1 -1
- package/dist/esm/commands.d.ts +11 -2
- package/dist/esm/commands.js +76 -24
- package/dist/esm/commands.js.map +1 -1
- package/dist/esm/config.d.ts +41 -14
- package/dist/esm/config.js +354 -114
- package/dist/esm/config.js.map +1 -1
- package/dist/esm/db.d.ts +1 -1
- package/dist/esm/db.js +53 -6
- 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 +12 -2
- package/dist/esm/features/embed.js.map +1 -1
- package/dist/esm/features/types.d.ts +2 -1
- 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 +15 -0
- package/dist/esm/output.js +19 -5
- package/dist/esm/output.js.map +1 -1
- package/dist/esm/scan.d.ts +3 -0
- package/dist/esm/scan.js +32 -4
- package/dist/esm/scan.js.map +1 -1
- package/package.json +9 -3
- package/schema.json +74 -54
- package/skills/sense/EXAMPLES.md +8 -6
- package/skills/sense/SKILL.md +51 -48
- package/skills/sense-setup/EXAMPLES.md +121 -0
- package/skills/sense-setup/SKILL.md +71 -66
- package/dist/cjs/cli/find.d.cts +0 -3
- package/dist/cjs/cli/find.d.ts +0 -3
- package/dist/cjs/cli/find.js.map +0 -1
- package/dist/esm/cli/find.d.ts +0 -3
- package/dist/esm/cli/find.js +0 -14
- package/dist/esm/cli/find.js.map +0 -1
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 =
|
|
222
|
+
var SUPPORTED_CONFIG_VERSION = 3;
|
|
172
223
|
// Each feature owns its tables, parse-time extraction, and reconcile step; commands degrade when one is off.
|
|
173
|
-
// links/sections/rank are opt-out
|
|
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,103 +488,219 @@ 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'
|
|
312
|
-
|
|
313
|
-
function unknownConfigKeys(cfg) {
|
|
314
|
-
var unknown = Object.keys(cfg).filter(function(k) {
|
|
315
|
-
return !KNOWN_KEYS.has(k);
|
|
316
|
-
}).map(function(k) {
|
|
317
|
-
return k;
|
|
318
|
-
});
|
|
319
|
-
var scan = cfg.scan;
|
|
320
|
-
if (scan && (typeof scan === "undefined" ? "undefined" : _type_of(scan)) === 'object' && !Array.isArray(scan)) {
|
|
321
|
-
var _unknown;
|
|
322
|
-
(_unknown = unknown).push.apply(_unknown, _to_consumable_array(Object.keys(scan).filter(function(k) {
|
|
323
|
-
return !KNOWN_SCAN_KEYS.has(k);
|
|
324
|
-
}).map(function(k) {
|
|
325
|
-
return "scan.".concat(k);
|
|
326
|
-
})));
|
|
327
|
-
}
|
|
328
|
-
var features = cfg.features;
|
|
329
|
-
if (features && (typeof features === "undefined" ? "undefined" : _type_of(features)) === 'object' && !Array.isArray(features)) {
|
|
330
|
-
var _unknown1;
|
|
331
|
-
(_unknown1 = unknown).push.apply(_unknown1, _to_consumable_array(Object.keys(features).filter(function(k) {
|
|
332
|
-
return !FEATURE_NAMES.includes(k);
|
|
333
|
-
}).map(function(k) {
|
|
334
|
-
return "features.".concat(k);
|
|
335
|
-
})));
|
|
336
|
-
}
|
|
337
|
-
return unknown;
|
|
338
|
-
}
|
|
339
|
-
var SAVED_FIND_KEYS = new Set([
|
|
340
|
-
'find',
|
|
504
|
+
var KNOWN_PRESET_KEYS = new Set([
|
|
505
|
+
'include',
|
|
506
|
+
'exclude',
|
|
341
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',
|
|
342
526
|
'where',
|
|
527
|
+
'k',
|
|
343
528
|
'semantic'
|
|
344
529
|
]);
|
|
345
|
-
|
|
346
|
-
|
|
530
|
+
function unknownConfigKeys(cfg) {
|
|
531
|
+
return Object.keys(cfg).filter(function(k) {
|
|
532
|
+
return !KNOWN_KEYS.has(k);
|
|
533
|
+
});
|
|
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) {
|
|
347
550
|
if ((typeof value === "undefined" ? "undefined" : _type_of(value)) !== 'object' || value === null || Array.isArray(value)) {
|
|
348
|
-
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ":
|
|
551
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": features must be an object of name -> boolean"));
|
|
349
552
|
}
|
|
350
|
-
var
|
|
351
|
-
var unknown = Object.keys(
|
|
352
|
-
return !
|
|
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);
|
|
353
614
|
});
|
|
354
615
|
if (unknown.length > 0) {
|
|
355
|
-
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ":
|
|
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"));
|
|
356
617
|
}
|
|
357
|
-
if (
|
|
358
|
-
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ":
|
|
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"));
|
|
359
620
|
}
|
|
360
|
-
if (
|
|
361
|
-
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ":
|
|
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"));
|
|
362
623
|
}
|
|
363
|
-
if (
|
|
364
|
-
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ":
|
|
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;
|
|
365
652
|
}
|
|
366
|
-
if (
|
|
367
|
-
|
|
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;
|
|
368
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? }"));
|
|
369
682
|
}
|
|
370
683
|
function validateConfig(parsed, configPath) {
|
|
371
|
-
var _cfg_features;
|
|
372
|
-
var _defaults_find;
|
|
373
684
|
if ((typeof parsed === "undefined" ? "undefined" : _type_of(parsed)) !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
374
685
|
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": config must be a JSON object"));
|
|
375
686
|
}
|
|
376
687
|
var cfg = parsed;
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
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"));
|
|
382
694
|
}
|
|
383
|
-
|
|
384
|
-
if (_type_of(
|
|
385
|
-
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ":
|
|
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? }"));
|
|
386
698
|
}
|
|
387
699
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
388
700
|
try {
|
|
389
|
-
for(var _iterator = Object.entries(
|
|
701
|
+
for(var _iterator = Object.entries(presets)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
390
702
|
var _step_value = _sliced_to_array(_step.value, 2), name = _step_value[0], value = _step_value[1];
|
|
391
|
-
|
|
392
|
-
validateSavedFind(name, value, configPath);
|
|
703
|
+
validatePreset(name, value, configPath);
|
|
393
704
|
}
|
|
394
705
|
} catch (err) {
|
|
395
706
|
_didIteratorError = true;
|
|
@@ -405,77 +716,40 @@ function validateConfig(parsed, configPath) {
|
|
|
405
716
|
}
|
|
406
717
|
}
|
|
407
718
|
}
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": defaults.find.where must be a SQL condition string"));
|
|
411
|
-
}
|
|
412
|
-
var checks = cfg.checks;
|
|
413
|
-
if (checks !== undefined) {
|
|
414
|
-
var _cfg_queries;
|
|
415
|
-
if ((typeof checks === "undefined" ? "undefined" : _type_of(checks)) !== 'object' || checks === null || Array.isArray(checks) || !Object.values(checks).every(function(v) {
|
|
416
|
-
return v === 'empty';
|
|
417
|
-
})) {
|
|
418
|
-
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ': checks must be an object of query name -> "empty"'));
|
|
419
|
-
}
|
|
420
|
-
var queries = (_cfg_queries = cfg.queries) !== null && _cfg_queries !== void 0 ? _cfg_queries : {};
|
|
421
|
-
var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
|
|
422
|
-
try {
|
|
423
|
-
for(var _iterator1 = Object.keys(checks)[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
|
|
424
|
-
var name1 = _step1.value;
|
|
425
|
-
if (queries[name1] === undefined) throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ': checks names "').concat(name1, '", which is not a saved query'));
|
|
426
|
-
if (typeof queries[name1] !== 'string') throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ': checks names "').concat(name1, '", which is a saved find, not a SQL query'));
|
|
427
|
-
}
|
|
428
|
-
} catch (err) {
|
|
429
|
-
_didIteratorError1 = true;
|
|
430
|
-
_iteratorError1 = err;
|
|
431
|
-
} finally{
|
|
432
|
-
try {
|
|
433
|
-
if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
|
|
434
|
-
_iterator1.return();
|
|
435
|
-
}
|
|
436
|
-
} finally{
|
|
437
|
-
if (_didIteratorError1) {
|
|
438
|
-
throw _iteratorError1;
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
}
|
|
719
|
+
if (presets.default === undefined) {
|
|
720
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ': presets must include a "default" preset'));
|
|
442
721
|
}
|
|
443
|
-
if (cfg.
|
|
444
|
-
|
|
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"));
|
|
445
725
|
}
|
|
446
|
-
var
|
|
726
|
+
var queries = cfg.queries;
|
|
727
|
+
var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
|
|
447
728
|
try {
|
|
448
|
-
var
|
|
449
|
-
var
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
var embed = value;
|
|
453
|
-
var shapeOk = name === 'embed' && (typeof value === "undefined" ? "undefined" : _type_of(value)) === 'object' && value !== null && !Array.isArray(value) && [
|
|
454
|
-
'model',
|
|
455
|
-
'url',
|
|
456
|
-
'key'
|
|
457
|
-
].every(function(f) {
|
|
458
|
-
return embed[f] === undefined || typeof embed[f] === 'string';
|
|
459
|
-
}) && (embed.type === undefined || embed.type === 'static' || embed.type === 'api');
|
|
460
|
-
if (!shapeOk) {
|
|
461
|
-
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? }' : ''));
|
|
462
|
-
}
|
|
463
|
-
};
|
|
464
|
-
for(var _iterator2 = Object.entries((_cfg_features = cfg.features) !== null && _cfg_features !== void 0 ? _cfg_features : {})[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = 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
|
+
}
|
|
465
733
|
} catch (err) {
|
|
466
|
-
|
|
467
|
-
|
|
734
|
+
_didIteratorError1 = true;
|
|
735
|
+
_iteratorError1 = err;
|
|
468
736
|
} finally{
|
|
469
737
|
try {
|
|
470
|
-
if (!
|
|
471
|
-
|
|
738
|
+
if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
|
|
739
|
+
_iterator1.return();
|
|
472
740
|
}
|
|
473
741
|
} finally{
|
|
474
|
-
if (
|
|
475
|
-
throw
|
|
742
|
+
if (_didIteratorError1) {
|
|
743
|
+
throw _iteratorError1;
|
|
476
744
|
}
|
|
477
745
|
}
|
|
478
746
|
}
|
|
747
|
+
if (cfg.features !== undefined) {
|
|
748
|
+
validateFeaturesBlock(cfg.features, configPath);
|
|
749
|
+
}
|
|
750
|
+
if (cfg.embed !== undefined) {
|
|
751
|
+
validateEmbedBlock(cfg.embed, configPath);
|
|
752
|
+
}
|
|
479
753
|
return cfg;
|
|
480
754
|
}
|
|
481
755
|
function loadConfig(explicitPath) {
|
|
@@ -492,19 +766,33 @@ function loadConfig(explicitPath) {
|
|
|
492
766
|
}
|
|
493
767
|
var raw = (0, _nodefs.readFileSync)(configPath, 'utf8');
|
|
494
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
|
+
}
|
|
495
775
|
// Version gate before shape validation: a config written by a newer sense should fail
|
|
496
776
|
// with "requires a newer sense", not with shape errors its own version may not have.
|
|
497
777
|
var version = (typeof parsed === "undefined" ? "undefined" : _type_of(parsed)) === 'object' && parsed !== null && typeof parsed.version === 'number' ? parsed.version : 1;
|
|
498
778
|
if (version > SUPPORTED_CONFIG_VERSION) {
|
|
499
779
|
throw new _errorsts.SenseError('CONFIG_VERSION_UNSUPPORTED', "config version ".concat(version, " requires a newer sense"));
|
|
500
780
|
}
|
|
501
|
-
|
|
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;
|
|
502
787
|
var migratedFrom;
|
|
503
788
|
if (version < SUPPORTED_CONFIG_VERSION) {
|
|
504
|
-
|
|
505
|
-
|
|
789
|
+
validateLegacyScan(parsed, configPath);
|
|
790
|
+
var result = migrateConfig(parsed);
|
|
791
|
+
cfg = validateConfig(result.cfg, configPath);
|
|
506
792
|
migratedFrom = result.from;
|
|
507
793
|
(0, _nodefs.writeFileSync)(configPath, "".concat(JSON.stringify(cfg, null, 2), "\n"));
|
|
794
|
+
} else {
|
|
795
|
+
cfg = validateConfig(parsed, configPath);
|
|
508
796
|
}
|
|
509
797
|
var unknownKeys = unknownConfigKeys(cfg);
|
|
510
798
|
return _object_spread_props(_object_spread({}, cfg), {
|