@threadbase-sh/scanner 0.11.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +69 -43
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +77 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +70 -42
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -834,6 +834,14 @@ import { createReadStream as createReadStream2 } from "fs";
|
|
|
834
834
|
import { stat } from "fs/promises";
|
|
835
835
|
import { basename as basename3 } from "path";
|
|
836
836
|
import { createInterface as createInterface2 } from "readline";
|
|
837
|
+
|
|
838
|
+
// src/canonical-path.ts
|
|
839
|
+
import { sep } from "path";
|
|
840
|
+
function canonicalPath(p) {
|
|
841
|
+
return sep === "\\" ? p.replace(/\//g, "\\") : p;
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
// src/providers/codex-cli.ts
|
|
837
845
|
var CodexCliProvider = class {
|
|
838
846
|
name = CODEX_CLI_PROVIDER;
|
|
839
847
|
async discover(roots) {
|
|
@@ -855,7 +863,7 @@ var CodexCliProvider = class {
|
|
|
855
863
|
for (const filePath of paths) {
|
|
856
864
|
try {
|
|
857
865
|
const s = await stat(filePath);
|
|
858
|
-
if (s.size > 0) results.push({ filePath, account: "codex" });
|
|
866
|
+
if (s.size > 0) results.push({ filePath: canonicalPath(filePath), account: "codex" });
|
|
859
867
|
} catch (err) {
|
|
860
868
|
log.warn({ filePath, err }, "codex discovery: stat failed");
|
|
861
869
|
}
|
|
@@ -1098,7 +1106,7 @@ async function discoverJsonlFiles(dirs, onProgress) {
|
|
|
1098
1106
|
if (size < 0) {
|
|
1099
1107
|
skippedInaccessible++;
|
|
1100
1108
|
} else if (size > 0) {
|
|
1101
|
-
results.push({ filePath, account });
|
|
1109
|
+
results.push({ filePath: canonicalPath(filePath), account });
|
|
1102
1110
|
kept++;
|
|
1103
1111
|
} else {
|
|
1104
1112
|
skippedEmpty++;
|
|
@@ -1163,7 +1171,7 @@ var ThreadbaseProvider = class {
|
|
|
1163
1171
|
import { EventEmitter } from "events";
|
|
1164
1172
|
import { closeSync as closeSync2, openSync as openSync2, readSync as readSync2, statSync as statSync3 } from "fs";
|
|
1165
1173
|
import { homedir as homedir2 } from "os";
|
|
1166
|
-
import { join as
|
|
1174
|
+
import { join as join5 } from "path";
|
|
1167
1175
|
|
|
1168
1176
|
// src/cache.ts
|
|
1169
1177
|
var LRUCache = class {
|
|
@@ -1718,6 +1726,7 @@ function openDatabase(dbPath) {
|
|
|
1718
1726
|
|
|
1719
1727
|
// src/persistent/dir-watermark.ts
|
|
1720
1728
|
import { readdir, stat as stat3 } from "fs/promises";
|
|
1729
|
+
import { dirname as dirname4, join as join4 } from "path";
|
|
1721
1730
|
var FULL_RECONCILE_EVERY_N_SCANS = 20;
|
|
1722
1731
|
async function discoverJsonlFilesGated(dirs, files, scannedDirs, options = {}) {
|
|
1723
1732
|
const log = getLogger();
|
|
@@ -1727,7 +1736,7 @@ async function discoverJsonlFilesGated(dirs, files, scannedDirs, options = {}) {
|
|
|
1727
1736
|
const results = [];
|
|
1728
1737
|
for (const rawDir of dirs) {
|
|
1729
1738
|
const { account } = rawDir;
|
|
1730
|
-
const projectsDir = rawDir.projectsDir
|
|
1739
|
+
const projectsDir = canonicalPath(rawDir.projectsDir);
|
|
1731
1740
|
const resolved = await resolveProjectDirs(projectsDir, scannedDirs);
|
|
1732
1741
|
if (resolved === null) continue;
|
|
1733
1742
|
for (const projectDir of resolved.entries) {
|
|
@@ -1788,11 +1797,10 @@ async function resolveProjectDirs(projectsDir, scannedDirs) {
|
|
|
1788
1797
|
return { entries, commitRoot: { mtimeMs: rootStat.mtimeMs } };
|
|
1789
1798
|
}
|
|
1790
1799
|
function dirnameOf(filePath) {
|
|
1791
|
-
|
|
1792
|
-
return idx === -1 ? filePath : filePath.slice(0, idx);
|
|
1800
|
+
return dirname4(filePath);
|
|
1793
1801
|
}
|
|
1794
1802
|
function joinPath(dir, name) {
|
|
1795
|
-
return
|
|
1803
|
+
return join4(dir, name);
|
|
1796
1804
|
}
|
|
1797
1805
|
|
|
1798
1806
|
// src/persistent/repositories/checkpoints.repo.ts
|
|
@@ -1802,15 +1810,16 @@ var CheckpointsRepo = class {
|
|
|
1802
1810
|
}
|
|
1803
1811
|
db;
|
|
1804
1812
|
replaceAll(sourcePath, checkpoints) {
|
|
1813
|
+
const path = canonicalPath(sourcePath);
|
|
1805
1814
|
const tx = this.db.transaction(() => {
|
|
1806
|
-
this.db.prepare("DELETE FROM message_checkpoints WHERE source_path = ?").run(
|
|
1815
|
+
this.db.prepare("DELETE FROM message_checkpoints WHERE source_path = ?").run(path);
|
|
1807
1816
|
const insert = this.db.prepare(
|
|
1808
1817
|
`INSERT INTO message_checkpoints
|
|
1809
1818
|
(source_path, message_index, byte_offset, line_number, parser_state)
|
|
1810
1819
|
VALUES (?, ?, ?, ?, ?)`
|
|
1811
1820
|
);
|
|
1812
1821
|
for (const c of checkpoints) {
|
|
1813
|
-
insert.run(
|
|
1822
|
+
insert.run(path, c.messageIndex, c.byteOffset, c.lineNumber, JSON.stringify(c.state));
|
|
1814
1823
|
}
|
|
1815
1824
|
});
|
|
1816
1825
|
tx();
|
|
@@ -1819,6 +1828,7 @@ var CheckpointsRepo = class {
|
|
|
1819
1828
|
// the chain covering the immutable prefix (Kafka sparse-index style); rows are
|
|
1820
1829
|
// only ever removed on truncation/replace or deletion.
|
|
1821
1830
|
append(sourcePath, checkpoints) {
|
|
1831
|
+
const path = canonicalPath(sourcePath);
|
|
1822
1832
|
const tx = this.db.transaction(() => {
|
|
1823
1833
|
const insert = this.db.prepare(
|
|
1824
1834
|
`INSERT INTO message_checkpoints
|
|
@@ -1826,7 +1836,7 @@ var CheckpointsRepo = class {
|
|
|
1826
1836
|
VALUES (?, ?, ?, ?, ?)`
|
|
1827
1837
|
);
|
|
1828
1838
|
for (const c of checkpoints) {
|
|
1829
|
-
insert.run(
|
|
1839
|
+
insert.run(path, c.messageIndex, c.byteOffset, c.lineNumber, JSON.stringify(c.state));
|
|
1830
1840
|
}
|
|
1831
1841
|
});
|
|
1832
1842
|
tx();
|
|
@@ -1839,7 +1849,7 @@ var CheckpointsRepo = class {
|
|
|
1839
1849
|
FROM message_checkpoints
|
|
1840
1850
|
WHERE source_path = ? AND message_index <= ?
|
|
1841
1851
|
ORDER BY message_index DESC LIMIT 1`
|
|
1842
|
-
).get(sourcePath, messageIndex);
|
|
1852
|
+
).get(canonicalPath(sourcePath), messageIndex);
|
|
1843
1853
|
return row ? toCheckpoint(row) : null;
|
|
1844
1854
|
}
|
|
1845
1855
|
// The highest-index checkpoint for a file, or null if none. The resume point
|
|
@@ -1850,14 +1860,14 @@ var CheckpointsRepo = class {
|
|
|
1850
1860
|
FROM message_checkpoints
|
|
1851
1861
|
WHERE source_path = ?
|
|
1852
1862
|
ORDER BY message_index DESC LIMIT 1`
|
|
1853
|
-
).get(sourcePath);
|
|
1863
|
+
).get(canonicalPath(sourcePath));
|
|
1854
1864
|
return row ? toCheckpoint(row) : null;
|
|
1855
1865
|
}
|
|
1856
1866
|
count(sourcePath) {
|
|
1857
|
-
return this.db.prepare("SELECT COUNT(*) AS n FROM message_checkpoints WHERE source_path = ?").get(sourcePath).n;
|
|
1867
|
+
return this.db.prepare("SELECT COUNT(*) AS n FROM message_checkpoints WHERE source_path = ?").get(canonicalPath(sourcePath)).n;
|
|
1858
1868
|
}
|
|
1859
1869
|
remove(sourcePath) {
|
|
1860
|
-
this.db.prepare("DELETE FROM message_checkpoints WHERE source_path = ?").run(sourcePath);
|
|
1870
|
+
this.db.prepare("DELETE FROM message_checkpoints WHERE source_path = ?").run(canonicalPath(sourcePath));
|
|
1861
1871
|
}
|
|
1862
1872
|
};
|
|
1863
1873
|
function toCheckpoint(row) {
|
|
@@ -1870,24 +1880,30 @@ function toCheckpoint(row) {
|
|
|
1870
1880
|
}
|
|
1871
1881
|
|
|
1872
1882
|
// src/persistent/repositories/conversation-files.repo.ts
|
|
1873
|
-
import { basename as basename5, dirname as
|
|
1883
|
+
import { basename as basename5, dirname as dirname5 } from "path";
|
|
1874
1884
|
var ConversationFilesRepo = class {
|
|
1875
1885
|
constructor(db) {
|
|
1876
1886
|
this.db = db;
|
|
1877
1887
|
}
|
|
1878
1888
|
db;
|
|
1879
1889
|
getByPath(absolutePath) {
|
|
1880
|
-
return this.db.prepare("SELECT * FROM conversation_files WHERE absolute_path = ?").get(absolutePath);
|
|
1890
|
+
return this.db.prepare("SELECT * FROM conversation_files WHERE absolute_path = ?").get(canonicalPath(absolutePath));
|
|
1881
1891
|
}
|
|
1882
1892
|
// Insert a freshly-discovered file at offset 0; returns its row id. Existing
|
|
1883
1893
|
// path is left untouched (returns the existing id) so a re-discovery is safe.
|
|
1894
|
+
//
|
|
1895
|
+
// absolute_path/parent_dir are stored canonicalized so a caller that built the
|
|
1896
|
+
// path with the native separator (watcher, path.join) and one that got it from
|
|
1897
|
+
// fast-glob (forward slashes, even on Windows) land on the same row instead of
|
|
1898
|
+
// inserting a duplicate.
|
|
1884
1899
|
ensure(absolutePath, account) {
|
|
1885
|
-
const
|
|
1900
|
+
const canonical = canonicalPath(absolutePath);
|
|
1901
|
+
const existing = this.getByPath(canonical);
|
|
1886
1902
|
if (existing) return existing.id;
|
|
1887
1903
|
const info = this.db.prepare(
|
|
1888
1904
|
`INSERT INTO conversation_files (absolute_path, parent_dir, file_name, account)
|
|
1889
1905
|
VALUES (?, ?, ?, ?)`
|
|
1890
|
-
).run(
|
|
1906
|
+
).run(canonical, dirname5(canonical), basename5(canonical), account);
|
|
1891
1907
|
return Number(info.lastInsertRowid);
|
|
1892
1908
|
}
|
|
1893
1909
|
// Advance the cursor + persisted reducer state after a successful index pass.
|
|
@@ -1949,7 +1965,7 @@ var ConversationFilesRepo = class {
|
|
|
1949
1965
|
activePathsByParentDir(parentDir) {
|
|
1950
1966
|
return this.db.prepare(
|
|
1951
1967
|
"SELECT absolute_path, account FROM conversation_files WHERE parent_dir = ? AND status != 'deleted'"
|
|
1952
|
-
).all(parentDir);
|
|
1968
|
+
).all(canonicalPath(parentDir));
|
|
1953
1969
|
}
|
|
1954
1970
|
};
|
|
1955
1971
|
|
|
@@ -2044,7 +2060,10 @@ var ConversationsRepo = class {
|
|
|
2044
2060
|
updated_at = CURRENT_TIMESTAMP`
|
|
2045
2061
|
).run({
|
|
2046
2062
|
file_id: fileId,
|
|
2047
|
-
|
|
2063
|
+
// Canonical form, matching conversation_files.absolute_path — otherwise
|
|
2064
|
+
// a native-separator caller writes a second spelling of the same file
|
|
2065
|
+
// that every by-path lookup (and the deletion-reconcile) then misses.
|
|
2066
|
+
source_path: canonicalPath(meta.id),
|
|
2048
2067
|
provider: meta.provider ?? CLAUDE_CODE_PROVIDER,
|
|
2049
2068
|
kind: meta.kind ?? null,
|
|
2050
2069
|
external_session_id: meta.externalSessionId ?? null,
|
|
@@ -2074,7 +2093,7 @@ var ConversationsRepo = class {
|
|
|
2074
2093
|
});
|
|
2075
2094
|
}
|
|
2076
2095
|
getBySourcePath(sourcePath) {
|
|
2077
|
-
const row = this.db.prepare("SELECT * FROM conversations WHERE source_path = ? AND status = 'active'").get(sourcePath);
|
|
2096
|
+
const row = this.db.prepare("SELECT * FROM conversations WHERE source_path = ? AND status = 'active'").get(canonicalPath(sourcePath));
|
|
2078
2097
|
return row ? rowToMeta(row) : null;
|
|
2079
2098
|
}
|
|
2080
2099
|
// Dual lookup matching scanner.getConversation: resolve by source_path (the
|
|
@@ -2138,7 +2157,7 @@ var ConversationsRepo = class {
|
|
|
2138
2157
|
pageMessageCount(sourcePath) {
|
|
2139
2158
|
const row = this.db.prepare(
|
|
2140
2159
|
"SELECT page_message_count AS n FROM conversations WHERE source_path = ? AND status = 'active'"
|
|
2141
|
-
).get(sourcePath);
|
|
2160
|
+
).get(canonicalPath(sourcePath));
|
|
2142
2161
|
return row?.n ?? 0;
|
|
2143
2162
|
}
|
|
2144
2163
|
count() {
|
|
@@ -2153,14 +2172,15 @@ var FtsRepo = class {
|
|
|
2153
2172
|
}
|
|
2154
2173
|
db;
|
|
2155
2174
|
upsert(meta) {
|
|
2175
|
+
const sourcePath = canonicalPath(meta.id);
|
|
2156
2176
|
const tx = this.db.transaction(() => {
|
|
2157
|
-
this.db.prepare("DELETE FROM conversation_messages_fts WHERE source_path = ?").run(
|
|
2177
|
+
this.db.prepare("DELETE FROM conversation_messages_fts WHERE source_path = ?").run(sourcePath);
|
|
2158
2178
|
this.db.prepare(
|
|
2159
2179
|
`INSERT INTO conversation_messages_fts
|
|
2160
2180
|
(source_path, content, project_name, session_id, session_name, account, model, branch, tool_names)
|
|
2161
2181
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
2162
2182
|
).run(
|
|
2163
|
-
|
|
2183
|
+
sourcePath,
|
|
2164
2184
|
meta.contentSnippet ?? "",
|
|
2165
2185
|
meta.projectName ?? "",
|
|
2166
2186
|
meta.sessionId ?? "",
|
|
@@ -2174,7 +2194,7 @@ var FtsRepo = class {
|
|
|
2174
2194
|
tx();
|
|
2175
2195
|
}
|
|
2176
2196
|
remove(sourcePath) {
|
|
2177
|
-
this.db.prepare("DELETE FROM conversation_messages_fts WHERE source_path = ?").run(sourcePath);
|
|
2197
|
+
this.db.prepare("DELETE FROM conversation_messages_fts WHERE source_path = ?").run(canonicalPath(sourcePath));
|
|
2178
2198
|
}
|
|
2179
2199
|
// Ranked source_paths matching the query, best first. Returns [] on an empty
|
|
2180
2200
|
// query (callers fall back to a recency listing).
|
|
@@ -2206,11 +2226,11 @@ var ScannedDirsRepo = class {
|
|
|
2206
2226
|
}
|
|
2207
2227
|
db;
|
|
2208
2228
|
get(path) {
|
|
2209
|
-
return this.db.prepare("SELECT * FROM scanned_dirs WHERE path = ?").get(path);
|
|
2229
|
+
return this.db.prepare("SELECT * FROM scanned_dirs WHERE path = ?").get(canonicalPath(path));
|
|
2210
2230
|
}
|
|
2211
2231
|
// Known project subdirectories under a root, path ascending (stable order).
|
|
2212
2232
|
childrenOf(parentRoot) {
|
|
2213
|
-
return this.db.prepare("SELECT * FROM scanned_dirs WHERE parent_root = ? ORDER BY path ASC").all(parentRoot);
|
|
2233
|
+
return this.db.prepare("SELECT * FROM scanned_dirs WHERE parent_root = ? ORDER BY path ASC").all(canonicalPath(parentRoot));
|
|
2214
2234
|
}
|
|
2215
2235
|
upsert(path, parentRoot, mtimeMs, hasNested) {
|
|
2216
2236
|
this.db.prepare(
|
|
@@ -2221,11 +2241,16 @@ var ScannedDirsRepo = class {
|
|
|
2221
2241
|
mtime_ms = excluded.mtime_ms,
|
|
2222
2242
|
has_nested = excluded.has_nested,
|
|
2223
2243
|
updated_at = CURRENT_TIMESTAMP`
|
|
2224
|
-
).run(
|
|
2244
|
+
).run(
|
|
2245
|
+
canonicalPath(path),
|
|
2246
|
+
parentRoot === null ? null : canonicalPath(parentRoot),
|
|
2247
|
+
mtimeMs,
|
|
2248
|
+
hasNested ? 1 : 0
|
|
2249
|
+
);
|
|
2225
2250
|
}
|
|
2226
2251
|
// Drop a project subdirectory's watermark row (it vanished from disk).
|
|
2227
2252
|
remove(path) {
|
|
2228
|
-
this.db.prepare("DELETE FROM scanned_dirs WHERE path = ?").run(path);
|
|
2253
|
+
this.db.prepare("DELETE FROM scanned_dirs WHERE path = ?").run(canonicalPath(path));
|
|
2229
2254
|
}
|
|
2230
2255
|
};
|
|
2231
2256
|
|
|
@@ -2325,7 +2350,7 @@ var PersistentEngine = class {
|
|
|
2325
2350
|
if (enabled.includes(CODEX_CLI_PROVIDER) && (options.codexRoots?.length ?? 0) > 0) {
|
|
2326
2351
|
coveredAccounts.add("codex");
|
|
2327
2352
|
}
|
|
2328
|
-
const seen = new Set(discovered.map((d) => d.filePath));
|
|
2353
|
+
const seen = new Set(discovered.map((d) => canonicalPath(d.filePath)));
|
|
2329
2354
|
for (const path of this.files.activePathsByAccounts([...coveredAccounts])) {
|
|
2330
2355
|
if (!seen.has(path)) this.markDeleted(path);
|
|
2331
2356
|
}
|
|
@@ -2339,9 +2364,10 @@ var PersistentEngine = class {
|
|
|
2339
2364
|
// half-written row or an over-advanced cursor. Returns the classification
|
|
2340
2365
|
// alongside the meta so callers (refreshFile) can keep, extend, or evict
|
|
2341
2366
|
// their own per-file caches without re-stat'ing the file (racy) themselves.
|
|
2342
|
-
async indexFile(
|
|
2367
|
+
async indexFile(rawFilePath, account, tierName, customTiers, resolveGitBranch, force = false, provider) {
|
|
2343
2368
|
const log = getLogger();
|
|
2344
2369
|
const tier = resolveTier(tierName, customTiers);
|
|
2370
|
+
const filePath = canonicalPath(rawFilePath);
|
|
2345
2371
|
const existing = this.files.getByPath(filePath);
|
|
2346
2372
|
const { change, stat: stat4 } = classify(filePath, existing);
|
|
2347
2373
|
if (change === "vanished" || !stat4) {
|
|
@@ -2652,7 +2678,7 @@ var IndexQueue = class {
|
|
|
2652
2678
|
var BATCH_SIZE2 = 12;
|
|
2653
2679
|
var DEFAULT_CONFIG_PATH = "~/.config/threadbase-scanner";
|
|
2654
2680
|
function defaultDbPath() {
|
|
2655
|
-
return process.env.TB_SCANNER_DB ??
|
|
2681
|
+
return process.env.TB_SCANNER_DB ?? join5(homedir2(), ".config", "threadbase-scanner", "index.db");
|
|
2656
2682
|
}
|
|
2657
2683
|
var ConversationScanner = class {
|
|
2658
2684
|
metadataCache = /* @__PURE__ */ new Map();
|
|
@@ -2945,12 +2971,13 @@ var ConversationScanner = class {
|
|
|
2945
2971
|
}
|
|
2946
2972
|
async getConversation(id, _options) {
|
|
2947
2973
|
const log = getLogger();
|
|
2948
|
-
const
|
|
2974
|
+
const cid = canonicalPath(id);
|
|
2975
|
+
const cached = this.conversationLRU.get(cid);
|
|
2949
2976
|
if (cached) {
|
|
2950
2977
|
log.debug({ id }, "getConversation: cache hit");
|
|
2951
2978
|
return cached.conversation;
|
|
2952
2979
|
}
|
|
2953
|
-
const meta = this.persistent ? this.engine().getByIdOrSession(
|
|
2980
|
+
const meta = this.persistent ? this.engine().getByIdOrSession(cid) : this.metadataCache.get(cid) ?? this.resolveSessionId(cid);
|
|
2954
2981
|
if (!meta) {
|
|
2955
2982
|
log.debug({ id }, "getConversation: not found in metadata");
|
|
2956
2983
|
return null;
|
|
@@ -2959,12 +2986,12 @@ var ConversationScanner = class {
|
|
|
2959
2986
|
try {
|
|
2960
2987
|
if (this.persistent && meta.provider !== CODEX_CLI_PROVIDER) {
|
|
2961
2988
|
const parsed = await parseConversationResumable(meta.filePath, meta.account);
|
|
2962
|
-
if (parsed) this.conversationLRU.set(
|
|
2989
|
+
if (parsed) this.conversationLRU.set(cid, parsed);
|
|
2963
2990
|
return parsed?.conversation ?? null;
|
|
2964
2991
|
}
|
|
2965
2992
|
const conversation = meta.provider === CODEX_CLI_PROVIDER ? await parseCodexConversation(meta.filePath, meta.account) : await parseConversation(meta.filePath, meta.account);
|
|
2966
2993
|
if (conversation) {
|
|
2967
|
-
this.conversationLRU.set(
|
|
2994
|
+
this.conversationLRU.set(cid, { conversation });
|
|
2968
2995
|
}
|
|
2969
2996
|
return conversation;
|
|
2970
2997
|
} catch (err) {
|
|
@@ -2992,7 +3019,7 @@ var ConversationScanner = class {
|
|
|
2992
3019
|
// which is identical by construction.
|
|
2993
3020
|
async getConversationPage(id, options) {
|
|
2994
3021
|
if (this.persistent) {
|
|
2995
|
-
return this.engine().getPage(id, options);
|
|
3022
|
+
return this.engine().getPage(canonicalPath(id), options);
|
|
2996
3023
|
}
|
|
2997
3024
|
const conversation = await this.getConversation(id);
|
|
2998
3025
|
if (!conversation) return null;
|
|
@@ -3042,14 +3069,15 @@ var ConversationScanner = class {
|
|
|
3042
3069
|
// each re-reading the file.
|
|
3043
3070
|
refreshesInFlight = /* @__PURE__ */ new Map();
|
|
3044
3071
|
refreshFile(filePath, account) {
|
|
3045
|
-
const
|
|
3072
|
+
const cpath = canonicalPath(filePath);
|
|
3073
|
+
const inFlight = this.refreshesInFlight.get(cpath);
|
|
3046
3074
|
if (inFlight) return inFlight;
|
|
3047
|
-
const refresh = this.doRefreshFile(
|
|
3048
|
-
if (this.refreshesInFlight.get(
|
|
3049
|
-
this.refreshesInFlight.delete(
|
|
3075
|
+
const refresh = this.doRefreshFile(cpath, account).finally(() => {
|
|
3076
|
+
if (this.refreshesInFlight.get(cpath) === refresh) {
|
|
3077
|
+
this.refreshesInFlight.delete(cpath);
|
|
3050
3078
|
}
|
|
3051
3079
|
});
|
|
3052
|
-
this.refreshesInFlight.set(
|
|
3080
|
+
this.refreshesInFlight.set(cpath, refresh);
|
|
3053
3081
|
return refresh;
|
|
3054
3082
|
}
|
|
3055
3083
|
async doRefreshFile(filePath, account) {
|