@wrongstack/tools 0.265.1 → 0.268.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.
@@ -2056,6 +2056,7 @@ async function loadGitignoreMatcher(projectRoot) {
2056
2056
 
2057
2057
  // src/codebase-index/indexer.ts
2058
2058
  var YIELD_EVERY_N = 50;
2059
+ var PARALLEL_BATCH = 20;
2059
2060
  function yieldEventLoop() {
2060
2061
  return new Promise((resolve2) => setImmediate(resolve2));
2061
2062
  }
@@ -2189,97 +2190,108 @@ async function runIndexerWithStore(store, opts) {
2189
2190
  if (!force) {
2190
2191
  for (const meta of store.getAllFileMetas()) existingMeta.set(meta.file, meta);
2191
2192
  }
2192
- for (let fi = 0; fi < files.length; fi++) {
2193
- const file = expectDefined(files[fi]);
2194
- opts.onProgress?.(fi + 1, files.length);
2195
- if (fi > 0 && fi % YIELD_EVERY_N === 0) {
2193
+ for (let batchStart = 0; batchStart < files.length; batchStart += PARALLEL_BATCH) {
2194
+ const batchEnd = Math.min(batchStart + PARALLEL_BATCH, files.length);
2195
+ const batchFiles = files.slice(batchStart, batchEnd);
2196
+ opts.onProgress?.(batchEnd, files.length);
2197
+ if (batchStart > 0 && batchStart % YIELD_EVERY_N === 0) {
2196
2198
  await yieldEventLoop();
2197
2199
  throwIfAborted(signal);
2198
2200
  }
2199
- let stat2;
2200
- try {
2201
- const statOpts = signal ? { signal } : {};
2202
- stat2 = await fs3.stat(file, statOpts);
2203
- } catch (e) {
2204
- if (isAbortError(e)) throw e;
2205
- store.deleteFile(file);
2206
- continue;
2207
- }
2208
- if (!stat2.isFile()) continue;
2209
- const lang = detectLang(file);
2210
- if (!lang) continue;
2211
- const meta = existingMeta.get(file);
2212
- if (!force && meta && meta.mtimeMs === Math.floor(stat2.mtimeMs)) {
2213
- langStats[lang] = (langStats[lang] ?? 0) + meta.symbolCount;
2214
- symbolsIndexed += meta.symbolCount;
2215
- filesIndexed++;
2216
- continue;
2217
- }
2218
- store.deleteRefsForFile(file);
2219
- store.deleteSymbolsForFile(file);
2220
- let content;
2221
- try {
2222
- content = await fs3.readFile(file, { encoding: "utf8", signal });
2223
- } catch (e) {
2224
- if (isAbortError(e)) throw e;
2225
- errors.push(`read error: ${file}: ${e instanceof Error ? e.message : String(e)}`);
2226
- continue;
2227
- }
2228
- let parsed;
2229
- try {
2230
- parsed = await parseFile(file, content, lang);
2231
- } catch (e) {
2232
- errors.push(`parse error: ${file}: ${e instanceof Error ? e.message : String(e)}`);
2233
- continue;
2234
- }
2235
- if (parsed.symbols.length === 0) {
2236
- store.upsertFile({
2237
- file,
2238
- lang,
2239
- mtimeMs: Math.floor(stat2.mtimeMs),
2240
- symbolCount: 0,
2241
- lastIndexed: Date.now()
2242
- });
2243
- filesIndexed++;
2244
- continue;
2245
- }
2246
- const nextId = store.getMaxSymbolId() + 1;
2247
- const symbolsWithIds = parsed.symbols.map((s, i) => ({ ...s, id: nextId + i }));
2248
- store.insertSymbols(symbolsWithIds, nextId);
2249
- const count = symbolsWithIds.length;
2250
- symbolsIndexed += count;
2251
- langStats[lang] = (langStats[lang] ?? 0) + count;
2252
- if (parsed.refs && parsed.refs.length > 0) {
2253
- const refsByLine = /* @__PURE__ */ new Map();
2254
- for (const r of parsed.refs) {
2255
- let arr = refsByLine.get(r.line);
2256
- if (!arr) {
2257
- arr = [];
2258
- refsByLine.set(r.line, arr);
2201
+ const statOpts = signal ? { signal } : {};
2202
+ const statReadParse = await Promise.allSettled(
2203
+ batchFiles.map(async (file) => {
2204
+ let stat2;
2205
+ try {
2206
+ stat2 = await fs3.stat(file, statOpts);
2207
+ } catch (e) {
2208
+ if (isAbortError(e)) throw e;
2209
+ return { file, stat: null, lang: "", parsed: null, error: `stat error: ${e instanceof Error ? e.message : String(e)}` };
2210
+ }
2211
+ if (!stat2.isFile()) return { file, stat: stat2, lang: "", parsed: null };
2212
+ const lang = detectLang(file);
2213
+ if (!lang) return { file, stat: stat2, lang: "", parsed: null };
2214
+ let content;
2215
+ try {
2216
+ content = await fs3.readFile(file, { encoding: "utf8", signal });
2217
+ } catch (e) {
2218
+ if (isAbortError(e)) throw e;
2219
+ return { file, stat: stat2, lang, parsed: null, error: `read error: ${e instanceof Error ? e.message : String(e)}` };
2220
+ }
2221
+ let parsed;
2222
+ try {
2223
+ parsed = await parseFile(file, content, lang);
2224
+ } catch (e) {
2225
+ return { file, stat: stat2, lang, parsed: null, error: `parse error: ${e instanceof Error ? e.message : String(e)}` };
2259
2226
  }
2260
- arr.push(r);
2227
+ return { file, stat: stat2, lang, parsed, content };
2228
+ })
2229
+ );
2230
+ for (let fi = 0; fi < statReadParse.length; fi++) {
2231
+ const settled = statReadParse[fi];
2232
+ const file = expectDefined(batchFiles[fi]);
2233
+ if (settled.status === "rejected") {
2234
+ const err = settled.reason;
2235
+ if (err instanceof Error && isAbortError(err)) throw err;
2236
+ errors.push(`batch error: ${file}: ${err instanceof Error ? err.message : String(err)}`);
2237
+ continue;
2261
2238
  }
2262
- const batch = [];
2263
- for (const sym of symbolsWithIds) {
2264
- const symRefs = refsByLine.get(sym.line);
2265
- if (symRefs) {
2266
- for (const r of symRefs) {
2267
- batch.push({ ...r, fromId: sym.id });
2268
- }
2239
+ const result = settled.value;
2240
+ if (result.error) {
2241
+ if (result.stat) store.deleteFile(file);
2242
+ if (result.error.includes("error:")) errors.push(result.error);
2243
+ continue;
2244
+ }
2245
+ const { stat: stat2, lang, parsed } = result;
2246
+ if (!lang || !parsed) {
2247
+ if (lang) {
2248
+ store.upsertFile({ file, lang, mtimeMs: Math.floor(stat2.mtimeMs), symbolCount: 0, lastIndexed: Date.now() });
2249
+ filesIndexed++;
2269
2250
  }
2251
+ continue;
2270
2252
  }
2271
- if (batch.length > 0) {
2272
- store.insertRefsBatch(batch);
2253
+ const meta = existingMeta.get(file);
2254
+ if (!force && meta && meta.mtimeMs === Math.floor(stat2.mtimeMs)) {
2255
+ langStats[lang] = (langStats[lang] ?? 0) + meta.symbolCount;
2256
+ symbolsIndexed += meta.symbolCount;
2257
+ filesIndexed++;
2258
+ continue;
2273
2259
  }
2260
+ store.deleteRefsForFile(file);
2261
+ store.deleteSymbolsForFile(file);
2262
+ if (parsed.symbols.length === 0) {
2263
+ store.upsertFile({ file, lang, mtimeMs: Math.floor(stat2.mtimeMs), symbolCount: 0, lastIndexed: Date.now() });
2264
+ filesIndexed++;
2265
+ continue;
2266
+ }
2267
+ const nextId = store.getMaxSymbolId() + 1;
2268
+ const symbolsWithIds = parsed.symbols.map((s, i) => ({ ...s, id: nextId + i }));
2269
+ store.insertSymbols(symbolsWithIds, nextId);
2270
+ const count = symbolsWithIds.length;
2271
+ symbolsIndexed += count;
2272
+ langStats[lang] = (langStats[lang] ?? 0) + count;
2273
+ if (parsed.refs && parsed.refs.length > 0) {
2274
+ const refsByLine = /* @__PURE__ */ new Map();
2275
+ for (const r of parsed.refs) {
2276
+ let arr = refsByLine.get(r.line);
2277
+ if (!arr) {
2278
+ arr = [];
2279
+ refsByLine.set(r.line, arr);
2280
+ }
2281
+ arr.push(r);
2282
+ }
2283
+ const batch = [];
2284
+ for (const sym of symbolsWithIds) {
2285
+ const symRefs = refsByLine.get(sym.line);
2286
+ if (symRefs) {
2287
+ for (const r of symRefs) batch.push({ ...r, fromId: sym.id });
2288
+ }
2289
+ }
2290
+ if (batch.length > 0) store.insertRefsBatch(batch);
2291
+ }
2292
+ store.upsertFile({ file, lang, mtimeMs: Math.floor(stat2.mtimeMs), symbolCount: count, lastIndexed: Date.now() });
2293
+ filesIndexed++;
2274
2294
  }
2275
- store.upsertFile({
2276
- file,
2277
- lang,
2278
- mtimeMs: Math.floor(stat2.mtimeMs),
2279
- symbolCount: count,
2280
- lastIndexed: Date.now()
2281
- });
2282
- filesIndexed++;
2283
2295
  }
2284
2296
  for (const [file_] of existingMeta) {
2285
2297
  try {