@arcbridge/core 0.1.0 → 0.1.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/index.js CHANGED
@@ -32,7 +32,7 @@ var ArcBridgeConfigSchema = z.object({
32
32
  exclude: z.array(z.string()).default(["node_modules", "dist", ".next", "coverage"]),
33
33
  default_mode: z.enum(["fast", "deep"]).default("fast"),
34
34
  csharp_indexer: z.enum(["auto", "roslyn", "tree-sitter"]).default("auto").describe(
35
- "C# indexer backend: 'auto' uses Roslyn if available, otherwise tree-sitter. 'tree-sitter' works without .NET SDK. 'roslyn' requires .NET SDK + global tool."
35
+ "C# indexer backend: 'auto' prefers the arcbridge-dotnet-indexer global tool, falls back to monorepo source if dotnet CLI is available, else tree-sitter. 'tree-sitter' works without .NET SDK. 'roslyn' requires global tool or monorepo source + .NET SDK."
36
36
  )
37
37
  }).default({}),
38
38
  testing: z.object({
@@ -4315,7 +4315,7 @@ function writeDependencies(db, dependencies) {
4315
4315
  // src/indexer/dotnet-indexer.ts
4316
4316
  import { execFileSync } from "child_process";
4317
4317
  import { resolve, join as join9, dirname, relative as relative4, basename } from "path";
4318
- import { readdirSync as readdirSync3, readFileSync as readFileSync3, existsSync as existsSync4 } from "fs";
4318
+ import { readdirSync as readdirSync3, readFileSync as readFileSync3, existsSync as existsSync4, accessSync, constants } from "fs";
4319
4319
  import { fileURLToPath } from "url";
4320
4320
  function findDotnetProject(projectRoot) {
4321
4321
  try {
@@ -4366,6 +4366,24 @@ function discoverDotnetServices(projectRoot) {
4366
4366
  }
4367
4367
  return parseSolutionProjects(slnPath);
4368
4368
  }
4369
+ function hasGlobalTool() {
4370
+ const pathEnv = process.env.PATH ?? "";
4371
+ const dirs = pathEnv.split(process.platform === "win32" ? ";" : ":");
4372
+ const name = "arcbridge-dotnet-indexer";
4373
+ const extensions = process.platform === "win32" ? (process.env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";") : [""];
4374
+ for (const dir of dirs) {
4375
+ if (!dir) continue;
4376
+ for (const ext of extensions) {
4377
+ try {
4378
+ accessSync(join9(dir, `${name}${ext}`), constants.X_OK);
4379
+ return true;
4380
+ } catch {
4381
+ continue;
4382
+ }
4383
+ }
4384
+ }
4385
+ return false;
4386
+ }
4369
4387
  function resolveIndexerProject() {
4370
4388
  const currentDir2 = dirname(fileURLToPath(import.meta.url));
4371
4389
  const candidates = [
@@ -4376,71 +4394,70 @@ function resolveIndexerProject() {
4376
4394
  for (const candidate of candidates) {
4377
4395
  if (existsSync4(candidate)) return candidate;
4378
4396
  }
4379
- throw new Error(
4380
- "Could not find ArcBridge.DotnetIndexer.csproj. Ensure the dotnet-indexer package is present in the monorepo."
4381
- );
4397
+ return null;
4382
4398
  }
4383
- function indexDotnetProjectRoslyn(db, options) {
4384
- const start = Date.now();
4385
- const service = options.service ?? "main";
4386
- const projectRoot = resolve(options.projectRoot);
4387
- const dotnetProject = options.csprojPath ?? findDotnetProject(projectRoot);
4388
- if (!dotnetProject) {
4389
- throw new Error(
4390
- "No .sln or .csproj file found in project root. The .NET indexer requires a project or solution file."
4391
- );
4399
+ function hasIndexerProject() {
4400
+ return resolveIndexerProject() !== null;
4401
+ }
4402
+ var EXEC_OPTIONS = {
4403
+ encoding: "utf-8",
4404
+ maxBuffer: 50 * 1024 * 1024,
4405
+ // 50MB for large projects
4406
+ timeout: 3e5
4407
+ // 5 minutes
4408
+ };
4409
+ function runDotnetIndexer(dotnetProject, hashesJson, cwd) {
4410
+ const args = [dotnetProject, "--existing-hashes", hashesJson];
4411
+ const preferSource = process.env.ARCBRIDGE_PREFER_SOURCE === "1";
4412
+ let globalToolError = null;
4413
+ if (!preferSource && hasGlobalTool()) {
4414
+ try {
4415
+ return execFileSync("arcbridge-dotnet-indexer", args, { ...EXEC_OPTIONS, cwd });
4416
+ } catch (err) {
4417
+ globalToolError = err;
4418
+ }
4392
4419
  }
4393
- const existingHashes = getExistingHashes(db, service);
4394
- const hashesJson = JSON.stringify(Object.fromEntries(existingHashes));
4395
4420
  const indexerProject = resolveIndexerProject();
4396
- let stdout;
4421
+ if (!indexerProject) {
4422
+ const base = "Roslyn C# indexer not available. Either install the global tool (`dotnet tool install -g arcbridge-dotnet-indexer`) or run from the ArcBridge monorepo.";
4423
+ if (globalToolError) {
4424
+ const msg = globalToolError instanceof Error ? globalToolError.message : String(globalToolError);
4425
+ throw new Error(`${base} Global tool was found but failed: ${msg}`, { cause: globalToolError });
4426
+ }
4427
+ throw new Error(base);
4428
+ }
4397
4429
  try {
4398
- stdout = execFileSync(
4430
+ return execFileSync(
4399
4431
  "dotnet",
4400
- [
4401
- "run",
4402
- "--project",
4403
- indexerProject,
4404
- "--no-build",
4405
- "--",
4406
- dotnetProject,
4407
- "--existing-hashes",
4408
- hashesJson
4409
- ],
4410
- {
4411
- encoding: "utf-8",
4412
- maxBuffer: 50 * 1024 * 1024,
4413
- // 50MB for large projects
4414
- timeout: 3e5,
4415
- // 5 minutes
4416
- cwd: projectRoot
4417
- }
4432
+ ["run", "--project", indexerProject, "--no-build", "--", ...args],
4433
+ { ...EXEC_OPTIONS, cwd }
4418
4434
  );
4419
4435
  } catch {
4420
4436
  try {
4421
- stdout = execFileSync(
4437
+ return execFileSync(
4422
4438
  "dotnet",
4423
- [
4424
- "run",
4425
- "--project",
4426
- indexerProject,
4427
- "--",
4428
- dotnetProject,
4429
- "--existing-hashes",
4430
- hashesJson
4431
- ],
4432
- {
4433
- encoding: "utf-8",
4434
- maxBuffer: 50 * 1024 * 1024,
4435
- timeout: 3e5,
4436
- cwd: projectRoot
4437
- }
4439
+ ["run", "--project", indexerProject, "--", ...args],
4440
+ { ...EXEC_OPTIONS, cwd }
4438
4441
  );
4439
4442
  } catch (retryErr) {
4440
4443
  const message = retryErr instanceof Error ? retryErr.message : String(retryErr);
4441
4444
  throw new Error(`.NET indexer failed: ${message}`, { cause: retryErr });
4442
4445
  }
4443
4446
  }
4447
+ }
4448
+ function indexDotnetProjectRoslyn(db, options) {
4449
+ const start = Date.now();
4450
+ const service = options.service ?? "main";
4451
+ const projectRoot = resolve(options.projectRoot);
4452
+ const dotnetProject = options.csprojPath ?? findDotnetProject(projectRoot);
4453
+ if (!dotnetProject) {
4454
+ throw new Error(
4455
+ "No .sln or .csproj file found in project root. The .NET indexer requires a project or solution file."
4456
+ );
4457
+ }
4458
+ const existingHashes = getExistingHashes(db, service);
4459
+ const hashesJson = JSON.stringify(Object.fromEntries(existingHashes));
4460
+ const stdout = runDotnetIndexer(dotnetProject, hashesJson, projectRoot);
4444
4461
  const lines = stdout.trim().split("\n");
4445
4462
  const jsonLine = lines.reverse().find((l) => l.startsWith("{"));
4446
4463
  if (!jsonLine) {
@@ -4522,7 +4539,7 @@ import { join as join10 } from "path";
4522
4539
  import { globbySync } from "globby";
4523
4540
 
4524
4541
  // src/indexer/csharp/parser.ts
4525
- import { accessSync, constants } from "fs";
4542
+ import { accessSync as accessSync2, constants as constants2 } from "fs";
4526
4543
  import { dirname as dirname2, resolve as resolve2 } from "path";
4527
4544
  import { fileURLToPath as fileURLToPath2 } from "url";
4528
4545
  import "web-tree-sitter";
@@ -4538,7 +4555,7 @@ function resolveGrammarPath() {
4538
4555
  ];
4539
4556
  for (const candidate of candidates) {
4540
4557
  try {
4541
- accessSync(candidate, constants.R_OK);
4558
+ accessSync2(candidate, constants2.R_OK);
4542
4559
  return candidate;
4543
4560
  } catch {
4544
4561
  continue;
@@ -5597,15 +5614,20 @@ function resolveCSharpBackend(projectRoot) {
5597
5614
  if (setting === "roslyn" || setting === "tree-sitter") {
5598
5615
  return setting;
5599
5616
  }
5600
- try {
5601
- execFileSync2("dotnet", ["--version"], {
5602
- encoding: "utf-8",
5603
- timeout: 5e3
5604
- });
5617
+ if (hasGlobalTool()) {
5605
5618
  return "roslyn";
5606
- } catch {
5607
- return "tree-sitter";
5608
5619
  }
5620
+ if (hasIndexerProject()) {
5621
+ try {
5622
+ execFileSync2("dotnet", ["--version"], {
5623
+ encoding: "utf-8",
5624
+ timeout: 5e3
5625
+ });
5626
+ return "roslyn";
5627
+ } catch {
5628
+ }
5629
+ }
5630
+ return "tree-sitter";
5609
5631
  }
5610
5632
  function indexTypeScriptProject(db, options) {
5611
5633
  const start = Date.now();