@wrongstack/tools 0.275.1 → 0.276.3
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/{background-indexer-BoTUw0EM.d.ts → background-indexer-BeDBxfSh.d.ts} +6 -0
- package/dist/builtin.js +1056 -246
- package/dist/builtin.js.map +1 -1
- package/dist/codebase-index/index.d.ts +30 -2
- package/dist/codebase-index/index.js +201 -24
- package/dist/codebase-index/index.js.map +1 -1
- package/dist/codebase-index/worker.js +196 -23
- package/dist/codebase-index/worker.js.map +1 -1
- package/dist/document.js +2 -2
- package/dist/document.js.map +1 -1
- package/dist/edit.js +52 -15
- package/dist/edit.js.map +1 -1
- package/dist/fetch.js +89 -18
- package/dist/fetch.js.map +1 -1
- package/dist/glob.js +35 -1
- package/dist/glob.js.map +1 -1
- package/dist/grep.js +15 -4
- package/dist/grep.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1090 -255
- package/dist/index.js.map +1 -1
- package/dist/install.d.ts +7 -0
- package/dist/install.js +6 -0
- package/dist/install.js.map +1 -1
- package/dist/json.d.ts +26 -1
- package/dist/json.js +453 -46
- package/dist/json.js.map +1 -1
- package/dist/memory.js +26 -4
- package/dist/memory.js.map +1 -1
- package/dist/outdated.js +2 -2
- package/dist/outdated.js.map +1 -1
- package/dist/pack.js +1056 -246
- package/dist/pack.js.map +1 -1
- package/dist/read.js +36 -6
- package/dist/read.js.map +1 -1
- package/dist/replace.js +27 -9
- package/dist/replace.js.map +1 -1
- package/dist/search.d.ts +5 -1
- package/dist/search.js +179 -62
- package/dist/search.js.map +1 -1
- package/dist/tool-help.js +2 -2
- package/dist/tool-help.js.map +1 -1
- package/dist/tool-search.js +2 -2
- package/dist/tool-search.js.map +1 -1
- package/dist/write.js +13 -3
- package/dist/write.js.map +1 -1
- package/package.json +2 -2
|
@@ -727,6 +727,104 @@ var IndexStore = class {
|
|
|
727
727
|
}
|
|
728
728
|
});
|
|
729
729
|
}
|
|
730
|
+
/**
|
|
731
|
+
* Commit a batch of file-level symbol/refs/upserts in a single transaction.
|
|
732
|
+
*
|
|
733
|
+
* Used by the indexer to amortize SQLite commit overhead across many files.
|
|
734
|
+
* Before this, the indexer issued one transaction per file (BEGIN IMMEDIATE
|
|
735
|
+
* for symbols, plus per-file deletes and an upsertFile call), so a 20-file
|
|
736
|
+
* parallel batch cost ~5+ transactions × 20 files = 100+ commits. With
|
|
737
|
+
* this entry point we do exactly one BEGIN/COMMIT per parallel batch.
|
|
738
|
+
*
|
|
739
|
+
* Each entry must already be a fully-parsed FileSymbols (symbols + refs).
|
|
740
|
+
* The caller is responsible for the per-file prefix accounting
|
|
741
|
+
* (refsByLine → flat list with `fromId` populated). `deleteForFiles` lets
|
|
742
|
+
* the caller clear stale symbols/refs for any files being re-indexed before
|
|
743
|
+
* the inserts run (required to keep refs → symbols FK invariants).
|
|
744
|
+
*
|
|
745
|
+
* Returns the symbols back with their assigned `id` (same shape as
|
|
746
|
+
* {@link insertSymbols}) so callers can build final per-file results.
|
|
747
|
+
*/
|
|
748
|
+
commitBatch(entries, options = {}) {
|
|
749
|
+
if (entries.length === 0 && (options.deleteForFiles?.length ?? 0) === 0) {
|
|
750
|
+
return [];
|
|
751
|
+
}
|
|
752
|
+
return this.runWithRetry(() => {
|
|
753
|
+
this.db.exec("BEGIN IMMEDIATE");
|
|
754
|
+
try {
|
|
755
|
+
if (options.deleteForFiles && options.deleteForFiles.length > 0) {
|
|
756
|
+
const placeholders = options.deleteForFiles.map(() => "?").join(",");
|
|
757
|
+
if (this.ftsAvailable) {
|
|
758
|
+
this.db.prepare(
|
|
759
|
+
`DELETE FROM symbols_fts WHERE rowid IN (SELECT id FROM symbols WHERE file IN (${placeholders}))`
|
|
760
|
+
).run(...options.deleteForFiles);
|
|
761
|
+
}
|
|
762
|
+
this.db.prepare(
|
|
763
|
+
`DELETE FROM refs WHERE from_id IN (SELECT id FROM symbols WHERE file IN (${placeholders}))`
|
|
764
|
+
).run(...options.deleteForFiles);
|
|
765
|
+
this.db.prepare(`DELETE FROM symbols WHERE file IN (${placeholders})`).run(...options.deleteForFiles);
|
|
766
|
+
}
|
|
767
|
+
const maxRows = this.db.prepare("SELECT MAX(id) AS m FROM symbols").all();
|
|
768
|
+
let nextId = (maxRows[0]?.m ?? 0) + 1;
|
|
769
|
+
const symStmt = this.db.prepare(
|
|
770
|
+
`INSERT INTO symbols(id, lang, kind, name, file, line, col, signature, doc_comment, scope, text, file_fk)
|
|
771
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
772
|
+
);
|
|
773
|
+
const ftsStmt = this.ftsAvailable ? this.db.prepare("INSERT INTO symbols_fts(rowid, text) VALUES (?, ?)") : null;
|
|
774
|
+
const allInserted = [];
|
|
775
|
+
const refsToInsert = [];
|
|
776
|
+
for (const entry of entries) {
|
|
777
|
+
for (const s of entry.symbols) {
|
|
778
|
+
const id = nextId++;
|
|
779
|
+
symStmt.run(
|
|
780
|
+
id,
|
|
781
|
+
s.lang,
|
|
782
|
+
s.kind,
|
|
783
|
+
s.name,
|
|
784
|
+
s.file,
|
|
785
|
+
s.line,
|
|
786
|
+
s.col,
|
|
787
|
+
s.signature,
|
|
788
|
+
s.docComment,
|
|
789
|
+
s.scope,
|
|
790
|
+
s.text,
|
|
791
|
+
s.file
|
|
792
|
+
);
|
|
793
|
+
ftsStmt?.run(id, buildIndexableText(s.name, s.signature, s.docComment));
|
|
794
|
+
allInserted.push({ ...s, id });
|
|
795
|
+
}
|
|
796
|
+
for (const r of entry.refs) refsToInsert.push(r);
|
|
797
|
+
}
|
|
798
|
+
if (refsToInsert.length > 0) {
|
|
799
|
+
const refStmt = this.db.prepare(
|
|
800
|
+
`INSERT INTO refs(from_id, to_name, to_id, call_type, line)
|
|
801
|
+
VALUES (?, ?, ?, ?, ?)`
|
|
802
|
+
);
|
|
803
|
+
for (const ref of refsToInsert) {
|
|
804
|
+
refStmt.run(ref.fromId, ref.toName, ref.toId ?? null, ref.callType, ref.line);
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
const upsertStmt = this.db.prepare(
|
|
808
|
+
`INSERT INTO files(file, lang, mtime_ms, symbol_count, last_indexed)
|
|
809
|
+
VALUES (?, ?, ?, ?, ?)
|
|
810
|
+
ON CONFLICT(file) DO UPDATE SET
|
|
811
|
+
lang = excluded.lang,
|
|
812
|
+
mtime_ms = excluded.mtime_ms,
|
|
813
|
+
symbol_count = excluded.symbol_count,
|
|
814
|
+
last_indexed = excluded.last_indexed`
|
|
815
|
+
);
|
|
816
|
+
const now = Date.now();
|
|
817
|
+
for (const entry of entries) {
|
|
818
|
+
upsertStmt.run(entry.file, entry.lang, entry.mtimeMs, entry.symbolCount, now);
|
|
819
|
+
}
|
|
820
|
+
this.db.exec("COMMIT");
|
|
821
|
+
return allInserted;
|
|
822
|
+
} catch (err) {
|
|
823
|
+
this.db.exec("ROLLBACK");
|
|
824
|
+
throw err;
|
|
825
|
+
}
|
|
826
|
+
});
|
|
827
|
+
}
|
|
730
828
|
/**
|
|
731
829
|
* Delete all refs whose source symbols are in a given file.
|
|
732
830
|
* Used when re-indexing a file to clear stale refs.
|
|
@@ -2258,6 +2356,8 @@ async function runIndexerWithStore(store, opts) {
|
|
|
2258
2356
|
return { file, stat: stat2, lang, parsed, content };
|
|
2259
2357
|
})
|
|
2260
2358
|
);
|
|
2359
|
+
const batchEntries = [];
|
|
2360
|
+
const deleteForFiles = [];
|
|
2261
2361
|
for (let fi = 0; fi < statReadParse.length; fi++) {
|
|
2262
2362
|
const settled = statReadParse[fi];
|
|
2263
2363
|
const file = expectDefined(batchFiles[fi]);
|
|
@@ -2282,43 +2382,116 @@ async function runIndexerWithStore(store, opts) {
|
|
|
2282
2382
|
}
|
|
2283
2383
|
if (!lang || !parsed) {
|
|
2284
2384
|
if (lang) {
|
|
2285
|
-
store.upsertFile({
|
|
2385
|
+
store.upsertFile({
|
|
2386
|
+
file,
|
|
2387
|
+
lang,
|
|
2388
|
+
mtimeMs: Math.floor(stat2.mtimeMs),
|
|
2389
|
+
symbolCount: 0,
|
|
2390
|
+
lastIndexed: Date.now()
|
|
2391
|
+
});
|
|
2286
2392
|
filesIndexed++;
|
|
2287
2393
|
}
|
|
2288
2394
|
continue;
|
|
2289
2395
|
}
|
|
2290
|
-
store.deleteRefsForFile(file);
|
|
2291
|
-
store.deleteSymbolsForFile(file);
|
|
2292
2396
|
if (parsed.symbols.length === 0) {
|
|
2293
|
-
store.upsertFile({
|
|
2397
|
+
store.upsertFile({
|
|
2398
|
+
file,
|
|
2399
|
+
lang,
|
|
2400
|
+
mtimeMs: Math.floor(stat2.mtimeMs),
|
|
2401
|
+
symbolCount: 0,
|
|
2402
|
+
lastIndexed: Date.now()
|
|
2403
|
+
});
|
|
2294
2404
|
filesIndexed++;
|
|
2295
2405
|
continue;
|
|
2296
2406
|
}
|
|
2297
|
-
const
|
|
2298
|
-
const count = symbolsWithIds.length;
|
|
2299
|
-
symbolsIndexed += count;
|
|
2300
|
-
langStats[lang] = (langStats[lang] ?? 0) + count;
|
|
2407
|
+
const refs = [];
|
|
2301
2408
|
if (parsed.refs && parsed.refs.length > 0) {
|
|
2302
|
-
const
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2409
|
+
for (const r of parsed.refs) refs.push({ ...r, fromId: 0 });
|
|
2410
|
+
}
|
|
2411
|
+
batchEntries.push({
|
|
2412
|
+
file,
|
|
2413
|
+
lang,
|
|
2414
|
+
symbols: parsed.symbols,
|
|
2415
|
+
refs,
|
|
2416
|
+
mtimeMs: Math.floor(stat2.mtimeMs),
|
|
2417
|
+
symbolCount: parsed.symbols.length
|
|
2418
|
+
});
|
|
2419
|
+
deleteForFiles.push(file);
|
|
2420
|
+
}
|
|
2421
|
+
if (batchEntries.length > 0) {
|
|
2422
|
+
try {
|
|
2423
|
+
const inserted = store.commitBatch(batchEntries, { deleteForFiles });
|
|
2424
|
+
let cursor = 0;
|
|
2425
|
+
for (const entry of batchEntries) {
|
|
2426
|
+
const count = entry.symbols.length;
|
|
2427
|
+
const symbolsWithIds = inserted.slice(cursor, cursor + count);
|
|
2428
|
+
cursor += count;
|
|
2429
|
+
symbolsIndexed += count;
|
|
2430
|
+
langStats[entry.lang] = (langStats[entry.lang] ?? 0) + count;
|
|
2431
|
+
filesIndexed++;
|
|
2432
|
+
if (entry.refs.length > 0 && symbolsWithIds.length > 0) {
|
|
2433
|
+
const refsByLine = /* @__PURE__ */ new Map();
|
|
2434
|
+
for (let i = 0; i < symbolsWithIds.length; i++) {
|
|
2435
|
+
const sym = symbolsWithIds[i];
|
|
2436
|
+
let arr = refsByLine.get(sym.line);
|
|
2437
|
+
if (!arr) {
|
|
2438
|
+
arr = [];
|
|
2439
|
+
refsByLine.set(sym.line, arr);
|
|
2440
|
+
}
|
|
2441
|
+
arr.push(i);
|
|
2442
|
+
}
|
|
2443
|
+
for (const ref of entry.refs) {
|
|
2444
|
+
const indices = refsByLine.get(ref.line);
|
|
2445
|
+
if (indices && indices.length > 0) {
|
|
2446
|
+
const idx = indices.shift();
|
|
2447
|
+
ref.fromId = symbolsWithIds[idx].id;
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2308
2450
|
}
|
|
2309
|
-
arr.push(r);
|
|
2310
2451
|
}
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2452
|
+
} catch (err) {
|
|
2453
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2454
|
+
errors.push(`commitBatch failed: ${message} \u2014 falling back to per-file writes`);
|
|
2455
|
+
for (const entry of batchEntries) {
|
|
2456
|
+
try {
|
|
2457
|
+
store.deleteRefsForFile(entry.file);
|
|
2458
|
+
store.deleteSymbolsForFile(entry.file);
|
|
2459
|
+
const symbolsWithIds = store.insertSymbols(entry.symbols);
|
|
2460
|
+
symbolsIndexed += symbolsWithIds.length;
|
|
2461
|
+
langStats[entry.lang] = (langStats[entry.lang] ?? 0) + symbolsWithIds.length;
|
|
2462
|
+
filesIndexed++;
|
|
2463
|
+
if (entry.refs.length > 0 && symbolsWithIds.length > 0) {
|
|
2464
|
+
const refsByLine = /* @__PURE__ */ new Map();
|
|
2465
|
+
for (const sym of symbolsWithIds) {
|
|
2466
|
+
let arr = refsByLine.get(sym.line);
|
|
2467
|
+
if (!arr) {
|
|
2468
|
+
arr = [];
|
|
2469
|
+
refsByLine.set(sym.line, arr);
|
|
2470
|
+
}
|
|
2471
|
+
arr.push(sym);
|
|
2472
|
+
}
|
|
2473
|
+
const fallbackBatch = [];
|
|
2474
|
+
for (const ref of entry.refs) {
|
|
2475
|
+
const syms = refsByLine.get(ref.line);
|
|
2476
|
+
if (syms && syms.length > 0) {
|
|
2477
|
+
const sym = syms.shift();
|
|
2478
|
+
fallbackBatch.push({ ...ref, fromId: sym.id });
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2481
|
+
if (fallbackBatch.length > 0) store.insertRefsBatch(fallbackBatch);
|
|
2482
|
+
}
|
|
2483
|
+
store.upsertFile({
|
|
2484
|
+
file: entry.file,
|
|
2485
|
+
lang: entry.lang,
|
|
2486
|
+
mtimeMs: entry.mtimeMs,
|
|
2487
|
+
symbolCount: entry.symbolCount,
|
|
2488
|
+
lastIndexed: Date.now()
|
|
2489
|
+
});
|
|
2490
|
+
} catch (innerErr) {
|
|
2491
|
+
errors.push(`fallback write failed: ${entry.file}: ${innerErr instanceof Error ? innerErr.message : String(innerErr)}`);
|
|
2316
2492
|
}
|
|
2317
2493
|
}
|
|
2318
|
-
if (batch.length > 0) store.insertRefsBatch(batch);
|
|
2319
2494
|
}
|
|
2320
|
-
store.upsertFile({ file, lang, mtimeMs: Math.floor(stat2.mtimeMs), symbolCount: count, lastIndexed: Date.now() });
|
|
2321
|
-
filesIndexed++;
|
|
2322
2495
|
}
|
|
2323
2496
|
}
|
|
2324
2497
|
if (discoveredFiles) {
|