sensemaking 0.20.0 → 0.21.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 +0 -1
- package/dist/cjs/config/access.d.cts +0 -1
- package/dist/cjs/config/access.d.ts +0 -1
- package/dist/cjs/config/access.js +10 -17
- package/dist/cjs/config/access.js.map +1 -1
- package/dist/cjs/config/index.d.cts +1 -1
- package/dist/cjs/config/index.d.ts +1 -1
- package/dist/cjs/config/index.js +0 -3
- package/dist/cjs/config/index.js.map +1 -1
- package/dist/cjs/config/types.d.cts +0 -3
- package/dist/cjs/config/types.d.ts +0 -3
- package/dist/cjs/config/types.js.map +1 -1
- package/dist/cjs/config/validate.js +6 -24
- package/dist/cjs/config/validate.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/links.js +4 -5
- package/dist/cjs/features/links.js.map +1 -1
- package/dist/cjs/features/sections.js +4 -1
- package/dist/cjs/features/sections.js.map +1 -1
- package/dist/cjs/store/builder.d.cts +9 -1
- package/dist/cjs/store/builder.d.ts +9 -1
- package/dist/cjs/store/builder.js +593 -2
- package/dist/cjs/store/builder.js.map +1 -1
- package/dist/cjs/store/duckdb/open.js +7 -1
- package/dist/cjs/store/duckdb/open.js.map +1 -1
- package/dist/cjs/store/duckdb/reconcile.js +30 -5
- package/dist/cjs/store/duckdb/reconcile.js.map +1 -1
- package/dist/cjs/store/embed-scope.d.cts +2 -0
- package/dist/cjs/store/embed-scope.d.ts +2 -0
- package/dist/cjs/store/embed-scope.js +85 -0
- package/dist/cjs/store/embed-scope.js.map +1 -0
- package/dist/cjs/store/feature-scope.d.cts +8 -0
- package/dist/cjs/store/feature-scope.d.ts +8 -0
- package/dist/cjs/store/feature-scope.js +107 -0
- package/dist/cjs/store/feature-scope.js.map +1 -0
- package/dist/cjs/store/open.js +193 -101
- package/dist/cjs/store/open.js.map +1 -1
- package/dist/cjs/store/preset-scope.d.cts +3 -0
- package/dist/cjs/store/preset-scope.d.ts +3 -0
- package/dist/cjs/store/preset-scope.js +293 -0
- package/dist/cjs/store/preset-scope.js.map +1 -0
- package/dist/cjs/store/reconcile.d.cts +1 -1
- package/dist/cjs/store/reconcile.d.ts +1 -1
- package/dist/cjs/store/reconcile.js +172 -178
- package/dist/cjs/store/reconcile.js.map +1 -1
- package/dist/cjs/store/signature.js +7 -5
- package/dist/cjs/store/signature.js.map +1 -1
- package/dist/cjs/store/sqlite/lexical.d.cts +1 -1
- package/dist/cjs/store/sqlite/lexical.d.ts +1 -1
- package/dist/cjs/store/sqlite/lexical.js +2 -2
- package/dist/cjs/store/sqlite/lexical.js.map +1 -1
- package/dist/cjs/store/sqlite/open.d.cts +0 -1
- package/dist/cjs/store/sqlite/open.d.ts +0 -1
- package/dist/cjs/store/sqlite/open.js +14 -231
- package/dist/cjs/store/sqlite/open.js.map +1 -1
- package/dist/cjs/store/sqlite/reconcile.d.cts +1 -1
- package/dist/cjs/store/sqlite/reconcile.d.ts +1 -1
- package/dist/cjs/store/sqlite/reconcile.js +78 -16
- package/dist/cjs/store/sqlite/reconcile.js.map +1 -1
- package/dist/cjs/store/sqlite/sql-functions.d.cts +1 -1
- package/dist/cjs/store/sqlite/sql-functions.d.ts +1 -1
- package/dist/cjs/store/sqlite/sql-functions.js +3 -3
- package/dist/cjs/store/sqlite/sql-functions.js.map +1 -1
- package/dist/cjs/store/sqlite/store.d.cts +1 -2
- package/dist/cjs/store/sqlite/store.d.ts +1 -2
- package/dist/cjs/store/sqlite/store.js +2 -3
- package/dist/cjs/store/sqlite/store.js.map +1 -1
- package/dist/cjs/store/turso/open.js +6 -0
- package/dist/cjs/store/turso/open.js.map +1 -1
- package/dist/cjs/store/turso/reconcile.js +72 -3
- package/dist/cjs/store/turso/reconcile.js.map +1 -1
- package/dist/cjs/store/types.d.cts +2 -4
- package/dist/cjs/store/types.d.ts +2 -4
- package/dist/cjs/store/types.js.map +1 -1
- package/dist/esm/config/access.d.ts +0 -1
- package/dist/esm/config/access.js +12 -17
- package/dist/esm/config/access.js.map +1 -1
- package/dist/esm/config/index.d.ts +1 -1
- package/dist/esm/config/index.js +1 -1
- package/dist/esm/config/index.js.map +1 -1
- package/dist/esm/config/types.d.ts +0 -3
- package/dist/esm/config/types.js.map +1 -1
- package/dist/esm/config/validate.js +6 -22
- package/dist/esm/config/validate.js.map +1 -1
- package/dist/esm/errors.d.ts +1 -1
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/features/links.js +3 -4
- package/dist/esm/features/links.js.map +1 -1
- package/dist/esm/features/sections.js +4 -1
- package/dist/esm/features/sections.js.map +1 -1
- package/dist/esm/store/builder.d.ts +9 -1
- package/dist/esm/store/builder.js +152 -3
- package/dist/esm/store/builder.js.map +1 -1
- package/dist/esm/store/duckdb/open.js +5 -1
- package/dist/esm/store/duckdb/open.js.map +1 -1
- package/dist/esm/store/duckdb/reconcile.js +11 -3
- package/dist/esm/store/duckdb/reconcile.js.map +1 -1
- package/dist/esm/store/embed-scope.d.ts +2 -0
- package/dist/esm/store/embed-scope.js +28 -0
- package/dist/esm/store/embed-scope.js.map +1 -0
- package/dist/esm/store/feature-scope.d.ts +8 -0
- package/dist/esm/store/feature-scope.js +49 -0
- package/dist/esm/store/feature-scope.js.map +1 -0
- package/dist/esm/store/open.js +78 -28
- package/dist/esm/store/open.js.map +1 -1
- package/dist/esm/store/preset-scope.d.ts +3 -0
- package/dist/esm/store/preset-scope.js +77 -0
- package/dist/esm/store/preset-scope.js.map +1 -0
- package/dist/esm/store/reconcile.d.ts +1 -1
- package/dist/esm/store/reconcile.js +30 -5
- package/dist/esm/store/reconcile.js.map +1 -1
- package/dist/esm/store/signature.js +7 -5
- package/dist/esm/store/signature.js.map +1 -1
- package/dist/esm/store/sqlite/lexical.d.ts +1 -1
- package/dist/esm/store/sqlite/lexical.js +4 -4
- package/dist/esm/store/sqlite/lexical.js.map +1 -1
- package/dist/esm/store/sqlite/open.d.ts +0 -1
- package/dist/esm/store/sqlite/open.js +14 -88
- package/dist/esm/store/sqlite/open.js.map +1 -1
- package/dist/esm/store/sqlite/reconcile.d.ts +1 -1
- package/dist/esm/store/sqlite/reconcile.js +14 -14
- package/dist/esm/store/sqlite/reconcile.js.map +1 -1
- package/dist/esm/store/sqlite/sql-functions.d.ts +1 -1
- package/dist/esm/store/sqlite/sql-functions.js +3 -3
- package/dist/esm/store/sqlite/sql-functions.js.map +1 -1
- package/dist/esm/store/sqlite/store.d.ts +1 -2
- package/dist/esm/store/sqlite/store.js +2 -3
- package/dist/esm/store/sqlite/store.js.map +1 -1
- package/dist/esm/store/turso/open.js +4 -0
- package/dist/esm/store/turso/open.js.map +1 -1
- package/dist/esm/store/turso/reconcile.js +6 -2
- package/dist/esm/store/turso/reconcile.js.map +1 -1
- package/dist/esm/store/types.d.ts +2 -4
- package/dist/esm/store/types.js.map +1 -1
- package/package.json +3 -2
- package/schema.json +0 -11
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/open.ts"],"sourcesContent":["import type { DuckDBConnection, DuckDBInstance } from '@duckdb/node-api';\nimport type { Config, ResolvedConfig } from '../../config/index.ts';\nimport { featureSignature } from '../../config/index.ts';\nimport { STORE_DIMS } from '../../embed/types.ts';\nimport { SenseError } from '../../errors.ts';\nimport { activeFeatures, FEATURES } from '../../features/index.ts';\nimport type { OpenResult } from '../open.ts';\nimport { openWithDialect } from '../open.ts';\nimport { getMeta, setMeta } from '../shared.ts';\nimport type { Connection, OpenDialect } from '../types.ts';\nimport { createConnection } from './connection.ts';\nimport { DUCKDB_PACKAGE, duckdbApi } from './native.ts';\nimport { duckdbDialect } from './reconcile.ts';\nimport { registerFunctions } from './sql-functions.ts';\nimport { createStore } from './store.ts';\n\nexport const DB_FILENAME = 'cache.duckdb';\n// Independent of sqlite's SCHEMA_VERSION -- the two stores' cache shapes evolve separately (VARIANT frontmatter columns vs untyped).\n// The store name already joins the feature signature, so switching a config's `store` key rebuilds rather than reusing the other engine's cache.\nexport const SCHEMA_VERSION = '3';\n\nexport type { OpenResult };\n\n// The connection plus this store's own native handles (types.ts's OpenDialect<Handle>): the\n// instance owns the WAL and must outlive the connection borrowed from it.\ninterface DuckdbHandle {\n instance: DuckDBInstance;\n duckdb: DuckDBConnection;\n}\n\n// `content` is a plain table (not FTS-virtual): the fts index is built over it lazily, only when a lexical query runs (lexical.ts), and read directly for contains() verification either way.\n// No tokenizer resolution: this store always uses the fts extension's default (porter) stemmer
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/open.ts"],"sourcesContent":["import type { DuckDBConnection, DuckDBInstance } from '@duckdb/node-api';\nimport type { Config, ResolvedConfig } from '../../config/index.ts';\nimport { featureSignature } from '../../config/index.ts';\nimport { STORE_DIMS } from '../../embed/types.ts';\nimport { SenseError } from '../../errors.ts';\nimport { activeFeatures, FEATURES } from '../../features/index.ts';\nimport type { OpenResult } from '../open.ts';\nimport { openWithDialect } from '../open.ts';\nimport { getMeta, setMeta } from '../shared.ts';\nimport type { Connection, OpenDialect } from '../types.ts';\nimport { createConnection } from './connection.ts';\nimport { DUCKDB_PACKAGE, duckdbApi } from './native.ts';\nimport { duckdbDialect } from './reconcile.ts';\nimport { registerFunctions } from './sql-functions.ts';\nimport { createStore } from './store.ts';\n\nexport const DB_FILENAME = 'cache.duckdb';\n// Independent of sqlite's SCHEMA_VERSION -- the two stores' cache shapes evolve separately (VARIANT frontmatter columns vs untyped).\n// The store name already joins the feature signature, so switching a config's `store` key rebuilds rather than reusing the other engine's cache.\nexport const SCHEMA_VERSION = '3';\n\nexport type { OpenResult };\n\n// The connection plus this store's own native handles (types.ts's OpenDialect<Handle>): the\n// instance owns the WAL and must outlive the connection borrowed from it.\ninterface DuckdbHandle {\n instance: DuckDBInstance;\n duckdb: DuckDBConnection;\n}\n\n// `content` is a plain table (not FTS-virtual): the fts index is built over it lazily, only when a lexical query runs (lexical.ts), and read directly for contains() verification either way.\n// No tokenizer resolution: this store always uses the fts extension's default (porter) stemmer.\nasync function ensureSchema(_handle: DuckdbHandle, conn: Connection, cfg: Config): Promise<void> {\n await conn.exec(`CREATE TABLE IF NOT EXISTS frontmatter (\"path\" TEXT PRIMARY KEY, \"_mtime\" DOUBLE, \"_ctime\" DOUBLE, \"_size\" INTEGER, \"_parse_error\" TEXT)`);\n await conn.exec(`CREATE TABLE IF NOT EXISTS content (\"path\" TEXT PRIMARY KEY, title TEXT, summary TEXT, text TEXT)`);\n await conn.exec(`CREATE TABLE IF NOT EXISTS preset_files (\"path\" TEXT, preset TEXT, PRIMARY KEY (\"path\", preset))`);\n await conn.exec('CREATE INDEX IF NOT EXISTS preset_files_preset ON preset_files(preset)');\n for (const feature of activeFeatures(cfg)) {\n // Native FLOAT[STORE_DIMS] instead of the embed feature's engine-neutral BLOB+scale DDL (vectors.ts). `scale` is kept, unused,\n // so the feature's shared reconcile-time INSERT/DELETE (features/embed.ts) names a column that exists on both stores.\n if (feature.name === 'embed') {\n await conn.exec(`CREATE TABLE IF NOT EXISTS embeddings (\"path\" TEXT, chunk INTEGER, start_line INTEGER, end_line INTEGER, scale REAL, vector FLOAT[${STORE_DIMS}], PRIMARY KEY (\"path\", chunk))`);\n continue;\n }\n await feature.schema(conn);\n }\n if ((await getMeta(conn, 'schema_version')) === null) await setMeta(conn, 'schema_version', SCHEMA_VERSION);\n if ((await getMeta(conn, 'features')) === null) await setMeta(conn, 'features', featureSignature(cfg, FEATURES));\n}\n\n// Order matters: the connection must be gone before the instance closes the WAL.\nasync function close(handle: DuckdbHandle): Promise<void> {\n handle.duckdb.disconnectSync();\n handle.instance.closeSync();\n}\n\nasync function connect(dbPath: string, _cfg: ResolvedConfig): Promise<{ handle: DuckdbHandle; conn: Connection }> {\n // Dynamic, not a top-level import: sqlite trees must never attempt to resolve this optional peer dependency, so nothing imports\n // it as a value until a duckdb tree opens (types-only imports are erased). Installed on first use if missing, shared with sql-functions.ts and vectors.ts via native.ts's duckdbApi.\n let DuckDBInstance: typeof import('@duckdb/node-api').DuckDBInstance;\n try {\n ({ DuckDBInstance } = await duckdbApi());\n } catch (err) {\n if (err instanceof SenseError) throw err;\n throw new SenseError('STORE_DEPENDENCY_MISSING', `store \"duckdb\" needs the ${DUCKDB_PACKAGE} package (${(err as Error).message})`);\n }\n\n let duckdb: DuckDBConnection;\n let instance: DuckDBInstance | undefined;\n try {\n // On-disk files default to an older storage format for cross-version compatibility, which rejects VARIANT columns (\"VARIANT\n // columns are not supported in storage versions prior to v1.5.0\"); this store's dynamic frontmatter columns need VARIANT (reconcile.ts), so the floor is pinned explicitly.\n instance = await DuckDBInstance.create(dbPath, { storage_compatibility_version: 'v1.5.0' });\n duckdb = await instance.connect();\n } catch (err) {\n // create() may have succeeded before connect() failed: close it, or its WAL stays open.\n instance?.closeSync();\n throw new SenseError('STORE_DEPENDENCY_MISSING', `store \"duckdb\" failed to open ${dbPath}: ${(err as Error).message}`);\n }\n // A throw below would leak the open instance, whose WAL then locks the .duckdb file undeletable on Windows.\n try {\n await registerFunctions(duckdb);\n const conn = createConnection(duckdb);\n return { handle: { instance, duckdb }, conn };\n } catch (err) {\n await close({ instance, duckdb });\n throw err;\n }\n}\n\n// This store's dialect (types.ts's OpenDialect) for the shared orchestration in store/open.ts.\nexport const duckdbOpenDialect: OpenDialect<DuckdbHandle> = {\n filename: DB_FILENAME,\n schemaVersion: SCHEMA_VERSION,\n reconcileDialect: duckdbDialect,\n connect,\n close,\n // duckdb's file lock spans the connection's life, and each platform words the refusal its own\n // way: posix \"Could not set lock on file ... Conflicting lock is held in <exe> (PID n)\", Windows\n // \"Cannot open file ... being used by another process\". Both are the same condition.\n isLocked: (err) => /Could not set lock on file|being used by another process/.test(err.message),\n ensureSchema,\n createStore: (handle, conn) => createStore(handle.instance, handle.duckdb, conn),\n};\n\nexport async function openDuckdb(cfg: ResolvedConfig): Promise<OpenResult> {\n return openWithDialect(cfg, duckdbOpenDialect);\n}\n"],"names":["DB_FILENAME","SCHEMA_VERSION","duckdbOpenDialect","openDuckdb","ensureSchema","_handle","conn","cfg","feature","exec","activeFeatures","name","STORE_DIMS","schema","getMeta","setMeta","featureSignature","FEATURES","close","handle","duckdb","disconnectSync","instance","closeSync","connect","dbPath","_cfg","DuckDBInstance","err","duckdbApi","SenseError","DUCKDB_PACKAGE","message","create","storage_compatibility_version","registerFunctions","createConnection","filename","schemaVersion","reconcileDialect","duckdbDialect","isLocked","test","createStore","openWithDialect"],"mappings":"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"}
|
|
@@ -9,6 +9,7 @@ Object.defineProperty(exports, "duckdbDialect", {
|
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
11
|
var _errorsts = require("../../errors.js");
|
|
12
|
+
var _sharedts = require("../shared.js");
|
|
12
13
|
var _lexicalts = require("./lexical.js");
|
|
13
14
|
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
14
15
|
try {
|
|
@@ -196,6 +197,34 @@ function reconcileContent(conn, touched, docs, _delta) {
|
|
|
196
197
|
});
|
|
197
198
|
})();
|
|
198
199
|
}
|
|
200
|
+
// DuckDB rejects more than one ALTER command per statement ("Parser Error: Only one ALTER
|
|
201
|
+
// command per statement is supported", measured), so every name's clause joins into one string
|
|
202
|
+
// and runs as a single exec() -- one column-add "leg" through the driver instead of `names.length`.
|
|
203
|
+
// VARIANT is the only type that can hold the mixed bigint/number/string/null shapes mapValue()
|
|
204
|
+
// produces for one key across files.
|
|
205
|
+
function addColumns(conn, names) {
|
|
206
|
+
return _async_to_generator(function() {
|
|
207
|
+
return _ts_generator(this, function(_state) {
|
|
208
|
+
switch(_state.label){
|
|
209
|
+
case 0:
|
|
210
|
+
if (names.length === 0) return [
|
|
211
|
+
2
|
|
212
|
+
];
|
|
213
|
+
return [
|
|
214
|
+
4,
|
|
215
|
+
conn.exec(names.map(function(name) {
|
|
216
|
+
return "ALTER TABLE frontmatter ADD COLUMN ".concat((0, _sharedts.quoteIdent)(name), " VARIANT");
|
|
217
|
+
}).join('; '))
|
|
218
|
+
];
|
|
219
|
+
case 1:
|
|
220
|
+
_state.sent();
|
|
221
|
+
return [
|
|
222
|
+
2
|
|
223
|
+
];
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
})();
|
|
227
|
+
}
|
|
199
228
|
var duckdbDialect = {
|
|
200
229
|
beginMode: function beginMode() {
|
|
201
230
|
return 'BEGIN';
|
|
@@ -205,11 +234,7 @@ var duckdbDialect = {
|
|
|
205
234
|
throw new _errorsts.SenseError('COLUMN_LIMIT', "frontmatter would need ".concat(count, " columns, crossing this store's sanity limit (").concat(MAX_FRONTMATTER_COLUMNS, "). Narrow the presets' include globs so fewer/other files are indexed, or fix whatever is generating unbounded frontmatter keys."));
|
|
206
235
|
}
|
|
207
236
|
},
|
|
208
|
-
|
|
209
|
-
// the mixed bigint/number/string/null shapes mapValue() produces for one key across files.
|
|
210
|
-
columnTypeSuffix: function columnTypeSuffix() {
|
|
211
|
-
return ' VARIANT';
|
|
212
|
-
},
|
|
237
|
+
addColumns: addColumns,
|
|
213
238
|
reconcileContent: reconcileContent
|
|
214
239
|
};
|
|
215
240
|
/* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/reconcile.ts"],"sourcesContent":["import { SenseError } from '../../errors.ts';\nimport type { ReconcileDelta } from '../../features/types.ts';\nimport type { ParsedDoc } from '../../scan/index.ts';\nimport type { Connection, ReconcileDialect } from '../types.ts';\nimport { markContentStale } from './lexical.ts';\n\n// This store's dialect (types.ts's ReconcileDialect) for the shared orchestration in\n// store/reconcile.ts. `content` is a plain table, not FTS-virtual, so rows are maintained here\n// unconditionally; DuckDB's ALTER TABLE needs a declared type, so every dynamic frontmatter\n// column is VARIANT (holds mapValue()'s mixed JS types for one key across files).\n\n// No rowid coupling needed (unlike sqlite's content, which links to frontmatter's rowid):\n// `path` is content's own primary key, so this is a plain per-doc row.\nconst INSERT_CONTENT_SQL = `INSERT INTO content (\"path\", title, summary, text) VALUES (?, ?, ?, ?)`;\n\nfunction contentRow(doc: ParsedDoc): unknown[] {\n return [doc.relPath, doc.search.title, doc.search.summary, doc.search.text];\n}\n\n// No compile-time column cap in DuckDB (unlike SQLite's SQLITE_MAX_COLUMN); kept as a sanity fence anyway\n// so a runaway frontmatter generator fails with a clear message instead of an unbounded ALTER TABLE loop.\nconst MAX_FRONTMATTER_COLUMNS = 10_000;\n\nasync function reconcileContent(conn: Connection, touched: string[], docs: ParsedDoc[], _delta: ReconcileDelta): Promise<void> {\n if (touched.length > 0)\n await conn.runBatch(\n 'DELETE FROM content WHERE \"path\" = ?',\n touched.map((p) => [p])\n );\n if (docs.length > 0) await conn.runBatch(INSERT_CONTENT_SQL, docs.map(contentRow));\n // content changed: the fts index is rebuilt lazily, on the next lexical query that needs it,\n // not here (lexical.ts's FtsIndexState).\n markContentStale(conn);\n}\n\nexport const duckdbDialect: ReconcileDialect = {\n beginMode: () => 'BEGIN',\n checkColumnLimit(count) {\n if (count > MAX_FRONTMATTER_COLUMNS) {\n throw new SenseError('COLUMN_LIMIT', `frontmatter would need ${count} columns, crossing this store's sanity limit (${MAX_FRONTMATTER_COLUMNS}). Narrow the presets' include globs so fewer/other files are indexed, or fix whatever is generating unbounded frontmatter keys.`);\n }\n },\n
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/reconcile.ts"],"sourcesContent":["import { SenseError } from '../../errors.ts';\nimport type { ReconcileDelta } from '../../features/types.ts';\nimport type { ParsedDoc } from '../../scan/index.ts';\nimport { quoteIdent } from '../shared.ts';\nimport type { Connection, ReconcileDialect } from '../types.ts';\nimport { markContentStale } from './lexical.ts';\n\n// This store's dialect (types.ts's ReconcileDialect) for the shared orchestration in\n// store/reconcile.ts. `content` is a plain table, not FTS-virtual, so rows are maintained here\n// unconditionally; DuckDB's ALTER TABLE needs a declared type, so every dynamic frontmatter\n// column is VARIANT (holds mapValue()'s mixed JS types for one key across files).\n\n// No rowid coupling needed (unlike sqlite's content, which links to frontmatter's rowid):\n// `path` is content's own primary key, so this is a plain per-doc row.\nconst INSERT_CONTENT_SQL = `INSERT INTO content (\"path\", title, summary, text) VALUES (?, ?, ?, ?)`;\n\nfunction contentRow(doc: ParsedDoc): unknown[] {\n return [doc.relPath, doc.search.title, doc.search.summary, doc.search.text];\n}\n\n// No compile-time column cap in DuckDB (unlike SQLite's SQLITE_MAX_COLUMN); kept as a sanity fence anyway\n// so a runaway frontmatter generator fails with a clear message instead of an unbounded ALTER TABLE loop.\nconst MAX_FRONTMATTER_COLUMNS = 10_000;\n\nasync function reconcileContent(conn: Connection, touched: string[], docs: ParsedDoc[], _delta: ReconcileDelta): Promise<void> {\n if (touched.length > 0)\n await conn.runBatch(\n 'DELETE FROM content WHERE \"path\" = ?',\n touched.map((p) => [p])\n );\n if (docs.length > 0) await conn.runBatch(INSERT_CONTENT_SQL, docs.map(contentRow));\n // content changed: the fts index is rebuilt lazily, on the next lexical query that needs it,\n // not here (lexical.ts's FtsIndexState).\n markContentStale(conn);\n}\n\n// DuckDB rejects more than one ALTER command per statement (\"Parser Error: Only one ALTER\n// command per statement is supported\", measured), so every name's clause joins into one string\n// and runs as a single exec() -- one column-add \"leg\" through the driver instead of `names.length`.\n// VARIANT is the only type that can hold the mixed bigint/number/string/null shapes mapValue()\n// produces for one key across files.\nasync function addColumns(conn: Connection, names: string[]): Promise<void> {\n if (names.length === 0) return;\n await conn.exec(names.map((name) => `ALTER TABLE frontmatter ADD COLUMN ${quoteIdent(name)} VARIANT`).join('; '));\n}\n\nexport const duckdbDialect: ReconcileDialect = {\n beginMode: () => 'BEGIN',\n checkColumnLimit(count) {\n if (count > MAX_FRONTMATTER_COLUMNS) {\n throw new SenseError('COLUMN_LIMIT', `frontmatter would need ${count} columns, crossing this store's sanity limit (${MAX_FRONTMATTER_COLUMNS}). Narrow the presets' include globs so fewer/other files are indexed, or fix whatever is generating unbounded frontmatter keys.`);\n }\n },\n addColumns,\n reconcileContent,\n};\n"],"names":["duckdbDialect","INSERT_CONTENT_SQL","contentRow","doc","relPath","search","title","summary","text","MAX_FRONTMATTER_COLUMNS","reconcileContent","conn","touched","docs","_delta","length","runBatch","map","p","markContentStale","addColumns","names","exec","name","quoteIdent","join","beginMode","checkColumnLimit","count","SenseError"],"mappings":";;;;+BA8CaA;;;eAAAA;;;wBA9Cc;wBAGA;yBAEM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEjC,qFAAqF;AACrF,+FAA+F;AAC/F,4FAA4F;AAC5F,kFAAkF;AAElF,0FAA0F;AAC1F,uEAAuE;AACvE,IAAMC,qBAAqB;AAE3B,SAASC,WAAWC,GAAc;IAChC,OAAO;QAACA,IAAIC,OAAO;QAAED,IAAIE,MAAM,CAACC,KAAK;QAAEH,IAAIE,MAAM,CAACE,OAAO;QAAEJ,IAAIE,MAAM,CAACG,IAAI;KAAC;AAC7E;AAEA,0GAA0G;AAC1G,0GAA0G;AAC1G,IAAMC,0BAA0B;AAEhC,SAAeC,iBAAiBC,IAAgB,EAAEC,OAAiB,EAAEC,IAAiB,EAAEC,MAAsB;;;;;yBACxGF,CAAAA,QAAQG,MAAM,GAAG,CAAA,GAAjBH;;;;oBACF;;wBAAMD,KAAKK,QAAQ,CACjB,wCACAJ,QAAQK,GAAG,CAAC,SAACC;mCAAM;gCAACA;6BAAE;;;;oBAFxB;;;yBAIEL,CAAAA,KAAKE,MAAM,GAAG,CAAA,GAAdF;;;;oBAAiB;;wBAAMF,KAAKK,QAAQ,CAACf,oBAAoBY,KAAKI,GAAG,CAACf;;;oBAAjD;;;oBACrB,6FAA6F;oBAC7F,yCAAyC;oBACzCiB,IAAAA,2BAAgB,EAACR;;;;;;IACnB;;AAEA,0FAA0F;AAC1F,+FAA+F;AAC/F,oGAAoG;AACpG,+FAA+F;AAC/F,qCAAqC;AACrC,SAAeS,WAAWT,IAAgB,EAAEU,KAAe;;;;;oBACzD,IAAIA,MAAMN,MAAM,KAAK,GAAG;;;oBACxB;;wBAAMJ,KAAKW,IAAI,CAACD,MAAMJ,GAAG,CAAC,SAACM;mCAAS,AAAC,sCAAsD,OAAjBC,IAAAA,oBAAU,EAACD,OAAM;2BAAWE,IAAI,CAAC;;;oBAA3G;;;;;;IACF;;AAEO,IAAMzB,gBAAkC;IAC7C0B,WAAW,SAAXA;eAAiB;;IACjBC,kBAAAA,SAAAA,iBAAiBC,KAAK;QACpB,IAAIA,QAAQnB,yBAAyB;YACnC,MAAM,IAAIoB,oBAAU,CAAC,gBAAgB,AAAC,0BAA+EpB,OAAtDmB,OAAM,kDAAwE,OAAxBnB,yBAAwB;QAC/I;IACF;IACAW,YAAAA;IACAV,kBAAAA;AACF"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// Decomposition of the `embed:` featureSignature segment (config/access.ts's featureSignature,
|
|
2
|
+
// features/embed.ts's signature()), for open()'s narrow embed-invalidation routing.
|
|
3
|
+
"use strict";
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
Object.defineProperty(exports, "classifyEmbedChange", {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
get: function() {
|
|
10
|
+
return classifyEmbedChange;
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
function _array_like_to_array(arr, len) {
|
|
14
|
+
if (len == null || len > arr.length) len = arr.length;
|
|
15
|
+
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
|
16
|
+
return arr2;
|
|
17
|
+
}
|
|
18
|
+
function _array_with_holes(arr) {
|
|
19
|
+
if (Array.isArray(arr)) return arr;
|
|
20
|
+
}
|
|
21
|
+
function _iterable_to_array_limit(arr, i) {
|
|
22
|
+
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
|
|
23
|
+
if (_i == null) return;
|
|
24
|
+
var _arr = [];
|
|
25
|
+
var _n = true;
|
|
26
|
+
var _d = false;
|
|
27
|
+
var _s, _e;
|
|
28
|
+
try {
|
|
29
|
+
for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
|
|
30
|
+
_arr.push(_s.value);
|
|
31
|
+
if (i && _arr.length === i) break;
|
|
32
|
+
}
|
|
33
|
+
} catch (err) {
|
|
34
|
+
_d = true;
|
|
35
|
+
_e = err;
|
|
36
|
+
} finally{
|
|
37
|
+
try {
|
|
38
|
+
if (!_n && _i["return"] != null) _i["return"]();
|
|
39
|
+
} finally{
|
|
40
|
+
if (_d) throw _e;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return _arr;
|
|
44
|
+
}
|
|
45
|
+
function _non_iterable_rest() {
|
|
46
|
+
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
47
|
+
}
|
|
48
|
+
function _sliced_to_array(arr, i) {
|
|
49
|
+
return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
|
|
50
|
+
}
|
|
51
|
+
function _unsupported_iterable_to_array(o, minLen) {
|
|
52
|
+
if (!o) return;
|
|
53
|
+
if (typeof o === "string") return _array_like_to_array(o, minLen);
|
|
54
|
+
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
55
|
+
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
56
|
+
if (n === "Map" || n === "Set") return Array.from(n);
|
|
57
|
+
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
|
|
58
|
+
}
|
|
59
|
+
// One embed segment's provider/model/chunkVersion, ignoring any trailing `@identity`. `embed:off`
|
|
60
|
+
// and any segment not in that exact shape return null, so the caller falls back to a full rebuild.
|
|
61
|
+
function parseEmbedSegment(sig) {
|
|
62
|
+
var part = sig.split('|').find(function(p) {
|
|
63
|
+
return p.startsWith('embed:');
|
|
64
|
+
});
|
|
65
|
+
if (part === undefined || part === 'embed:off') return null;
|
|
66
|
+
var at = part.indexOf('@');
|
|
67
|
+
var body = at === -1 ? part : part.slice(0, at);
|
|
68
|
+
var match = /^embed:(static|openai|cohere):(.+):(chunk:v\d+(?::\d+)?)$/.exec(body);
|
|
69
|
+
if (!match) return null;
|
|
70
|
+
var _match = _sliced_to_array(match, 4), provider = _match[1], model = _match[2], chunkVersion = _match[3];
|
|
71
|
+
return {
|
|
72
|
+
provider: provider,
|
|
73
|
+
model: model,
|
|
74
|
+
chunkVersion: chunkVersion
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function classifyEmbedChange(before, after) {
|
|
78
|
+
var b = parseEmbedSegment(before);
|
|
79
|
+
var a = parseEmbedSegment(after);
|
|
80
|
+
if (b === null || a === null) return null;
|
|
81
|
+
if (b.chunkVersion !== a.chunkVersion) return 'chunk';
|
|
82
|
+
if (b.provider !== a.provider || b.model !== a.model) return 'model';
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
/* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/embed-scope.ts"],"sourcesContent":["// Decomposition of the `embed:` featureSignature segment (config/access.ts's featureSignature,\n// features/embed.ts's signature()), for open()'s narrow embed-invalidation routing.\n\nexport type EmbedChangeKind = 'model' | 'chunk';\n\ninterface EmbedSegment {\n provider: string;\n model: string;\n chunkVersion: string;\n}\n\n// One embed segment's provider/model/chunkVersion, ignoring any trailing `@identity`. `embed:off`\n// and any segment not in that exact shape return null, so the caller falls back to a full rebuild.\nfunction parseEmbedSegment(sig: string): EmbedSegment | null {\n const part = sig.split('|').find((p) => p.startsWith('embed:'));\n if (part === undefined || part === 'embed:off') return null;\n const at = part.indexOf('@');\n const body = at === -1 ? part : part.slice(0, at);\n const match = /^embed:(static|openai|cohere):(.+):(chunk:v\\d+(?::\\d+)?)$/.exec(body);\n if (!match) return null;\n const [, provider, model, chunkVersion] = match;\n return { provider, model, chunkVersion };\n}\n\n// 'chunk' when chunkTokens or the chunk version moved (boundaries changed, embeddings rebuild);\n// 'model' when only the provider or model moved (rows unchanged, values stale); null otherwise.\nexport function classifyEmbedChange(before: string, after: string): EmbedChangeKind | null {\n const b = parseEmbedSegment(before);\n const a = parseEmbedSegment(after);\n if (b === null || a === null) return null;\n if (b.chunkVersion !== a.chunkVersion) return 'chunk';\n if (b.provider !== a.provider || b.model !== a.model) return 'model';\n return null;\n}\n"],"names":["classifyEmbedChange","parseEmbedSegment","sig","part","split","find","p","startsWith","undefined","at","indexOf","body","slice","match","exec","provider","model","chunkVersion","before","after","b","a"],"mappings":"AAAA,+FAA+F;AAC/F,oFAAoF;;;;;+BAyBpEA;;;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAfhB,kGAAkG;AAClG,mGAAmG;AACnG,SAASC,kBAAkBC,GAAW;IACpC,IAAMC,OAAOD,IAAIE,KAAK,CAAC,KAAKC,IAAI,CAAC,SAACC;eAAMA,EAAEC,UAAU,CAAC;;IACrD,IAAIJ,SAASK,aAAaL,SAAS,aAAa,OAAO;IACvD,IAAMM,KAAKN,KAAKO,OAAO,CAAC;IACxB,IAAMC,OAAOF,OAAO,CAAC,IAAIN,OAAOA,KAAKS,KAAK,CAAC,GAAGH;IAC9C,IAAMI,QAAQ,4DAA4DC,IAAI,CAACH;IAC/E,IAAI,CAACE,OAAO,OAAO;IACnB,IAA0CA,0BAAAA,WAAjCE,WAAiCF,WAAvBG,QAAuBH,WAAhBI,eAAgBJ;IAC1C,OAAO;QAAEE,UAAAA;QAAUC,OAAAA;QAAOC,cAAAA;IAAa;AACzC;AAIO,SAASjB,oBAAoBkB,MAAc,EAAEC,KAAa;IAC/D,IAAMC,IAAInB,kBAAkBiB;IAC5B,IAAMG,IAAIpB,kBAAkBkB;IAC5B,IAAIC,MAAM,QAAQC,MAAM,MAAM,OAAO;IACrC,IAAID,EAAEH,YAAY,KAAKI,EAAEJ,YAAY,EAAE,OAAO;IAC9C,IAAIG,EAAEL,QAAQ,KAAKM,EAAEN,QAAQ,IAAIK,EAAEJ,KAAK,KAAKK,EAAEL,KAAK,EAAE,OAAO;IAC7D,OAAO;AACT"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FeatureName } from '../config/index.js';
|
|
2
|
+
export declare const NARROW_FEATURE_TABLE: Readonly<Record<string, string>>;
|
|
3
|
+
export interface FeatureToggle {
|
|
4
|
+
name: FeatureName;
|
|
5
|
+
turnedOn: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function isFeatureOnlyChange(changedKeys: ReadonlySet<string>): boolean;
|
|
8
|
+
export declare function classifyFeatureToggles(before: string, after: string, changedKeys: ReadonlySet<string>): FeatureToggle[] | null;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FeatureName } from '../config/index.js';
|
|
2
|
+
export declare const NARROW_FEATURE_TABLE: Readonly<Record<string, string>>;
|
|
3
|
+
export interface FeatureToggle {
|
|
4
|
+
name: FeatureName;
|
|
5
|
+
turnedOn: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function isFeatureOnlyChange(changedKeys: ReadonlySet<string>): boolean;
|
|
8
|
+
export declare function classifyFeatureToggles(before: string, after: string, changedKeys: ReadonlySet<string>): FeatureToggle[] | null;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
get NARROW_FEATURE_TABLE () {
|
|
13
|
+
return NARROW_FEATURE_TABLE;
|
|
14
|
+
},
|
|
15
|
+
get classifyFeatureToggles () {
|
|
16
|
+
return classifyFeatureToggles;
|
|
17
|
+
},
|
|
18
|
+
get isFeatureOnlyChange () {
|
|
19
|
+
return isFeatureOnlyChange;
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
function _array_like_to_array(arr, len) {
|
|
23
|
+
if (len == null || len > arr.length) len = arr.length;
|
|
24
|
+
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
|
25
|
+
return arr2;
|
|
26
|
+
}
|
|
27
|
+
function _array_without_holes(arr) {
|
|
28
|
+
if (Array.isArray(arr)) return _array_like_to_array(arr);
|
|
29
|
+
}
|
|
30
|
+
function _iterable_to_array(iter) {
|
|
31
|
+
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) {
|
|
32
|
+
return Array.from(iter);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function _non_iterable_spread() {
|
|
36
|
+
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
37
|
+
}
|
|
38
|
+
function _to_consumable_array(arr) {
|
|
39
|
+
return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
|
|
40
|
+
}
|
|
41
|
+
function _unsupported_iterable_to_array(o, minLen) {
|
|
42
|
+
if (!o) return;
|
|
43
|
+
if (typeof o === "string") return _array_like_to_array(o, minLen);
|
|
44
|
+
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
45
|
+
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
46
|
+
if (n === "Map" || n === "Set") return Array.from(n);
|
|
47
|
+
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
|
|
48
|
+
}
|
|
49
|
+
var NARROW_FEATURE_TABLE = {
|
|
50
|
+
tags: 'tags',
|
|
51
|
+
sections: 'sections',
|
|
52
|
+
links: 'links'
|
|
53
|
+
};
|
|
54
|
+
// links feeds rank's afterReconcile pass, so a links toggle always co-changes the `feature:rank`
|
|
55
|
+
// segment too (featureEnabled's dependency); both are narrow-supported and builder.ts applies
|
|
56
|
+
// them together. A changed set naming any other feature falls through to the existing full clear.
|
|
57
|
+
var NARROW_FEATURE_NAMES = new Set(_to_consumable_array(Object.keys(NARROW_FEATURE_TABLE)).concat([
|
|
58
|
+
'rank'
|
|
59
|
+
]));
|
|
60
|
+
function isFeatureOnlyChange(changedKeys) {
|
|
61
|
+
return changedKeys.size > 0 && _to_consumable_array(changedKeys).every(function(key) {
|
|
62
|
+
return key.startsWith('feature:') && NARROW_FEATURE_NAMES.has(key.slice('feature:'.length));
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
// One feature segment's old on/off, read back out of a stored `feature:<name>:on|off` segment.
|
|
66
|
+
// Anything not in that exact shape returns null so the caller falls back to a full rebuild.
|
|
67
|
+
function parseOnOff(sig, name) {
|
|
68
|
+
var part = sig.split('|').find(function(p) {
|
|
69
|
+
return p.startsWith("feature:".concat(name, ":"));
|
|
70
|
+
});
|
|
71
|
+
if (part === undefined) return null;
|
|
72
|
+
var fields = part.split(':');
|
|
73
|
+
if (fields.length !== 3 || fields[2] !== 'on' && fields[2] !== 'off') return null;
|
|
74
|
+
return fields[2] === 'on';
|
|
75
|
+
}
|
|
76
|
+
function classifyFeatureToggles(before, after, changedKeys) {
|
|
77
|
+
var toggles = [];
|
|
78
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
79
|
+
try {
|
|
80
|
+
for(var _iterator = changedKeys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
81
|
+
var key = _step.value;
|
|
82
|
+
var name = key.slice('feature:'.length);
|
|
83
|
+
var wasOn = parseOnOff(before, name);
|
|
84
|
+
var isOn = parseOnOff(after, name);
|
|
85
|
+
if (wasOn === null || isOn === null || wasOn === isOn) return null;
|
|
86
|
+
toggles.push({
|
|
87
|
+
name: name,
|
|
88
|
+
turnedOn: isOn
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
} catch (err) {
|
|
92
|
+
_didIteratorError = true;
|
|
93
|
+
_iteratorError = err;
|
|
94
|
+
} finally{
|
|
95
|
+
try {
|
|
96
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
97
|
+
_iterator.return();
|
|
98
|
+
}
|
|
99
|
+
} finally{
|
|
100
|
+
if (_didIteratorError) {
|
|
101
|
+
throw _iteratorError;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return toggles;
|
|
106
|
+
}
|
|
107
|
+
/* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/feature-scope.ts"],"sourcesContent":["import type { FeatureName } from '../config/index.ts';\n\n// Decomposition of the `feature:<name>:<on|off>` featureSignature segments (config/access.ts's\n// featureSignature), for open()'s narrow feature-toggle invalidation routing.\n\n// Every narrow-supported feature but rank owns one dedicated table, dropped and (turning on)\n// fully re-derived. rank has no table -- it writes PageRank into frontmatter's own `_rank`\n// column -- so builder.ts handles it, and the links/rank pair, as special cases outside this map.\nexport const NARROW_FEATURE_TABLE: Readonly<Record<string, string>> = { tags: 'tags', sections: 'sections', links: 'links' };\n\n// links feeds rank's afterReconcile pass, so a links toggle always co-changes the `feature:rank`\n// segment too (featureEnabled's dependency); both are narrow-supported and builder.ts applies\n// them together. A changed set naming any other feature falls through to the existing full clear.\nconst NARROW_FEATURE_NAMES: ReadonlySet<string> = new Set([...Object.keys(NARROW_FEATURE_TABLE), 'rank']);\n\nexport interface FeatureToggle {\n name: FeatureName;\n // true: was off, now on (must fully re-derive). false: was on, now off (drop its rows).\n turnedOn: boolean;\n}\n\n// Every changed key is a `feature:<name>` segment for a narrow-supported feature.\nexport function isFeatureOnlyChange(changedKeys: ReadonlySet<string>): boolean {\n return changedKeys.size > 0 && [...changedKeys].every((key) => key.startsWith('feature:') && NARROW_FEATURE_NAMES.has(key.slice('feature:'.length)));\n}\n\n// One feature segment's old on/off, read back out of a stored `feature:<name>:on|off` segment.\n// Anything not in that exact shape returns null so the caller falls back to a full rebuild.\nfunction parseOnOff(sig: string, name: string): boolean | null {\n const part = sig.split('|').find((p) => p.startsWith(`feature:${name}:`));\n if (part === undefined) return null;\n const fields = part.split(':');\n if (fields.length !== 3 || (fields[2] !== 'on' && fields[2] !== 'off')) return null;\n return fields[2] === 'on';\n}\n\n// Old-vs-new on/off for every changed feature key, or null when a segment can't be parsed back\n// out of `before` or `after`, or when it parses to the same state on both sides (should never\n// happen for a genuinely changed key) -- either way the caller takes the full rebuild.\nexport function classifyFeatureToggles(before: string, after: string, changedKeys: ReadonlySet<string>): FeatureToggle[] | null {\n const toggles: FeatureToggle[] = [];\n for (const key of changedKeys) {\n const name = key.slice('feature:'.length) as FeatureName;\n const wasOn = parseOnOff(before, name);\n const isOn = parseOnOff(after, name);\n if (wasOn === null || isOn === null || wasOn === isOn) return null;\n toggles.push({ name, turnedOn: isOn });\n }\n return toggles;\n}\n"],"names":["NARROW_FEATURE_TABLE","classifyFeatureToggles","isFeatureOnlyChange","tags","sections","links","NARROW_FEATURE_NAMES","Set","Object","keys","changedKeys","size","every","key","startsWith","has","slice","length","parseOnOff","sig","name","part","split","find","p","undefined","fields","before","after","toggles","wasOn","isOn","push","turnedOn"],"mappings":";;;;;;;;;;;QAQaA;eAAAA;;QA+BGC;eAAAA;;QAjBAC;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAdT,IAAMF,uBAAyD;IAAEG,MAAM;IAAQC,UAAU;IAAYC,OAAO;AAAQ;AAE3H,iGAAiG;AACjG,8FAA8F;AAC9F,kGAAkG;AAClG,IAAMC,uBAA4C,IAAIC,IAAI,AAAC,qBAAGC,OAAOC,IAAI,CAACT,8BAAhB;IAAuC;CAAO;AASjG,SAASE,oBAAoBQ,WAAgC;IAClE,OAAOA,YAAYC,IAAI,GAAG,KAAK,AAAC,qBAAGD,aAAaE,KAAK,CAAC,SAACC;eAAQA,IAAIC,UAAU,CAAC,eAAeR,qBAAqBS,GAAG,CAACF,IAAIG,KAAK,CAAC,WAAWC,MAAM;;AACnJ;AAEA,+FAA+F;AAC/F,4FAA4F;AAC5F,SAASC,WAAWC,GAAW,EAAEC,IAAY;IAC3C,IAAMC,OAAOF,IAAIG,KAAK,CAAC,KAAKC,IAAI,CAAC,SAACC;eAAMA,EAAEV,UAAU,CAAC,AAAC,WAAe,OAALM,MAAK;;IACrE,IAAIC,SAASI,WAAW,OAAO;IAC/B,IAAMC,SAASL,KAAKC,KAAK,CAAC;IAC1B,IAAII,OAAOT,MAAM,KAAK,KAAMS,MAAM,CAAC,EAAE,KAAK,QAAQA,MAAM,CAAC,EAAE,KAAK,OAAQ,OAAO;IAC/E,OAAOA,MAAM,CAAC,EAAE,KAAK;AACvB;AAKO,SAASzB,uBAAuB0B,MAAc,EAAEC,KAAa,EAAElB,WAAgC;IACpG,IAAMmB,UAA2B,EAAE;QAC9B,kCAAA,2BAAA;;QAAL,QAAK,YAAanB,gCAAb,SAAA,6BAAA,QAAA,yBAAA,iCAA0B;YAA1B,IAAMG,MAAN;YACH,IAAMO,OAAOP,IAAIG,KAAK,CAAC,WAAWC,MAAM;YACxC,IAAMa,QAAQZ,WAAWS,QAAQP;YACjC,IAAMW,OAAOb,WAAWU,OAAOR;YAC/B,IAAIU,UAAU,QAAQC,SAAS,QAAQD,UAAUC,MAAM,OAAO;YAC9DF,QAAQG,IAAI,CAAC;gBAAEZ,MAAAA;gBAAMa,UAAUF;YAAK;QACtC;;QANK;QAAA;;;iBAAA,6BAAA;gBAAA;;;gBAAA;sBAAA;;;;IAOL,OAAOF;AACT"}
|