@rudderhq/cli 0.7.19 → 0.7.20-canary.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/dist/index.js CHANGED
@@ -22345,6 +22345,256 @@ var init_native_payload = __esm({
22345
22345
  }
22346
22346
  });
22347
22347
 
22348
+ // src/runtime/platform-dependencies.ts
22349
+ import { mkdir, readFile, rm } from "node:fs/promises";
22350
+ import path10 from "node:path";
22351
+ function runtimePackageJsonPath(cacheDir, packageName) {
22352
+ return path10.join(cacheDir, "node_modules", ...packageName.split("/"), "package.json");
22353
+ }
22354
+ async function readRuntimePackageJson(cacheDir, packageName) {
22355
+ try {
22356
+ return JSON.parse(await readFile(runtimePackageJsonPath(cacheDir, packageName), "utf8"));
22357
+ } catch {
22358
+ return null;
22359
+ }
22360
+ }
22361
+ async function canResolveRuntimePackage(cacheDir, packageName) {
22362
+ try {
22363
+ await readFile(runtimePackageJsonPath(cacheDir, packageName), "utf8");
22364
+ return true;
22365
+ } catch {
22366
+ return false;
22367
+ }
22368
+ }
22369
+ async function removeRuntimeInstallLocks(cacheDir) {
22370
+ await Promise.all([
22371
+ rm(path10.join(cacheDir, "package-lock.json"), { force: true }),
22372
+ rm(path10.join(cacheDir, "node_modules", ".package-lock.json"), { force: true })
22373
+ ]);
22374
+ }
22375
+ function packageNameFromSpec(packageSpec) {
22376
+ if (!packageSpec.startsWith("@")) {
22377
+ const versionSeparator2 = packageSpec.indexOf("@");
22378
+ return versionSeparator2 === -1 ? packageSpec : packageSpec.slice(0, versionSeparator2);
22379
+ }
22380
+ const versionSeparator = packageSpec.indexOf("@", 1);
22381
+ return versionSeparator === -1 ? packageSpec : packageSpec.slice(0, versionSeparator);
22382
+ }
22383
+ function normalizeOptionalDependencyVersion(versionRange) {
22384
+ const trimmed = versionRange?.trim();
22385
+ if (!trimmed) return null;
22386
+ const exactVersion = /^[~^]\s*([0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z.-]+)?)$/.exec(trimmed);
22387
+ return exactVersion?.[1] ?? trimmed;
22388
+ }
22389
+ async function installRuntimePackageInStaging(spawnSyncImpl, cacheDir, packageSpec, packageName, options) {
22390
+ const stagingDir = path10.join(cacheDir, `.platform-repair-${process.pid}-${Date.now()}`);
22391
+ await mkdir(stagingDir, { recursive: true });
22392
+ try {
22393
+ const packResult = runNpmPack(spawnSyncImpl, packageSpec, stagingDir, options);
22394
+ if (packResult.status !== 0) return packResult;
22395
+ const packFilename = parseNpmPackFilename(packResult.stdout);
22396
+ if (!packFilename) {
22397
+ return createSyntheticSpawnResult(1, "", `Unable to parse npm pack output for ${packageSpec}.`);
22398
+ }
22399
+ const archivePath = path10.join(stagingDir, packFilename);
22400
+ const targetDir = path10.dirname(runtimePackageJsonPath(cacheDir, packageName));
22401
+ await mkdir(path10.dirname(targetDir), { recursive: true });
22402
+ await rm(targetDir, { recursive: true, force: true });
22403
+ await mkdir(targetDir, { recursive: true });
22404
+ const extractResult = runTarExtract(spawnSyncImpl, archivePath, targetDir, options);
22405
+ return combineSpawnResults(packResult, extractResult);
22406
+ } finally {
22407
+ await rm(stagingDir, { recursive: true, force: true });
22408
+ }
22409
+ }
22410
+ function runNpmPack(spawnSyncImpl, packageSpec, destinationDir, options) {
22411
+ const timeout = options.remainingMs(options.deadline, options.cacheDir, `npm pack ${packageSpec}`);
22412
+ const npm = resolveNpmCommandInvocation();
22413
+ return spawnSyncImpl(
22414
+ npm.command,
22415
+ [
22416
+ ...npm.args,
22417
+ "pack",
22418
+ packageSpec,
22419
+ "--pack-destination",
22420
+ destinationDir,
22421
+ "--registry",
22422
+ NPM_PUBLIC_REGISTRY_URL,
22423
+ "--silent"
22424
+ ],
22425
+ {
22426
+ encoding: "utf8",
22427
+ stdio: ["ignore", "pipe", "pipe"],
22428
+ env: { ...process.env, ...NPM_PLATFORM_REPAIR_ENV },
22429
+ ...timeout === void 0 ? {} : { timeout },
22430
+ ...process.platform === "win32" ? { windowsHide: true } : {}
22431
+ }
22432
+ );
22433
+ }
22434
+ function runTarExtract(spawnSyncImpl, archivePath, targetDir, options) {
22435
+ const timeout = options.remainingMs(options.deadline, options.cacheDir, "extract runtime platform package");
22436
+ return spawnSyncImpl(
22437
+ "tar",
22438
+ ["-xzf", archivePath, "-C", targetDir, "--strip-components", "1"],
22439
+ {
22440
+ encoding: "utf8",
22441
+ stdio: ["ignore", "pipe", "pipe"],
22442
+ ...timeout === void 0 ? {} : { timeout },
22443
+ ...process.platform === "win32" ? { windowsHide: true } : {}
22444
+ }
22445
+ );
22446
+ }
22447
+ function parseNpmPackFilename(stdout) {
22448
+ if (typeof stdout !== "string") return null;
22449
+ const filename = stdout.trim().split(/\r?\n/).filter(Boolean).at(-1);
22450
+ return filename?.endsWith(".tgz") ? filename : null;
22451
+ }
22452
+ function createSyntheticSpawnResult(status, stdout, stderr) {
22453
+ return { status, stdout, stderr };
22454
+ }
22455
+ function combineSpawnResults(...results) {
22456
+ const last = results.at(-1);
22457
+ return {
22458
+ status: last?.status ?? 0,
22459
+ stdout: results.map((result) => result.stdout).filter(Boolean).join("\n"),
22460
+ stderr: results.map((result) => result.stderr).filter(Boolean).join("\n"),
22461
+ error: results.find((result) => result.error)?.error
22462
+ };
22463
+ }
22464
+ function isLinuxGlibcRuntime() {
22465
+ try {
22466
+ const report = process.report?.getReport();
22467
+ return typeof report.header?.glibcVersionRuntime === "string";
22468
+ } catch {
22469
+ return true;
22470
+ }
22471
+ }
22472
+ function resolveSharpPlatformPackageName(sharpPackage) {
22473
+ const platformPrefixes = process.platform === "linux" ? [
22474
+ isLinuxGlibcRuntime() ? "linux" : "linuxmusl",
22475
+ "linux",
22476
+ "linuxmusl"
22477
+ ] : [process.platform];
22478
+ for (const platformPrefix of platformPrefixes) {
22479
+ const packageName = `@img/sharp-${platformPrefix}-${process.arch}`;
22480
+ if (sharpPackage.optionalDependencies?.[packageName]) return packageName;
22481
+ }
22482
+ return null;
22483
+ }
22484
+ async function hasRequiredRuntimeNativeDependencies(cacheDir) {
22485
+ const sharpPackage = await readRuntimePackageJson(cacheDir, "sharp");
22486
+ if (!sharpPackage) return true;
22487
+ const platformPackageName = resolveSharpPlatformPackageName(sharpPackage);
22488
+ if (!platformPackageName) return true;
22489
+ const requiredPackages = [{
22490
+ name: platformPackageName,
22491
+ version: normalizeOptionalDependencyVersion(sharpPackage.optionalDependencies?.[platformPackageName])
22492
+ }];
22493
+ for (let index = 0; index < requiredPackages.length; index += 1) {
22494
+ const requiredPackage = requiredPackages[index];
22495
+ const packageJson = await readRuntimePackageJson(cacheDir, requiredPackage.name);
22496
+ if (!packageJson || requiredPackage.version !== null && packageJson.version !== requiredPackage.version) return false;
22497
+ for (const [dependencyName, versionRange] of Object.entries(packageJson.optionalDependencies ?? {})) {
22498
+ if (!requiredPackages.some(({ name }) => name === dependencyName)) {
22499
+ requiredPackages.push({
22500
+ name: dependencyName,
22501
+ version: normalizeOptionalDependencyVersion(versionRange)
22502
+ });
22503
+ }
22504
+ }
22505
+ }
22506
+ return true;
22507
+ }
22508
+ async function ensureRuntimeNativeDependencies(options) {
22509
+ if (process.env.RUDDER_RUNTIME_INSTALL_OMIT_OPTIONAL !== "true") return "";
22510
+ const sharpPackage = await readRuntimePackageJson(options.cacheDir, "sharp");
22511
+ if (!sharpPackage) return "";
22512
+ const platformPackageName = resolveSharpPlatformPackageName(sharpPackage);
22513
+ if (!platformPackageName) return "";
22514
+ const installOptions = {
22515
+ deadline: options.deadline,
22516
+ cacheDir: options.cacheDir,
22517
+ remainingMs: options.remainingMs
22518
+ };
22519
+ const requiredPackageVersions = /* @__PURE__ */ new Map([
22520
+ [platformPackageName, normalizeOptionalDependencyVersion(sharpPackage.optionalDependencies?.[platformPackageName])]
22521
+ ]);
22522
+ const requiredPackages = /* @__PURE__ */ new Set([platformPackageName]);
22523
+ let output = "";
22524
+ for (let pass = 0; pass < 8; pass += 1) {
22525
+ const missingSpecs = [];
22526
+ for (const packageName of requiredPackages) {
22527
+ const version = requiredPackageVersions.get(packageName) ?? null;
22528
+ const packageJson = await readRuntimePackageJson(options.cacheDir, packageName);
22529
+ if (packageJson && (version === null || packageJson.version === version)) continue;
22530
+ missingSpecs.push(version ? `${packageName}@${version}` : packageName);
22531
+ }
22532
+ if (missingSpecs.length > 0) {
22533
+ await removeRuntimeInstallLocks(options.cacheDir);
22534
+ for (const packageSpec of missingSpecs) {
22535
+ const packageName = packageNameFromSpec(packageSpec);
22536
+ const result = await installRuntimePackageInStaging(
22537
+ options.spawnSyncImpl,
22538
+ options.cacheDir,
22539
+ packageSpec,
22540
+ packageName,
22541
+ installOptions
22542
+ );
22543
+ output = collectOutputParts(output, collectSpawnOutput(result));
22544
+ if (result.status === 0 && await canResolveRuntimePackage(options.cacheDir, packageName)) continue;
22545
+ const command2 = formatRuntimePlatformRepairCommand(options.cacheDir, packageSpec);
22546
+ throw options.createError(
22547
+ `Rudder runtime installation is missing required native package ${packageName}. Re-run manually: ${command2}`,
22548
+ command2,
22549
+ output
22550
+ );
22551
+ }
22552
+ }
22553
+ let discoveredNewPackage = false;
22554
+ for (const packageName of [...requiredPackages]) {
22555
+ const packageJson = await readRuntimePackageJson(options.cacheDir, packageName);
22556
+ for (const [dependencyName, versionRange] of Object.entries(packageJson?.optionalDependencies ?? {})) {
22557
+ if (requiredPackages.has(dependencyName)) continue;
22558
+ requiredPackages.add(dependencyName);
22559
+ requiredPackageVersions.set(dependencyName, normalizeOptionalDependencyVersion(versionRange));
22560
+ discoveredNewPackage = true;
22561
+ }
22562
+ }
22563
+ if (!discoveredNewPackage && await hasRequiredRuntimeNativeDependencies(options.cacheDir)) return output;
22564
+ }
22565
+ const command = [...requiredPackages].map((packageName) => formatRuntimePlatformRepairCommand(
22566
+ options.cacheDir,
22567
+ requiredPackageVersions.get(packageName) ? `${packageName}@${requiredPackageVersions.get(packageName)}` : packageName
22568
+ )).join("; ");
22569
+ throw options.createError(
22570
+ "Rudder runtime native dependency preparation did not converge. Re-run manually: " + command,
22571
+ command,
22572
+ output
22573
+ );
22574
+ }
22575
+ function formatRuntimePlatformRepairCommand(cacheDir, packageSpec) {
22576
+ return `npm pack ${packageSpec} --registry=${NPM_PUBLIC_REGISTRY_URL} --silent, then extract it into ${path10.join(cacheDir, "node_modules")}`;
22577
+ }
22578
+ function collectSpawnOutput(result) {
22579
+ return [result.stdout, result.stderr, result.error instanceof Error ? result.error.message : null].filter((value) => typeof value === "string" && value.trim().length > 0).join("\n").trim();
22580
+ }
22581
+ function collectOutputParts(...parts) {
22582
+ return parts.filter((part) => part.trim().length > 0).join("\n").trim();
22583
+ }
22584
+ var NPM_PUBLIC_REGISTRY_URL, NPM_PLATFORM_REPAIR_ENV;
22585
+ var init_platform_dependencies = __esm({
22586
+ "src/runtime/platform-dependencies.ts"() {
22587
+ "use strict";
22588
+ init_npm_command();
22589
+ NPM_PUBLIC_REGISTRY_URL = "https://registry.npmjs.org";
22590
+ NPM_PLATFORM_REPAIR_ENV = {
22591
+ npm_config_registry: NPM_PUBLIC_REGISTRY_URL,
22592
+ npm_config_update_notifier: "false",
22593
+ NO_UPDATE_NOTIFIER: "1"
22594
+ };
22595
+ }
22596
+ });
22597
+
22348
22598
  // src/runtime/postgres-runtime-download.ts
22349
22599
  import { createHash as createHash3 } from "node:crypto";
22350
22600
  import { createReadStream, createWriteStream } from "node:fs";
@@ -22466,12 +22716,22 @@ var init_postgres_runtime_source = __esm({
22466
22716
  // src/runtime/install.ts
22467
22717
  import { execFileSync, spawnSync as spawnSync2 } from "node:child_process";
22468
22718
  import { createReadStream as createReadStream2, createWriteStream as createWriteStream2 } from "node:fs";
22469
- import { chmod, mkdir, mkdtemp, readFile, readdir, realpath, rename, rm, stat, symlink, writeFile } from "node:fs/promises";
22719
+ import { chmod, mkdir as mkdir2, mkdtemp, readFile as readFile2, readdir, realpath, rename, rm as rm2, stat, symlink, writeFile } from "node:fs/promises";
22470
22720
  import { createRequire } from "node:module";
22471
- import path10 from "node:path";
22721
+ import path11 from "node:path";
22472
22722
  import { performance as performance2 } from "node:perf_hooks";
22473
22723
  import { pipeline as pipeline2 } from "node:stream/promises";
22474
22724
  import { pathToFileURL } from "node:url";
22725
+ function omitOptionalRuntimeDependencies() {
22726
+ return process.env.RUDDER_RUNTIME_INSTALL_OMIT_OPTIONAL === "true";
22727
+ }
22728
+ function runtimeNpmInstallFlags() {
22729
+ return [
22730
+ ...RUNTIME_NPM_INSTALL_BASE_FLAGS,
22731
+ ...omitOptionalRuntimeDependencies() ? ["--omit=optional"] : RUNTIME_NPM_INSTALL_OPTIONAL_FLAGS,
22732
+ ...RUNTIME_NPM_INSTALL_SUFFIX_FLAGS
22733
+ ];
22734
+ }
22475
22735
  function createRuntimeInstallDeadline(options) {
22476
22736
  if (options.timeoutMs === void 0) return void 0;
22477
22737
  if (!Number.isFinite(options.timeoutMs) || options.timeoutMs <= 0) {
@@ -22512,7 +22772,7 @@ function resolveRuntimePackageVersion(version) {
22512
22772
  return normalized.length > 0 ? normalized : "latest";
22513
22773
  }
22514
22774
  function resolveRuntimeCacheDir(version, homeDir = resolveRudderHomeDir()) {
22515
- return path10.join(homeDir, "runtimes", sanitizeRuntimeCacheSegment(resolveRuntimePackageVersion(version)));
22775
+ return path11.join(homeDir, "runtimes", sanitizeRuntimeCacheSegment(resolveRuntimePackageVersion(version)));
22516
22776
  }
22517
22777
  function resolveRuntimePackageSpec(version, packageName = RUNTIME_NPM_PACKAGE_NAME) {
22518
22778
  const packageVersion = resolveRuntimePackageVersion(version);
@@ -22520,7 +22780,7 @@ function resolveRuntimePackageSpec(version, packageName = RUNTIME_NPM_PACKAGE_NA
22520
22780
  }
22521
22781
  async function readRuntimeInstallMetadata(cacheDir) {
22522
22782
  try {
22523
- const raw = await readFile(path10.join(cacheDir, RUNTIME_METADATA_FILE), "utf8");
22783
+ const raw = await readFile2(path11.join(cacheDir, RUNTIME_METADATA_FILE), "utf8");
22524
22784
  const parsed = JSON.parse(raw);
22525
22785
  if (parsed.version !== 1) return null;
22526
22786
  if (typeof parsed.packageName !== "string" || typeof parsed.packageVersion !== "string") return null;
@@ -22535,7 +22795,7 @@ async function readRuntimeInstallMetadata(cacheDir) {
22535
22795
  }
22536
22796
  }
22537
22797
  async function writeRuntimeInstallMetadata(cacheDir, metadata) {
22538
- await writeFile(path10.join(cacheDir, RUNTIME_METADATA_FILE), `${JSON.stringify(metadata, null, 2)}
22798
+ await writeFile(path11.join(cacheDir, RUNTIME_METADATA_FILE), `${JSON.stringify(metadata, null, 2)}
22539
22799
  `, "utf8");
22540
22800
  }
22541
22801
  async function touchRuntimeInstallMetadata(cacheDir, postgresRuntime) {
@@ -22561,23 +22821,16 @@ function resolveEmbeddedPostgresPlatformPackage(platform = process.platform, arc
22561
22821
  if (platform === "win32" && arch === "x64") return "@embedded-postgres/windows-x64";
22562
22822
  return null;
22563
22823
  }
22564
- async function canResolveRuntimePackage(cacheDir, packageName) {
22565
- try {
22566
- await readFile(path10.join(cacheDir, "node_modules", ...packageName.split("/"), "package.json"), "utf8");
22567
- return true;
22568
- } catch {
22569
- return false;
22570
- }
22571
- }
22572
22824
  async function hasRequiredRuntimePlatformDependencies(cacheDir, metadata, postgresVersionProbe, deadline) {
22825
+ if (omitOptionalRuntimeDependencies()) return hasRequiredRuntimeNativeDependencies(cacheDir);
22573
22826
  if (!await canResolveRuntimePackage(cacheDir, EMBEDDED_POSTGRES_PACKAGE_NAME)) return true;
22574
22827
  const platformPackage = resolveEmbeddedPostgresPlatformPackage();
22575
22828
  if (!platformPackage) return true;
22576
22829
  if (await canResolveRuntimePackage(cacheDir, platformPackage)) return true;
22577
22830
  const expectedSharedBinDir = resolveSharedRuntimePostgresPayloadBinDir(
22578
- path10.dirname(path10.dirname(cacheDir))
22831
+ path11.dirname(path11.dirname(cacheDir))
22579
22832
  );
22580
- return metadata.postgresRuntime?.scope === "shared" && metadata.postgresRuntime.platform === process.platform && metadata.postgresRuntime.arch === process.arch && path10.resolve(metadata.postgresRuntime.binDir) === path10.resolve(expectedSharedBinDir) && await isRuntimePostgresPayloadUsable(
22833
+ return metadata.postgresRuntime?.scope === "shared" && metadata.postgresRuntime.platform === process.platform && metadata.postgresRuntime.arch === process.arch && path11.resolve(metadata.postgresRuntime.binDir) === path11.resolve(expectedSharedBinDir) && await isRuntimePostgresPayloadUsable(
22581
22834
  cacheDir,
22582
22835
  metadata.postgresRuntime.binDir,
22583
22836
  postgresVersionProbe,
@@ -22592,8 +22845,8 @@ async function isRuntimeCacheHitWithinDeadline(options, deadline) {
22592
22845
  return false;
22593
22846
  }
22594
22847
  try {
22595
- const packageJsonPath = path10.join(options.cacheDir, "node_modules", ...packageName.split("/"), "package.json");
22596
- const packageJson = JSON.parse(await readFile(packageJsonPath, "utf8"));
22848
+ const packageJsonPath = path11.join(options.cacheDir, "node_modules", ...packageName.split("/"), "package.json");
22849
+ const packageJson = JSON.parse(await readFile2(packageJsonPath, "utf8"));
22597
22850
  const packageVersionMatches = packageVersion === "latest" || packageJson.version === packageVersion;
22598
22851
  return packageVersionMatches && await hasRequiredRuntimePlatformDependencies(
22599
22852
  options.cacheDir,
@@ -22612,7 +22865,7 @@ async function ensureRuntimeInstalled(options) {
22612
22865
  const cacheDir = resolveRuntimeCacheDir(packageVersion, homeDir);
22613
22866
  const deadline = createRuntimeInstallDeadline(options);
22614
22867
  return withRuntimeFilesystemLock(
22615
- path10.join(homeDir, "runtime-payloads", ".postgres-runtime.lifecycle.lock"),
22868
+ path11.join(homeDir, "runtime-payloads", ".postgres-runtime.lifecycle.lock"),
22616
22869
  async () => withRuntimeFilesystemLock(
22617
22870
  `${cacheDir}.install.lock`,
22618
22871
  async () => {
@@ -22635,7 +22888,7 @@ async function ensureRuntimeInstalled(options) {
22635
22888
  );
22636
22889
  }
22637
22890
  function scheduleIncompleteRuntimeCacheCleanup(options) {
22638
- const remove = options.remove ?? ((cacheDir) => rm(cacheDir, { recursive: true, force: true }));
22891
+ const remove = options.remove ?? ((cacheDir) => rm2(cacheDir, { recursive: true, force: true }));
22639
22892
  void withRuntimeFilesystemLock(
22640
22893
  `${options.cacheDir}.install.lock`,
22641
22894
  async () => {
@@ -22733,12 +22986,12 @@ async function ensureRuntimeInstalledUnlocked(options, deadline) {
22733
22986
  postgresPayload2
22734
22987
  );
22735
22988
  }
22736
- await rm(cacheDir, { recursive: true, force: true });
22737
- await mkdir(cacheDir, { recursive: true });
22738
- await writeFile(path10.join(cacheDir, "package.json"), `${JSON.stringify(RUNTIME_CACHE_PACKAGE_JSON, null, 2)}
22989
+ await rm2(cacheDir, { recursive: true, force: true });
22990
+ await mkdir2(cacheDir, { recursive: true });
22991
+ await writeFile(path11.join(cacheDir, "package.json"), `${JSON.stringify(RUNTIME_CACHE_PACKAGE_JSON, null, 2)}
22739
22992
  `, "utf8");
22740
22993
  const result = runNpmRuntimeInstall(spawnSyncImpl, cacheDir, packageSpec, deadline);
22741
- let output = collectSpawnOutput(result);
22994
+ let output = collectSpawnOutput2(result);
22742
22995
  if (result.status !== 0 && packageVersion !== "latest" && options.allowLatestFallback !== false && isVersionNotFoundError(output)) {
22743
22996
  const fallbackVersion = "latest";
22744
22997
  const fallbackCacheDir = resolveRuntimeCacheDir(fallbackVersion, options.homeDir);
@@ -22773,16 +23026,17 @@ async function ensureRuntimeInstalledUnlocked(options, deadline) {
22773
23026
  fallbackPostgresPayload
22774
23027
  );
22775
23028
  }
22776
- await rm(fallbackCacheDir, { recursive: true, force: true });
22777
- await mkdir(fallbackCacheDir, { recursive: true });
22778
- await writeFile(path10.join(fallbackCacheDir, "package.json"), `${JSON.stringify(RUNTIME_CACHE_PACKAGE_JSON, null, 2)}
23029
+ await rm2(fallbackCacheDir, { recursive: true, force: true });
23030
+ await mkdir2(fallbackCacheDir, { recursive: true });
23031
+ await writeFile(path11.join(fallbackCacheDir, "package.json"), `${JSON.stringify(RUNTIME_CACHE_PACKAGE_JSON, null, 2)}
22779
23032
  `, "utf8");
22780
23033
  const fallbackResult = runNpmRuntimeInstall(spawnSyncImpl, fallbackCacheDir, fallbackSpec, deadline);
22781
- let fallbackOutput = collectSpawnOutput(fallbackResult);
23034
+ let fallbackOutput = collectSpawnOutput2(fallbackResult);
22782
23035
  if (fallbackResult.status !== 0) return null;
22783
- fallbackOutput = collectOutputParts(
23036
+ fallbackOutput = collectOutputParts2(
22784
23037
  fallbackOutput,
22785
- await ensureRequiredEmbeddedPostgresPlatformPackage(spawnSyncImpl, fallbackCacheDir, deadline)
23038
+ await ensureRequiredEmbeddedPostgresPlatformPackage(spawnSyncImpl, fallbackCacheDir, deadline),
23039
+ await ensureRuntimeNativeDependenciesForCache(spawnSyncImpl, fallbackCacheDir, deadline)
22786
23040
  );
22787
23041
  const postgresPayload2 = await stageRuntimePostgresPayload(
22788
23042
  fallbackCacheDir,
@@ -22823,9 +23077,10 @@ async function ensureRuntimeInstalledUnlocked(options, deadline) {
22823
23077
  { cacheDir, command, output }
22824
23078
  );
22825
23079
  }
22826
- output = collectOutputParts(
23080
+ output = collectOutputParts2(
22827
23081
  output,
22828
- await ensureRequiredEmbeddedPostgresPlatformPackage(spawnSyncImpl, cacheDir, deadline)
23082
+ await ensureRequiredEmbeddedPostgresPlatformPackage(spawnSyncImpl, cacheDir, deadline),
23083
+ await ensureRuntimeNativeDependenciesForCache(spawnSyncImpl, cacheDir, deadline)
22829
23084
  );
22830
23085
  const postgresPayload = await stageRuntimePostgresPayload(
22831
23086
  cacheDir,
@@ -22857,10 +23112,10 @@ async function ensureRuntimeInstalledUnlocked(options, deadline) {
22857
23112
  );
22858
23113
  }
22859
23114
  function resolveRuntimePostgresPayloadBinDir(cacheDir, platform = process.platform, arch = process.arch) {
22860
- return path10.join(cacheDir, RUNTIME_POSTGRES_PAYLOAD_DIR, runtimePostgresPlatformSegment(platform, arch), "bin");
23115
+ return path11.join(cacheDir, RUNTIME_POSTGRES_PAYLOAD_DIR, runtimePostgresPlatformSegment(platform, arch), "bin");
22861
23116
  }
22862
23117
  function resolveSharedRuntimePostgresPayloadBinDir(homeDir = resolveRudderHomeDir(), platform = process.platform, arch = process.arch) {
22863
- return path10.join(
23118
+ return path11.join(
22864
23119
  homeDir,
22865
23120
  "runtime-payloads",
22866
23121
  RUNTIME_POSTGRES_PAYLOAD_DIR,
@@ -22869,7 +23124,7 @@ function resolveSharedRuntimePostgresPayloadBinDir(homeDir = resolveRudderHomeDi
22869
23124
  );
22870
23125
  }
22871
23126
  function resolveRuntimeServerEntrypoint(cacheDir, packageName = RUNTIME_NPM_PACKAGE_NAME) {
22872
- return createRequire(path10.join(cacheDir, "package.json")).resolve(packageName);
23127
+ return createRequire(path11.join(cacheDir, "package.json")).resolve(packageName);
22873
23128
  }
22874
23129
  async function importRuntimeServerModule(cacheDir, packageName = RUNTIME_NPM_PACKAGE_NAME) {
22875
23130
  const entrypoint = resolveRuntimeServerEntrypoint(cacheDir, packageName);
@@ -22880,7 +23135,7 @@ function runNpmRuntimeInstall(spawnSyncImpl, cacheDir, packageSpec, deadline) {
22880
23135
  const npm = resolveNpmCommandInvocation();
22881
23136
  return spawnSyncImpl(
22882
23137
  npm.command,
22883
- [...npm.args, "install", "--prefix", cacheDir, ...RUNTIME_NPM_INSTALL_FLAGS, packageSpec],
23138
+ [...npm.args, "install", "--prefix", cacheDir, ...runtimeNpmInstallFlags(), packageSpec],
22884
23139
  {
22885
23140
  encoding: "utf8",
22886
23141
  stdio: ["ignore", "pipe", "pipe"],
@@ -22890,35 +23145,25 @@ function runNpmRuntimeInstall(spawnSyncImpl, cacheDir, packageSpec, deadline) {
22890
23145
  );
22891
23146
  }
22892
23147
  function formatRuntimeInstallCommand(cacheDir, packageSpec) {
22893
- return `npm install --prefix ${cacheDir} ${RUNTIME_NPM_INSTALL_FLAGS.join(" ")} ${packageSpec}`;
23148
+ return `npm install --prefix ${cacheDir} ${runtimeNpmInstallFlags().join(" ")} ${packageSpec}`;
22894
23149
  }
22895
- function formatRuntimePlatformRepairCommand(cacheDir, packageSpec) {
22896
- return `npm pack ${packageSpec} --registry=${NPM_PUBLIC_REGISTRY_URL} --silent, then extract it into ${path10.join(cacheDir, "node_modules")}`;
23150
+ function formatRuntimePlatformRepairCommand2(cacheDir, packageSpec) {
23151
+ return `npm pack ${packageSpec} --registry=${NPM_PUBLIC_REGISTRY_URL2} --silent, then extract it into ${path11.join(cacheDir, "node_modules")}`;
22897
23152
  }
22898
- function collectSpawnOutput(result) {
23153
+ function collectSpawnOutput2(result) {
22899
23154
  return [result.stdout, result.stderr, result.error instanceof Error ? result.error.message : null].filter((value) => typeof value === "string" && value.trim().length > 0).join("\n").trim();
22900
23155
  }
22901
- function collectOutputParts(...parts) {
23156
+ function collectOutputParts2(...parts) {
22902
23157
  return parts.filter((part) => part.trim().length > 0).join("\n").trim();
22903
23158
  }
22904
23159
  function withPostgresPayload(result, postgresPayload) {
22905
23160
  return {
22906
23161
  ...result,
22907
- output: collectOutputParts(result.output, postgresPayload.output),
23162
+ output: collectOutputParts2(result.output, postgresPayload.output),
22908
23163
  ...postgresPayload.binDir ? { postgresPayloadBinDir: postgresPayload.binDir } : {},
22909
23164
  ...postgresPayload.metadata ? { postgresRuntime: postgresPayload.metadata } : {}
22910
23165
  };
22911
23166
  }
22912
- function runtimePackageJsonPath(cacheDir, packageName) {
22913
- return path10.join(cacheDir, "node_modules", ...packageName.split("/"), "package.json");
22914
- }
22915
- async function readRuntimePackageJson(cacheDir, packageName) {
22916
- try {
22917
- return JSON.parse(await readFile(runtimePackageJsonPath(cacheDir, packageName), "utf8"));
22918
- } catch {
22919
- return null;
22920
- }
22921
- }
22922
23167
  async function tryRepairExistingRuntimePackage(options) {
22923
23168
  const runtimePackage = await readRuntimePackageJson(options.cacheDir, options.packageName);
22924
23169
  if (!runtimePackage) return null;
@@ -22928,9 +23173,24 @@ async function tryRepairExistingRuntimePackage(options) {
22928
23173
  options.cacheDir,
22929
23174
  options.deadline
22930
23175
  );
22931
- if (!await canResolveRuntimePackage(options.cacheDir, EMBEDDED_POSTGRES_PACKAGE_NAME)) return output;
23176
+ const nativeOutput = await ensureRuntimeNativeDependenciesForCache(
23177
+ options.spawnSyncImpl,
23178
+ options.cacheDir,
23179
+ options.deadline
23180
+ );
23181
+ const combinedOutput = collectOutputParts2(output, nativeOutput);
23182
+ if (!await canResolveRuntimePackage(options.cacheDir, EMBEDDED_POSTGRES_PACKAGE_NAME)) return combinedOutput;
22932
23183
  const platformPackage = resolveEmbeddedPostgresPlatformPackage();
22933
- return !platformPackage || await canResolveRuntimePackage(options.cacheDir, platformPackage) ? output : null;
23184
+ return !platformPackage || await canResolveRuntimePackage(options.cacheDir, platformPackage) ? combinedOutput : null;
23185
+ }
23186
+ async function ensureRuntimeNativeDependenciesForCache(spawnSyncImpl, cacheDir, deadline) {
23187
+ return ensureRuntimeNativeDependencies({
23188
+ spawnSyncImpl,
23189
+ cacheDir,
23190
+ deadline,
23191
+ remainingMs: remainingRuntimeInstallMs,
23192
+ createError: (message, command, output) => new RuntimeInstallError(message, { cacheDir, command, output })
23193
+ });
22934
23194
  }
22935
23195
  async function resolveEmbeddedPostgresPlatformPackageSpec(cacheDir) {
22936
23196
  if (!await canResolveRuntimePackage(cacheDir, EMBEDDED_POSTGRES_PACKAGE_NAME)) return null;
@@ -22942,6 +23202,7 @@ async function resolveEmbeddedPostgresPlatformPackageSpec(cacheDir) {
22942
23202
  return packageVersion ? `${packageName}@${packageVersion}` : packageName;
22943
23203
  }
22944
23204
  async function ensureRequiredEmbeddedPostgresPlatformPackage(spawnSyncImpl, cacheDir, deadline) {
23205
+ if (omitOptionalRuntimeDependencies()) return "";
22945
23206
  const packageSpec = await resolveEmbeddedPostgresPlatformPackageSpec(cacheDir);
22946
23207
  if (!packageSpec) return "";
22947
23208
  const packageName = packageNameFromSpec(packageSpec);
@@ -22952,104 +23213,18 @@ async function ensureRequiredEmbeddedPostgresPlatformPackage(spawnSyncImpl, cach
22952
23213
  cacheDir,
22953
23214
  packageSpec,
22954
23215
  packageName,
22955
- deadline
23216
+ { cacheDir, deadline, remainingMs: remainingRuntimeInstallMs }
22956
23217
  );
22957
- const output = collectSpawnOutput(result);
23218
+ const output = collectSpawnOutput2(result);
22958
23219
  if (result.status === 0 && packageName && await canResolveRuntimePackage(cacheDir, packageName)) {
22959
23220
  return output;
22960
23221
  }
22961
- const command = formatRuntimePlatformRepairCommand(cacheDir, packageSpec);
23222
+ const command = formatRuntimePlatformRepairCommand2(cacheDir, packageSpec);
22962
23223
  throw new RuntimeInstallError(
22963
23224
  `Rudder runtime installation is missing required platform package ${packageName || packageSpec}. Re-run manually: ${command}`,
22964
23225
  { cacheDir, command, output }
22965
23226
  );
22966
23227
  }
22967
- async function installRuntimePackageInStaging(spawnSyncImpl, cacheDir, packageSpec, packageName, deadline) {
22968
- const stagingDir = path10.join(cacheDir, `.platform-repair-${process.pid}-${Date.now()}`);
22969
- await mkdir(stagingDir, { recursive: true });
22970
- try {
22971
- const packResult = runNpmPack(spawnSyncImpl, packageSpec, stagingDir, cacheDir, deadline);
22972
- if (packResult.status !== 0) return packResult;
22973
- const packFilename = parseNpmPackFilename(packResult.stdout);
22974
- if (!packFilename) {
22975
- return createSyntheticSpawnResult(1, "", `Unable to parse npm pack output for ${packageSpec}.`);
22976
- }
22977
- const archivePath = path10.join(stagingDir, packFilename);
22978
- const targetDir = path10.dirname(runtimePackageJsonPath(cacheDir, packageName));
22979
- await mkdir(path10.dirname(targetDir), { recursive: true });
22980
- await rm(targetDir, { recursive: true, force: true });
22981
- await mkdir(targetDir, { recursive: true });
22982
- const extractResult = runTarExtract(spawnSyncImpl, archivePath, targetDir, cacheDir, deadline);
22983
- return combineSpawnResults(packResult, extractResult);
22984
- } finally {
22985
- await rm(stagingDir, { recursive: true, force: true });
22986
- }
22987
- }
22988
- function runNpmPack(spawnSyncImpl, packageSpec, destinationDir, cacheDir, deadline) {
22989
- const timeout = remainingRuntimeInstallMs(deadline, cacheDir, `npm pack ${packageSpec}`);
22990
- const npm = resolveNpmCommandInvocation();
22991
- return spawnSyncImpl(
22992
- npm.command,
22993
- [...npm.args, "pack", packageSpec, "--pack-destination", destinationDir, ...RUNTIME_NPM_PACK_FLAGS],
22994
- {
22995
- encoding: "utf8",
22996
- stdio: ["ignore", "pipe", "pipe"],
22997
- env: { ...process.env, ...NPM_PLATFORM_REPAIR_ENV },
22998
- ...timeout === void 0 ? {} : { timeout },
22999
- ...process.platform === "win32" ? { windowsHide: true } : {}
23000
- }
23001
- );
23002
- }
23003
- function runTarExtract(spawnSyncImpl, archivePath, targetDir, cacheDir, deadline) {
23004
- const timeout = remainingRuntimeInstallMs(deadline, cacheDir, "extract runtime platform package");
23005
- return spawnSyncImpl(
23006
- "tar",
23007
- ["-xzf", archivePath, "-C", targetDir, "--strip-components", "1"],
23008
- {
23009
- encoding: "utf8",
23010
- stdio: ["ignore", "pipe", "pipe"],
23011
- ...timeout === void 0 ? {} : { timeout },
23012
- ...process.platform === "win32" ? { windowsHide: true } : {}
23013
- }
23014
- );
23015
- }
23016
- function parseNpmPackFilename(stdout) {
23017
- if (typeof stdout !== "string") return null;
23018
- const filename = stdout.trim().split(/\r?\n/).filter(Boolean).at(-1);
23019
- return filename?.endsWith(".tgz") ? filename : null;
23020
- }
23021
- function createSyntheticSpawnResult(status, stdout, stderr) {
23022
- return { status, stdout, stderr };
23023
- }
23024
- function combineSpawnResults(...results) {
23025
- const last = results.at(-1);
23026
- return {
23027
- status: last?.status ?? 0,
23028
- stdout: results.map((result) => result.stdout).filter(Boolean).join("\n"),
23029
- stderr: results.map((result) => result.stderr).filter(Boolean).join("\n"),
23030
- error: results.find((result) => result.error)?.error
23031
- };
23032
- }
23033
- async function removeRuntimeInstallLocks(cacheDir) {
23034
- await Promise.all([
23035
- rm(path10.join(cacheDir, "package-lock.json"), { force: true }),
23036
- rm(path10.join(cacheDir, "node_modules", ".package-lock.json"), { force: true })
23037
- ]);
23038
- }
23039
- function packageNameFromSpec(packageSpec) {
23040
- if (!packageSpec.startsWith("@")) {
23041
- const versionSeparator2 = packageSpec.indexOf("@");
23042
- return versionSeparator2 === -1 ? packageSpec : packageSpec.slice(0, versionSeparator2);
23043
- }
23044
- const versionSeparator = packageSpec.indexOf("@", 1);
23045
- return versionSeparator === -1 ? packageSpec : packageSpec.slice(0, versionSeparator);
23046
- }
23047
- function normalizeOptionalDependencyVersion(versionRange) {
23048
- const trimmed = versionRange?.trim();
23049
- if (!trimmed) return null;
23050
- const exactVersion = /^[~^]\s*([0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z.-]+)?)$/.exec(trimmed);
23051
- return exactVersion?.[1] ?? trimmed;
23052
- }
23053
23228
  function runtimePostgresPlatformSegment(platform = process.platform, arch = process.arch) {
23054
23229
  return `${platform}-${arch}`;
23055
23230
  }
@@ -23057,25 +23232,25 @@ function runtimePostgresExecutableName(baseName) {
23057
23232
  return process.platform === "win32" ? `${baseName}.exe` : baseName;
23058
23233
  }
23059
23234
  function debianSharedirCandidate(binDir) {
23060
- const normalized = path10.resolve(binDir);
23061
- const parts = normalized.split(path10.sep);
23235
+ const normalized = path11.resolve(binDir);
23236
+ const parts = normalized.split(path11.sep);
23062
23237
  const libIndex = parts.lastIndexOf("lib");
23063
23238
  if (libIndex < 0) return null;
23064
23239
  if (parts[libIndex + 1] !== "postgresql") return null;
23065
23240
  const version = parts[libIndex + 2];
23066
23241
  if (!version || parts[libIndex + 3] !== "bin") return null;
23067
- const prefix = parts.slice(0, libIndex).join(path10.sep) || path10.sep;
23068
- return path10.join(prefix, "share", "postgresql", version);
23242
+ const prefix = parts.slice(0, libIndex).join(path11.sep) || path11.sep;
23243
+ return path11.join(prefix, "share", "postgresql", version);
23069
23244
  }
23070
23245
  async function resolveRuntimePostgresTemplateDir(binDir, cacheDir = binDir, deadline) {
23071
23246
  for (const candidatePath of [
23072
- path10.join(binDir, "..", "share", "postgresql", "postgres.bki"),
23073
- path10.join(binDir, "..", "share", "postgres.bki")
23247
+ path11.join(binDir, "..", "share", "postgresql", "postgres.bki"),
23248
+ path11.join(binDir, "..", "share", "postgres.bki")
23074
23249
  ]) {
23075
23250
  remainingRuntimeInstallMs(deadline, cacheDir, "discover PostgreSQL runtime templates");
23076
23251
  try {
23077
23252
  await stat(candidatePath);
23078
- return path10.dirname(candidatePath);
23253
+ return path11.dirname(candidatePath);
23079
23254
  } catch {
23080
23255
  }
23081
23256
  }
@@ -23083,12 +23258,12 @@ async function resolveRuntimePostgresTemplateDir(binDir, cacheDir = binDir, dead
23083
23258
  if (debianSharedir) {
23084
23259
  remainingRuntimeInstallMs(deadline, cacheDir, "discover PostgreSQL runtime templates");
23085
23260
  try {
23086
- await stat(path10.join(debianSharedir, "postgres.bki"));
23261
+ await stat(path11.join(debianSharedir, "postgres.bki"));
23087
23262
  return debianSharedir;
23088
23263
  } catch {
23089
23264
  }
23090
23265
  }
23091
- const pgConfigPath = path10.join(binDir, process.platform === "win32" ? "pg_config.exe" : "pg_config");
23266
+ const pgConfigPath = path11.join(binDir, process.platform === "win32" ? "pg_config.exe" : "pg_config");
23092
23267
  try {
23093
23268
  remainingRuntimeInstallMs(deadline, cacheDir, "discover PostgreSQL runtime templates");
23094
23269
  await stat(pgConfigPath);
@@ -23107,7 +23282,7 @@ async function resolveRuntimePostgresTemplateDir(binDir, cacheDir = binDir, dead
23107
23282
  }
23108
23283
  if (!sharedir) return null;
23109
23284
  remainingRuntimeInstallMs(deadline, cacheDir, "validate PostgreSQL runtime templates");
23110
- const candidatePath = path10.join(sharedir, "postgres.bki");
23285
+ const candidatePath = path11.join(sharedir, "postgres.bki");
23111
23286
  await stat(candidatePath);
23112
23287
  return sharedir;
23113
23288
  } catch (error) {
@@ -23116,7 +23291,7 @@ async function resolveRuntimePostgresTemplateDir(binDir, cacheDir = binDir, dead
23116
23291
  }
23117
23292
  }
23118
23293
  function resolveRuntimePostgresShareDir(binDir, templateDir) {
23119
- const adjacentShareDir = path10.resolve(binDir, "..", "share");
23294
+ const adjacentShareDir = path11.resolve(binDir, "..", "share");
23120
23295
  return pathIsInside(templateDir, adjacentShareDir) ? adjacentShareDir : templateDir;
23121
23296
  }
23122
23297
  async function assertRuntimePostgresBinDirComplete(cacheDir, binDir, deadline) {
@@ -23124,7 +23299,7 @@ async function assertRuntimePostgresBinDirComplete(cacheDir, binDir, deadline) {
23124
23299
  const missing = [];
23125
23300
  for (const binary of requiredBinaries) {
23126
23301
  remainingRuntimeInstallMs(deadline, cacheDir, "validate PostgreSQL runtime binaries");
23127
- const binaryPath = path10.join(binDir, runtimePostgresExecutableName(binary));
23302
+ const binaryPath = path11.join(binDir, runtimePostgresExecutableName(binary));
23128
23303
  try {
23129
23304
  await stat(binaryPath);
23130
23305
  } catch {
@@ -23133,19 +23308,19 @@ async function assertRuntimePostgresBinDirComplete(cacheDir, binDir, deadline) {
23133
23308
  }
23134
23309
  const templateDir = await resolveRuntimePostgresTemplateDir(binDir, cacheDir, deadline);
23135
23310
  if (!templateDir) {
23136
- missing.push(path10.join(binDir, "..", "share", "postgresql", "postgres.bki"));
23311
+ missing.push(path11.join(binDir, "..", "share", "postgresql", "postgres.bki"));
23137
23312
  } else {
23138
23313
  try {
23139
- await stat(path10.join(templateDir, "postgresql.conf.sample"));
23314
+ await stat(path11.join(templateDir, "postgresql.conf.sample"));
23140
23315
  } catch {
23141
- missing.push(path10.join(templateDir, "postgresql.conf.sample"));
23316
+ missing.push(path11.join(templateDir, "postgresql.conf.sample"));
23142
23317
  }
23143
23318
  const shareDir = resolveRuntimePostgresShareDir(binDir, templateDir);
23144
23319
  const hasTimezoneDir = (await Promise.all([
23145
- path10.join(templateDir, "timezone"),
23146
- path10.join(shareDir, "timezone")
23320
+ path11.join(templateDir, "timezone"),
23321
+ path11.join(shareDir, "timezone")
23147
23322
  ].map((candidate) => stat(candidate).catch(() => null)))).some((candidate) => candidate?.isDirectory());
23148
- if (!hasTimezoneDir) missing.push(path10.join(shareDir, "timezone"));
23323
+ if (!hasTimezoneDir) missing.push(path11.join(shareDir, "timezone"));
23149
23324
  }
23150
23325
  if (missing.length > 0) {
23151
23326
  throw new RuntimeInstallError(
@@ -23170,8 +23345,8 @@ async function isRuntimePostgresPayloadUsable(cacheDir, binDir, postgresVersionP
23170
23345
  }
23171
23346
  }
23172
23347
  function pathIsInside(candidatePath, rootPath) {
23173
- const relative = path10.relative(path10.resolve(rootPath), path10.resolve(candidatePath));
23174
- return relative === "" || relative !== ".." && !relative.startsWith(`..${path10.sep}`) && !path10.isAbsolute(relative);
23348
+ const relative = path11.relative(path11.resolve(rootPath), path11.resolve(candidatePath));
23349
+ return relative === "" || relative !== ".." && !relative.startsWith(`..${path11.sep}`) && !path11.isAbsolute(relative);
23175
23350
  }
23176
23351
  async function copyRuntimePayloadEntry(sourcePath, targetPath, cacheDir, deadline, signal, command) {
23177
23352
  if (signal.aborted) throw runtimeInstallDeadlineError(cacheDir, command);
@@ -23180,12 +23355,12 @@ async function copyRuntimePayloadEntry(sourcePath, targetPath, cacheDir, deadlin
23180
23355
  if (signal.aborted) throw runtimeInstallDeadlineError(cacheDir, command);
23181
23356
  remainingRuntimeInstallMs(deadline, cacheDir, command);
23182
23357
  if (sourceStats.isDirectory()) {
23183
- await mkdir(targetPath, { recursive: true });
23358
+ await mkdir2(targetPath, { recursive: true });
23184
23359
  const entries = await readdir(sourcePath);
23185
23360
  for (const entry of entries) {
23186
23361
  await copyRuntimePayloadEntry(
23187
- path10.join(sourcePath, entry),
23188
- path10.join(targetPath, entry),
23362
+ path11.join(sourcePath, entry),
23363
+ path11.join(targetPath, entry),
23189
23364
  cacheDir,
23190
23365
  deadline,
23191
23366
  signal,
@@ -23195,7 +23370,7 @@ async function copyRuntimePayloadEntry(sourcePath, targetPath, cacheDir, deadlin
23195
23370
  return;
23196
23371
  }
23197
23372
  if (!sourceStats.isFile()) return;
23198
- await mkdir(path10.dirname(targetPath), { recursive: true });
23373
+ await mkdir2(path11.dirname(targetPath), { recursive: true });
23199
23374
  try {
23200
23375
  await pipeline2(
23201
23376
  createReadStream2(sourcePath),
@@ -23205,7 +23380,7 @@ async function copyRuntimePayloadEntry(sourcePath, targetPath, cacheDir, deadlin
23205
23380
  await chmod(targetPath, sourceStats.mode);
23206
23381
  remainingRuntimeInstallMs(deadline, cacheDir, command);
23207
23382
  } catch (error) {
23208
- await rm(targetPath, { force: true });
23383
+ await rm2(targetPath, { force: true });
23209
23384
  if (signal.aborted || isRuntimeInstallDeadlineError(error)) {
23210
23385
  throw runtimeInstallDeadlineError(cacheDir, command);
23211
23386
  }
@@ -23227,13 +23402,13 @@ async function copyRuntimePostgresPayloadWithinDeadline(sourceRuntimeDir, target
23227
23402
  }, timeoutMs);
23228
23403
  });
23229
23404
  const copyPromise = (async () => {
23230
- await mkdir(targetRuntimeDir, { recursive: true });
23405
+ await mkdir2(targetRuntimeDir, { recursive: true });
23231
23406
  for (const directoryName of ["bin", "lib"]) {
23232
- const sourceDirectory = path10.join(sourceRuntimeDir, directoryName);
23407
+ const sourceDirectory = path11.join(sourceRuntimeDir, directoryName);
23233
23408
  if (!await stat(sourceDirectory).catch(() => null)) continue;
23234
23409
  await copyRuntimePayloadEntry(
23235
23410
  sourceDirectory,
23236
- path10.join(targetRuntimeDir, directoryName),
23411
+ path11.join(targetRuntimeDir, directoryName),
23237
23412
  cacheDir,
23238
23413
  deadline,
23239
23414
  controller.signal,
@@ -23242,7 +23417,7 @@ async function copyRuntimePostgresPayloadWithinDeadline(sourceRuntimeDir, target
23242
23417
  }
23243
23418
  await copyRuntimePayloadEntry(
23244
23419
  sourceShareDir,
23245
- path10.join(targetRuntimeDir, "share"),
23420
+ path11.join(targetRuntimeDir, "share"),
23246
23421
  cacheDir,
23247
23422
  deadline,
23248
23423
  controller.signal,
@@ -23260,18 +23435,18 @@ async function copyRuntimePostgresPayloadWithinDeadline(sourceRuntimeDir, target
23260
23435
  async function withRuntimeFilesystemLock(lockPath, task, options = {}) {
23261
23436
  const deadlineTimeout = remainingRuntimeInstallMs(
23262
23437
  options.deadline,
23263
- options.cacheDir ?? path10.dirname(lockPath),
23438
+ options.cacheDir ?? path11.dirname(lockPath),
23264
23439
  options.command ?? `wait for runtime lock ${lockPath}`
23265
23440
  );
23266
23441
  const timeoutMs = Math.min(options.timeoutMs ?? 3e4, deadlineTimeout ?? Number.POSITIVE_INFINITY);
23267
23442
  const pollMs = options.pollMs ?? 50;
23268
23443
  const startedAt = Date.now();
23269
23444
  const lockId = `${process.pid}-${startedAt}-${Math.random().toString(16).slice(2)}`;
23270
- const ownerPath = path10.join(lockPath, "owner.json");
23271
- await mkdir(path10.dirname(lockPath), { recursive: true });
23445
+ const ownerPath = path11.join(lockPath, "owner.json");
23446
+ await mkdir2(path11.dirname(lockPath), { recursive: true });
23272
23447
  while (true) {
23273
23448
  try {
23274
- await mkdir(lockPath);
23449
+ await mkdir2(lockPath);
23275
23450
  await writeFile(
23276
23451
  ownerPath,
23277
23452
  `${JSON.stringify({ pid: process.pid, lockId, createdAt: (/* @__PURE__ */ new Date()).toISOString() })}
@@ -23282,27 +23457,27 @@ async function withRuntimeFilesystemLock(lockPath, task, options = {}) {
23282
23457
  } catch (error) {
23283
23458
  if (error.code !== "EEXIST") throw error;
23284
23459
  try {
23285
- const existing = JSON.parse(await readFile(ownerPath, "utf8"));
23460
+ const existing = JSON.parse(await readFile2(ownerPath, "utf8"));
23286
23461
  if (typeof existing.pid !== "number" || !isPidRunning(existing.pid)) {
23287
- await rm(lockPath, { recursive: true, force: true });
23462
+ await rm2(lockPath, { recursive: true, force: true });
23288
23463
  continue;
23289
23464
  }
23290
23465
  } catch {
23291
23466
  const lockStats = await stat(lockPath).catch(() => null);
23292
23467
  if (lockStats && Date.now() - lockStats.mtimeMs > 5e3) {
23293
- await rm(lockPath, { recursive: true, force: true });
23468
+ await rm2(lockPath, { recursive: true, force: true });
23294
23469
  continue;
23295
23470
  }
23296
23471
  }
23297
23472
  if (Date.now() - startedAt >= timeoutMs) {
23298
23473
  throw new RuntimeInstallError(
23299
23474
  `Timed out waiting for PostgreSQL runtime install lock ${lockPath}`,
23300
- { cacheDir: path10.dirname(lockPath), command: "prepare shared PostgreSQL runtime", output: "" }
23475
+ { cacheDir: path11.dirname(lockPath), command: "prepare shared PostgreSQL runtime", output: "" }
23301
23476
  );
23302
23477
  }
23303
23478
  remainingRuntimeInstallMs(
23304
23479
  options.deadline,
23305
- options.cacheDir ?? path10.dirname(lockPath),
23480
+ options.cacheDir ?? path11.dirname(lockPath),
23306
23481
  options.command ?? `wait for runtime lock ${lockPath}`
23307
23482
  );
23308
23483
  await new Promise((resolve) => setTimeout(resolve, pollMs));
@@ -23312,9 +23487,9 @@ async function withRuntimeFilesystemLock(lockPath, task, options = {}) {
23312
23487
  return await task();
23313
23488
  } finally {
23314
23489
  try {
23315
- const existing = JSON.parse(await readFile(ownerPath, "utf8"));
23490
+ const existing = JSON.parse(await readFile2(ownerPath, "utf8"));
23316
23491
  if (existing.lockId === lockId) {
23317
- await rm(lockPath, { recursive: true, force: true });
23492
+ await rm2(lockPath, { recursive: true, force: true });
23318
23493
  }
23319
23494
  } catch {
23320
23495
  }
@@ -23322,29 +23497,29 @@ async function withRuntimeFilesystemLock(lockPath, task, options = {}) {
23322
23497
  }
23323
23498
  function isManagedRuntimePostgresBinDir(binDir, homeDir) {
23324
23499
  const managedBinDir = process.env[RUDDER_DESKTOP_MANAGED_POSTGRES_BIN_DIR_ENV]?.trim();
23325
- if (managedBinDir && path10.resolve(managedBinDir) === path10.resolve(binDir)) return true;
23326
- const runtimesRelative = path10.relative(
23327
- path10.join(homeDir, "runtimes"),
23328
- path10.resolve(binDir)
23500
+ if (managedBinDir && path11.resolve(managedBinDir) === path11.resolve(binDir)) return true;
23501
+ const runtimesRelative = path11.relative(
23502
+ path11.join(homeDir, "runtimes"),
23503
+ path11.resolve(binDir)
23329
23504
  );
23330
- const runtimeSegments = runtimesRelative.split(path10.sep);
23331
- if (runtimesRelative !== "" && runtimesRelative !== ".." && !runtimesRelative.startsWith(`..${path10.sep}`) && !path10.isAbsolute(runtimesRelative) && runtimeSegments.length === 4 && runtimeSegments[0]?.length > 0 && runtimeSegments[1] === RUNTIME_POSTGRES_PAYLOAD_DIR && runtimeSegments[2] === `${process.platform}-${process.arch}` && runtimeSegments[3] === "bin") {
23505
+ const runtimeSegments = runtimesRelative.split(path11.sep);
23506
+ if (runtimesRelative !== "" && runtimesRelative !== ".." && !runtimesRelative.startsWith(`..${path11.sep}`) && !path11.isAbsolute(runtimesRelative) && runtimeSegments.length === 4 && runtimeSegments[0]?.length > 0 && runtimeSegments[1] === RUNTIME_POSTGRES_PAYLOAD_DIR && runtimeSegments[2] === `${process.platform}-${process.arch}` && runtimeSegments[3] === "bin") {
23332
23507
  return true;
23333
23508
  }
23334
- const payloadsRelative = path10.relative(
23335
- path10.join(homeDir, "runtime-payloads"),
23336
- path10.resolve(binDir)
23509
+ const payloadsRelative = path11.relative(
23510
+ path11.join(homeDir, "runtime-payloads"),
23511
+ path11.resolve(binDir)
23337
23512
  );
23338
- const payloadSegments = payloadsRelative.split(path10.sep);
23339
- return payloadsRelative !== "" && payloadsRelative !== ".." && !payloadsRelative.startsWith(`..${path10.sep}`) && !path10.isAbsolute(payloadsRelative) && payloadSegments.length === 3 && payloadSegments[0] === RUNTIME_POSTGRES_PAYLOAD_DIR && payloadSegments[1] === `${process.platform}-${process.arch}` && payloadSegments[2] === "bin";
23513
+ const payloadSegments = payloadsRelative.split(path11.sep);
23514
+ return payloadsRelative !== "" && payloadsRelative !== ".." && !payloadsRelative.startsWith(`..${path11.sep}`) && !path11.isAbsolute(payloadsRelative) && payloadSegments.length === 3 && payloadSegments[0] === RUNTIME_POSTGRES_PAYLOAD_DIR && payloadSegments[1] === `${process.platform}-${process.arch}` && payloadSegments[2] === "bin";
23340
23515
  }
23341
23516
  async function findLegacyRuntimePostgresBinDir(cacheDir, homeDir, postgresVersionProbe, deadline) {
23342
- const runtimesRoot = path10.join(homeDir, "runtimes");
23517
+ const runtimesRoot = path11.join(homeDir, "runtimes");
23343
23518
  const entries = await readdir(runtimesRoot, { withFileTypes: true }).catch(() => []);
23344
23519
  for (const entry of entries) {
23345
23520
  if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
23346
- const candidateCacheDir = path10.join(runtimesRoot, entry.name);
23347
- if (path10.resolve(candidateCacheDir) === path10.resolve(cacheDir)) continue;
23521
+ const candidateCacheDir = path11.join(runtimesRoot, entry.name);
23522
+ if (path11.resolve(candidateCacheDir) === path11.resolve(cacheDir)) continue;
23348
23523
  const candidateBinDir = resolveRuntimePostgresPayloadBinDir(candidateCacheDir);
23349
23524
  remainingRuntimeInstallMs(deadline, cacheDir, "find cached PostgreSQL runtime payload");
23350
23525
  if (await isRuntimePostgresPayloadUsable(cacheDir, candidateBinDir, postgresVersionProbe, deadline)) {
@@ -23354,13 +23529,13 @@ async function findLegacyRuntimePostgresBinDir(cacheDir, homeDir, postgresVersio
23354
23529
  return null;
23355
23530
  }
23356
23531
  async function readLiveRuntimeDescriptors(homeDir) {
23357
- const instancesRoot = path10.join(homeDir, "instances");
23532
+ const instancesRoot = path11.join(homeDir, "instances");
23358
23533
  const entries = await readdir(instancesRoot, { withFileTypes: true }).catch(() => []);
23359
23534
  const descriptors = [];
23360
23535
  for (const entry of entries) {
23361
23536
  if (!entry.isDirectory()) continue;
23362
23537
  try {
23363
- const raw = JSON.parse(await readFile(path10.join(instancesRoot, entry.name, "runtime", "server.json"), "utf8"));
23538
+ const raw = JSON.parse(await readFile2(path11.join(instancesRoot, entry.name, "runtime", "server.json"), "utf8"));
23364
23539
  if (typeof raw.pid !== "number" || !Number.isInteger(raw.pid) || !isPidRunning(raw.pid) || typeof raw.version !== "string") {
23365
23540
  continue;
23366
23541
  }
@@ -23378,13 +23553,13 @@ async function assertSharedPostgresPayloadNotLive(cacheDir, homeDir, sharedBinDi
23378
23553
  const sharedPhysicalBinDir = await realpath(sharedBinDir).catch(() => null);
23379
23554
  const mayReferenceSharedPayload = await Promise.all(liveDescriptors.map(async (descriptor) => {
23380
23555
  if (descriptor.postgresBinDir === void 0) return true;
23381
- if (path10.resolve(descriptor.postgresBinDir) === path10.resolve(sharedBinDir)) return true;
23556
+ if (path11.resolve(descriptor.postgresBinDir) === path11.resolve(sharedBinDir)) return true;
23382
23557
  const descriptorPhysicalBinDir = await realpath(descriptor.postgresBinDir).catch(() => null);
23383
- if (descriptorPhysicalBinDir && sharedPhysicalBinDir && path10.resolve(descriptorPhysicalBinDir) === path10.resolve(sharedPhysicalBinDir)) {
23558
+ if (descriptorPhysicalBinDir && sharedPhysicalBinDir && path11.resolve(descriptorPhysicalBinDir) === path11.resolve(sharedPhysicalBinDir)) {
23384
23559
  return true;
23385
23560
  }
23386
23561
  if (!descriptorPhysicalBinDir) {
23387
- return pathIsInside(descriptor.postgresBinDir, path10.join(homeDir, "runtimes")) || pathIsInside(descriptor.postgresBinDir, path10.join(homeDir, "runtime-payloads"));
23562
+ return pathIsInside(descriptor.postgresBinDir, path11.join(homeDir, "runtimes")) || pathIsInside(descriptor.postgresBinDir, path11.join(homeDir, "runtime-payloads"));
23388
23563
  }
23389
23564
  return false;
23390
23565
  }));
@@ -23399,7 +23574,7 @@ async function validateRuntimePostgresVersion(cacheDir, binDir, postgresVersionP
23399
23574
  await assertRuntimePostgresBinDirComplete(cacheDir, binDir, deadline);
23400
23575
  for (const binary of ["initdb", "pg_ctl", "postgres"]) {
23401
23576
  remainingRuntimeInstallMs(deadline, cacheDir, "validate PostgreSQL runtime version");
23402
- const binaryPath = path10.join(binDir, runtimePostgresExecutableName(binary));
23577
+ const binaryPath = path11.join(binDir, runtimePostgresExecutableName(binary));
23403
23578
  const result = postgresVersionProbe(binaryPath);
23404
23579
  if (!/\bPostgreSQL\)?\s+18\.4\b/i.test(result)) {
23405
23580
  throw new RuntimeInstallError(
@@ -23439,24 +23614,24 @@ async function findRuntimePostgresBinDir(rootDir, cacheDir, postgresVersionProbe
23439
23614
  if (await isRuntimePostgresPayloadUsable(cacheDir, current, postgresVersionProbe, deadline)) return current;
23440
23615
  const entries = await readdir(current, { withFileTypes: true }).catch(() => []);
23441
23616
  for (const entry of entries) {
23442
- if (entry.isDirectory()) queue.push(path10.join(current, entry.name));
23617
+ if (entry.isDirectory()) queue.push(path11.join(current, entry.name));
23443
23618
  }
23444
23619
  }
23445
23620
  return null;
23446
23621
  }
23447
23622
  async function reconcileSharedPostgresPayloadGenerations(cacheDir, sharedPlatformRoot, postgresVersionProbe, cleanupDownloads = false, deadline) {
23448
23623
  remainingRuntimeInstallMs(deadline, cacheDir, "reconcile shared PostgreSQL payload");
23449
- const parentDir = path10.dirname(sharedPlatformRoot);
23450
- const baseName = path10.basename(sharedPlatformRoot);
23624
+ const parentDir = path11.dirname(sharedPlatformRoot);
23625
+ const baseName = path11.basename(sharedPlatformRoot);
23451
23626
  const entries = await readdir(parentDir, { withFileTypes: true }).catch(() => []);
23452
- const temporaryRoots = entries.filter((entry) => entry.name.startsWith(`${baseName}.tmp-`)).map((entry) => path10.join(parentDir, entry.name));
23453
- const previousRoots = entries.filter((entry) => entry.name.startsWith(`${baseName}.previous-`)).map((entry) => path10.join(parentDir, entry.name)).sort().reverse();
23454
- const downloadsRoot = path10.join(
23455
- path10.dirname(path10.dirname(sharedPlatformRoot)),
23627
+ const temporaryRoots = entries.filter((entry) => entry.name.startsWith(`${baseName}.tmp-`)).map((entry) => path11.join(parentDir, entry.name));
23628
+ const previousRoots = entries.filter((entry) => entry.name.startsWith(`${baseName}.previous-`)).map((entry) => path11.join(parentDir, entry.name)).sort().reverse();
23629
+ const downloadsRoot = path11.join(
23630
+ path11.dirname(path11.dirname(sharedPlatformRoot)),
23456
23631
  ".downloads"
23457
23632
  );
23458
- const staleDownloadRoots = cleanupDownloads ? (await readdir(downloadsRoot, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.name.startsWith("postgres-18.4-")).map((entry) => path10.join(downloadsRoot, entry.name)) : [];
23459
- const canonicalBinDir = path10.join(sharedPlatformRoot, "bin");
23633
+ const staleDownloadRoots = cleanupDownloads ? (await readdir(downloadsRoot, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.name.startsWith("postgres-18.4-")).map((entry) => path11.join(downloadsRoot, entry.name)) : [];
23634
+ const canonicalBinDir = path11.join(sharedPlatformRoot, "bin");
23460
23635
  if (!await isRuntimePostgresPayloadUsable(
23461
23636
  cacheDir,
23462
23637
  canonicalBinDir,
@@ -23466,28 +23641,28 @@ async function reconcileSharedPostgresPayloadGenerations(cacheDir, sharedPlatfor
23466
23641
  for (const previousRoot of previousRoots) {
23467
23642
  if (!await isRuntimePostgresPayloadUsable(
23468
23643
  cacheDir,
23469
- path10.join(previousRoot, "bin"),
23644
+ path11.join(previousRoot, "bin"),
23470
23645
  postgresVersionProbe,
23471
23646
  deadline
23472
23647
  )) {
23473
23648
  continue;
23474
23649
  }
23475
- await rm(sharedPlatformRoot, { recursive: true, force: true });
23650
+ await rm2(sharedPlatformRoot, { recursive: true, force: true });
23476
23651
  await rename(previousRoot, sharedPlatformRoot);
23477
23652
  break;
23478
23653
  }
23479
23654
  }
23480
23655
  await Promise.all([
23481
- ...temporaryRoots.map((candidate) => rm(candidate, { recursive: true, force: true })),
23482
- ...previousRoots.map((candidate) => rm(candidate, { recursive: true, force: true })),
23483
- ...staleDownloadRoots.map((candidate) => rm(candidate, { recursive: true, force: true }))
23656
+ ...temporaryRoots.map((candidate) => rm2(candidate, { recursive: true, force: true })),
23657
+ ...previousRoots.map((candidate) => rm2(candidate, { recursive: true, force: true })),
23658
+ ...staleDownloadRoots.map((candidate) => rm2(candidate, { recursive: true, force: true }))
23484
23659
  ]);
23485
23660
  }
23486
23661
  async function installSharedRuntimePostgresPayload(cacheDir, homeDir, sourceBinDir, postgresVersionProbe, deadline) {
23487
23662
  const sharedBinDir = resolveSharedRuntimePostgresPayloadBinDir(homeDir);
23488
- const sharedRuntimeDir = path10.dirname(sharedBinDir);
23663
+ const sharedRuntimeDir = path11.dirname(sharedBinDir);
23489
23664
  const sharedPlatformRoot = sharedRuntimeDir;
23490
- const sourceRuntimeDir = path10.dirname(sourceBinDir);
23665
+ const sourceRuntimeDir = path11.dirname(sourceBinDir);
23491
23666
  const sourceTemplateDir = await resolveRuntimePostgresTemplateDir(sourceBinDir, cacheDir, deadline);
23492
23667
  if (!sourceTemplateDir) {
23493
23668
  throw new RuntimeInstallError(
@@ -23508,13 +23683,13 @@ async function installSharedRuntimePostgresPayload(cacheDir, homeDir, sourceBinD
23508
23683
  return sharedBinDir;
23509
23684
  }
23510
23685
  await assertSharedPostgresPayloadNotLive(cacheDir, homeDir, sharedBinDir);
23511
- await mkdir(path10.dirname(sharedPlatformRoot), { recursive: true });
23686
+ await mkdir2(path11.dirname(sharedPlatformRoot), { recursive: true });
23512
23687
  const temporaryPlatformRoot = `${sharedPlatformRoot}.tmp-${process.pid}-${Date.now()}`;
23513
23688
  const previousPlatformRoot = `${sharedPlatformRoot}.previous-${process.pid}-${Date.now()}`;
23514
23689
  let previousMoved = false;
23515
23690
  let published = false;
23516
- await rm(temporaryPlatformRoot, { recursive: true, force: true });
23517
- await rm(previousPlatformRoot, { recursive: true, force: true });
23691
+ await rm2(temporaryPlatformRoot, { recursive: true, force: true });
23692
+ await rm2(previousPlatformRoot, { recursive: true, force: true });
23518
23693
  try {
23519
23694
  const temporaryRuntimeDir = temporaryPlatformRoot;
23520
23695
  const sourceShareDir = resolveRuntimePostgresShareDir(sourceBinDir, sourceTemplateDir);
@@ -23525,7 +23700,7 @@ async function installSharedRuntimePostgresPayload(cacheDir, homeDir, sourceBinD
23525
23700
  cacheDir,
23526
23701
  deadline
23527
23702
  );
23528
- const temporaryBinDir = path10.join(temporaryRuntimeDir, "bin");
23703
+ const temporaryBinDir = path11.join(temporaryRuntimeDir, "bin");
23529
23704
  await validateRuntimePostgresVersion(cacheDir, temporaryBinDir, postgresVersionProbe, deadline);
23530
23705
  try {
23531
23706
  await rename(sharedPlatformRoot, previousPlatformRoot);
@@ -23544,13 +23719,13 @@ async function installSharedRuntimePostgresPayload(cacheDir, homeDir, sourceBinD
23544
23719
  throw error;
23545
23720
  }
23546
23721
  if (previousMoved) {
23547
- await rm(previousPlatformRoot, { recursive: true, force: true });
23722
+ await rm2(previousPlatformRoot, { recursive: true, force: true });
23548
23723
  previousMoved = false;
23549
23724
  }
23550
23725
  } finally {
23551
- await rm(temporaryPlatformRoot, { recursive: true, force: true });
23726
+ await rm2(temporaryPlatformRoot, { recursive: true, force: true });
23552
23727
  if (published || !previousMoved) {
23553
- await rm(previousPlatformRoot, { recursive: true, force: true });
23728
+ await rm2(previousPlatformRoot, { recursive: true, force: true });
23554
23729
  }
23555
23730
  }
23556
23731
  return sharedBinDir;
@@ -23561,17 +23736,17 @@ async function downloadSharedRuntimePostgresPayload(cacheDir, homeDir, postgresV
23561
23736
  const archiveUrl = archiveSource?.url ?? null;
23562
23737
  if (!archiveUrl) return null;
23563
23738
  const sharedBinDir = resolveSharedRuntimePostgresPayloadBinDir(homeDir);
23564
- const sharedPlatformRoot = path10.dirname(sharedBinDir);
23739
+ const sharedPlatformRoot = path11.dirname(sharedBinDir);
23565
23740
  const downloadLockPath = `${sharedPlatformRoot}.download.lock`;
23566
23741
  return withRuntimeFilesystemLock(downloadLockPath, async () => {
23567
23742
  if (await isRuntimePostgresPayloadUsable(cacheDir, sharedBinDir, postgresVersionProbe, deadline)) {
23568
23743
  return sharedBinDir;
23569
23744
  }
23570
- const workRoot = path10.join(homeDir, "runtime-payloads", ".downloads");
23571
- await mkdir(workRoot, { recursive: true });
23572
- const workDir = await mkdtemp(path10.join(workRoot, "postgres-18.4-"));
23573
- const archivePath = path10.join(workDir, "postgresql-18.4.zip");
23574
- const extractDir = path10.join(workDir, "extract");
23745
+ const workRoot = path11.join(homeDir, "runtime-payloads", ".downloads");
23746
+ await mkdir2(workRoot, { recursive: true });
23747
+ const workDir = await mkdtemp(path11.join(workRoot, "postgres-18.4-"));
23748
+ const archivePath = path11.join(workDir, "postgresql-18.4.zip");
23749
+ const extractDir = path11.join(workDir, "extract");
23575
23750
  try {
23576
23751
  await downloadRuntimePostgresArchive(
23577
23752
  archiveUrl,
@@ -23582,7 +23757,7 @@ async function downloadSharedRuntimePostgresPayload(cacheDir, homeDir, postgresV
23582
23757
  const configuredMaxBytes = Number.parseInt(process.env[RUDDER_POSTGRES_RUNTIME_ARCHIVE_MAX_BYTES_ENV2] ?? "", 10);
23583
23758
  const maxArchiveBytes = Number.isSafeInteger(configuredMaxBytes) && configuredMaxBytes > 0 ? configuredMaxBytes : DEFAULT_RUNTIME_POSTGRES_ARCHIVE_MAX_BYTES2;
23584
23759
  const nativePublishStaging = `${sharedPlatformRoot}.tmp-native-${process.pid}-${Date.now()}`;
23585
- await mkdir(path10.dirname(sharedPlatformRoot), { recursive: true });
23760
+ await mkdir2(path11.dirname(sharedPlatformRoot), { recursive: true });
23586
23761
  const nativeInstall = await tryInstallNativePayload({
23587
23762
  archivePath,
23588
23763
  extractPath: extractDir,
@@ -23614,22 +23789,22 @@ async function downloadSharedRuntimePostgresPayload(cacheDir, homeDir, postgresV
23614
23789
  );
23615
23790
  }
23616
23791
  await copyRuntimePostgresPayloadWithinDeadline(
23617
- path10.dirname(extractedBinDir2),
23792
+ path11.dirname(extractedBinDir2),
23618
23793
  publishStagingPath,
23619
23794
  resolveRuntimePostgresShareDir(extractedBinDir2, templateDir),
23620
23795
  cacheDir,
23621
23796
  deadline,
23622
23797
  context.signal
23623
23798
  );
23624
- return path10.relative(
23799
+ return path11.relative(
23625
23800
  publishStagingPath,
23626
- path10.join(publishStagingPath, "bin", runtimePostgresExecutableName("postgres"))
23801
+ path11.join(publishStagingPath, "bin", runtimePostgresExecutableName("postgres"))
23627
23802
  );
23628
23803
  },
23629
23804
  validatePublished: async (destinationPath) => {
23630
23805
  await validateRuntimePostgresVersion(
23631
23806
  cacheDir,
23632
- path10.join(destinationPath, "bin"),
23807
+ path11.join(destinationPath, "bin"),
23633
23808
  postgresVersionProbe,
23634
23809
  deadline
23635
23810
  );
@@ -23638,7 +23813,7 @@ async function downloadSharedRuntimePostgresPayload(cacheDir, homeDir, postgresV
23638
23813
  if (nativeInstall.installed) {
23639
23814
  return sharedBinDir;
23640
23815
  }
23641
- await mkdir(extractDir, { recursive: true });
23816
+ await mkdir2(extractDir, { recursive: true });
23642
23817
  extractRuntimePostgresArchive(archivePath, extractDir, cacheDir, deadline);
23643
23818
  const extractedBinDir = await findRuntimePostgresBinDir(
23644
23819
  extractDir,
@@ -23660,27 +23835,27 @@ async function downloadSharedRuntimePostgresPayload(cacheDir, homeDir, postgresV
23660
23835
  deadline
23661
23836
  );
23662
23837
  } finally {
23663
- const cleanup = cleanupWorkDir ?? ((candidate) => rm(candidate, { recursive: true, force: true }));
23838
+ const cleanup = cleanupWorkDir ?? ((candidate) => rm2(candidate, { recursive: true, force: true }));
23664
23839
  void cleanup(workDir).catch(() => {
23665
23840
  });
23666
23841
  }
23667
23842
  }, { deadline, cacheDir, command: "acquire shared PostgreSQL download lock" });
23668
23843
  }
23669
23844
  async function ensureRuntimePostgresCompatibilityLink(cacheDir, homeDir, packageVersion) {
23670
- const compatibilityRoot = path10.join(cacheDir, RUNTIME_POSTGRES_PAYLOAD_DIR);
23671
- const sharedPayloadRoot = path10.join(homeDir, "runtime-payloads", RUNTIME_POSTGRES_PAYLOAD_DIR);
23845
+ const compatibilityRoot = path11.join(cacheDir, RUNTIME_POSTGRES_PAYLOAD_DIR);
23846
+ const sharedPayloadRoot = path11.join(homeDir, "runtime-payloads", RUNTIME_POSTGRES_PAYLOAD_DIR);
23672
23847
  const runtimeMetadata = await readRuntimeInstallMetadata(cacheDir);
23673
23848
  const liveDescriptors = await readLiveRuntimeDescriptors(homeDir);
23674
23849
  const compatibilityBinDir = resolveRuntimePostgresPayloadBinDir(cacheDir);
23675
23850
  const isProtected = liveDescriptors.some((descriptor) => descriptor.postgresBinDir && pathIsInside(descriptor.postgresBinDir, compatibilityRoot) || !descriptor.postgresBinDir && descriptor.version === (runtimeMetadata?.packageVersion ?? packageVersion));
23676
23851
  if (isProtected) return;
23677
- await mkdir(path10.dirname(compatibilityRoot), { recursive: true });
23852
+ await mkdir2(path11.dirname(compatibilityRoot), { recursive: true });
23678
23853
  const temporaryRoot = `${compatibilityRoot}.next-${process.pid}-${Date.now()}`;
23679
23854
  const previousRoot = `${compatibilityRoot}.previous-${process.pid}-${Date.now()}`;
23680
- await rm(temporaryRoot, { recursive: true, force: true });
23681
- await rm(previousRoot, { recursive: true, force: true });
23855
+ await rm2(temporaryRoot, { recursive: true, force: true });
23856
+ await rm2(previousRoot, { recursive: true, force: true });
23682
23857
  await symlink(
23683
- process.platform === "win32" ? sharedPayloadRoot : path10.relative(path10.dirname(compatibilityRoot), sharedPayloadRoot),
23858
+ process.platform === "win32" ? sharedPayloadRoot : path11.relative(path11.dirname(compatibilityRoot), sharedPayloadRoot),
23684
23859
  temporaryRoot,
23685
23860
  process.platform === "win32" ? "junction" : "dir"
23686
23861
  );
@@ -23702,18 +23877,18 @@ async function ensureRuntimePostgresCompatibilityLink(cacheDir, homeDir, package
23702
23877
  throw error;
23703
23878
  }
23704
23879
  if (previousMoved) {
23705
- await rm(previousRoot, { recursive: true, force: true });
23880
+ await rm2(previousRoot, { recursive: true, force: true });
23706
23881
  previousMoved = false;
23707
23882
  }
23708
23883
  } finally {
23709
- await rm(temporaryRoot, { recursive: true, force: true });
23710
- if (!previousMoved) await rm(previousRoot, { recursive: true, force: true });
23884
+ await rm2(temporaryRoot, { recursive: true, force: true });
23885
+ if (!previousMoved) await rm2(previousRoot, { recursive: true, force: true });
23711
23886
  }
23712
23887
  }
23713
23888
  async function stageRuntimePostgresPayload(cacheDir, homeDir, packageVersion, enabled, postgresVersionProbe, deadline, cleanupDownloadWorkDir) {
23714
23889
  if (!enabled) return { output: "" };
23715
23890
  const explicitSourceBinDir = process.env[RUDDER_POSTGRES_BIN_DIR_ENV]?.trim();
23716
- const resolvedExplicitSourceBinDir = explicitSourceBinDir ? path10.resolve(explicitSourceBinDir) : null;
23891
+ const resolvedExplicitSourceBinDir = explicitSourceBinDir ? path11.resolve(explicitSourceBinDir) : null;
23717
23892
  if (resolvedExplicitSourceBinDir && !isManagedRuntimePostgresBinDir(resolvedExplicitSourceBinDir, homeDir)) {
23718
23893
  await validateRuntimePostgresVersion(
23719
23894
  cacheDir,
@@ -23734,7 +23909,7 @@ async function stageRuntimePostgresPayload(cacheDir, homeDir, packageVersion, en
23734
23909
  };
23735
23910
  }
23736
23911
  const sharedBinDir = resolveSharedRuntimePostgresPayloadBinDir(homeDir);
23737
- const sharedPlatformRoot = path10.dirname(sharedBinDir);
23912
+ const sharedPlatformRoot = path11.dirname(sharedBinDir);
23738
23913
  await withRuntimeFilesystemLock(
23739
23914
  `${sharedPlatformRoot}.install.lock`,
23740
23915
  async () => reconcileSharedPostgresPayloadGenerations(
@@ -23825,7 +24000,7 @@ async function pruneRuntimeCache(options = {}) {
23825
24000
  const warnings = [];
23826
24001
  for (const entry of deletions) {
23827
24002
  try {
23828
- await rm(entry.cacheDir, { recursive: true, force: true });
24003
+ await rm2(entry.cacheDir, { recursive: true, force: true });
23829
24004
  deleted.push({
23830
24005
  cacheDir: entry.cacheDir,
23831
24006
  packageVersion: entry.packageVersion,
@@ -23846,13 +24021,13 @@ async function pruneRuntimeCache(options = {}) {
23846
24021
  };
23847
24022
  }
23848
24023
  async function scanRuntimeCacheEntries(homeDir) {
23849
- const runtimesDir = path10.join(homeDir, "runtimes");
24024
+ const runtimesDir = path11.join(homeDir, "runtimes");
23850
24025
  const dirents = await readdir(runtimesDir, { withFileTypes: true }).catch(() => null);
23851
24026
  if (!dirents) return [];
23852
24027
  const entries = [];
23853
24028
  for (const dirent of dirents) {
23854
24029
  if (!dirent.isDirectory()) continue;
23855
- const cacheDir = path10.join(runtimesDir, dirent.name);
24030
+ const cacheDir = path11.join(runtimesDir, dirent.name);
23856
24031
  const metadata = await readRuntimeInstallMetadata(cacheDir);
23857
24032
  if (!metadata) continue;
23858
24033
  const fallbackStat = await safeStat(cacheDir);
@@ -23885,7 +24060,7 @@ async function directorySizeBytes(targetPath) {
23885
24060
  if (!dirents) return 0;
23886
24061
  let total = 0;
23887
24062
  for (const dirent of dirents) {
23888
- const entryPath = path10.join(targetPath, dirent.name);
24063
+ const entryPath = path11.join(targetPath, dirent.name);
23889
24064
  if (dirent.isSymbolicLink()) continue;
23890
24065
  if (dirent.isDirectory()) {
23891
24066
  total += await directorySizeBytes(entryPath);
@@ -23897,15 +24072,15 @@ async function directorySizeBytes(targetPath) {
23897
24072
  return total;
23898
24073
  }
23899
24074
  async function readActiveRuntimeVersions(homeDir) {
23900
- const instancesDir = path10.join(homeDir, "instances");
24075
+ const instancesDir = path11.join(homeDir, "instances");
23901
24076
  const dirents = await readdir(instancesDir, { withFileTypes: true }).catch(() => null);
23902
24077
  if (!dirents) return [];
23903
24078
  const versions = /* @__PURE__ */ new Set();
23904
24079
  for (const dirent of dirents) {
23905
24080
  if (!dirent.isDirectory()) continue;
23906
24081
  try {
23907
- const descriptorPath = path10.join(instancesDir, dirent.name, "runtime", "server.json");
23908
- const parsed = JSON.parse(await readFile(descriptorPath, "utf8"));
24082
+ const descriptorPath = path11.join(instancesDir, dirent.name, "runtime", "server.json");
24083
+ const parsed = JSON.parse(await readFile2(descriptorPath, "utf8"));
23909
24084
  if (typeof parsed.version !== "string") continue;
23910
24085
  if (typeof parsed.pid === "number" && Number.isInteger(parsed.pid) && parsed.pid > 0 && isPidRunning(parsed.pid)) {
23911
24086
  versions.add(parsed.version);
@@ -24013,25 +24188,27 @@ function parseRuntimeVersion(version) {
24013
24188
  canaryNumber: canaryMatch ? Number(canaryMatch[1]) : null
24014
24189
  };
24015
24190
  }
24016
- var RUNTIME_NPM_PACKAGE_NAME, NPM_PUBLIC_REGISTRY_URL, RUNTIME_METADATA_FILE, RUNTIME_POSTGRES_PAYLOAD_DIR, DEFAULT_RUNTIME_CACHE_MAX_ENTRIES, DEFAULT_RUNTIME_CACHE_MAX_AGE_MS, DEFAULT_RUNTIME_CACHE_MAX_BYTES, DEFAULT_RUNTIME_CACHE_KEEP_PREVIOUS, RUNTIME_NPM_INSTALL_FLAGS, RUNTIME_NPM_PACK_FLAGS, EMBEDDED_POSTGRES_PACKAGE_NAME, RUDDER_DESKTOP_MANAGED_POSTGRES_BIN_DIR_ENV, RUDDER_POSTGRES_BIN_DIR_ENV, RUDDER_POSTGRES_RUNTIME_ARCHIVE_MAX_BYTES_ENV2, DEFAULT_RUNTIME_POSTGRES_ARCHIVE_MAX_BYTES2, RUNTIME_CACHE_PACKAGE_JSON, NPM_PLATFORM_REPAIR_ENV, RuntimeInstallError;
24191
+ var RUNTIME_NPM_PACKAGE_NAME, NPM_PUBLIC_REGISTRY_URL2, RUNTIME_METADATA_FILE, RUNTIME_POSTGRES_PAYLOAD_DIR, DEFAULT_RUNTIME_CACHE_MAX_ENTRIES, DEFAULT_RUNTIME_CACHE_MAX_AGE_MS, DEFAULT_RUNTIME_CACHE_MAX_BYTES, DEFAULT_RUNTIME_CACHE_KEEP_PREVIOUS, RUNTIME_NPM_INSTALL_BASE_FLAGS, RUNTIME_NPM_INSTALL_OPTIONAL_FLAGS, RUNTIME_NPM_INSTALL_SUFFIX_FLAGS, EMBEDDED_POSTGRES_PACKAGE_NAME, RUDDER_DESKTOP_MANAGED_POSTGRES_BIN_DIR_ENV, RUDDER_POSTGRES_BIN_DIR_ENV, RUDDER_POSTGRES_RUNTIME_ARCHIVE_MAX_BYTES_ENV2, DEFAULT_RUNTIME_POSTGRES_ARCHIVE_MAX_BYTES2, RUNTIME_CACHE_PACKAGE_JSON, RuntimeInstallError;
24017
24192
  var init_install = __esm({
24018
24193
  "src/runtime/install.ts"() {
24019
24194
  "use strict";
24020
24195
  init_home();
24021
24196
  init_npm_command();
24022
24197
  init_native_payload();
24198
+ init_platform_dependencies();
24023
24199
  init_postgres_runtime_download();
24024
24200
  init_postgres_runtime_source();
24025
24201
  RUNTIME_NPM_PACKAGE_NAME = "@rudderhq/server";
24026
- NPM_PUBLIC_REGISTRY_URL = "https://registry.npmjs.org";
24202
+ NPM_PUBLIC_REGISTRY_URL2 = "https://registry.npmjs.org";
24027
24203
  RUNTIME_METADATA_FILE = "runtime.json";
24028
24204
  RUNTIME_POSTGRES_PAYLOAD_DIR = "postgres-18.4";
24029
24205
  DEFAULT_RUNTIME_CACHE_MAX_ENTRIES = 2;
24030
24206
  DEFAULT_RUNTIME_CACHE_MAX_AGE_MS = 14 * 24 * 60 * 60 * 1e3;
24031
24207
  DEFAULT_RUNTIME_CACHE_MAX_BYTES = 2 * 1024 * 1024 * 1024;
24032
24208
  DEFAULT_RUNTIME_CACHE_KEEP_PREVIOUS = 0;
24033
- RUNTIME_NPM_INSTALL_FLAGS = ["--omit=dev", "--include=optional", "--no-audit", "--no-fund"];
24034
- RUNTIME_NPM_PACK_FLAGS = ["--registry", NPM_PUBLIC_REGISTRY_URL, "--silent"];
24209
+ RUNTIME_NPM_INSTALL_BASE_FLAGS = ["--omit=dev"];
24210
+ RUNTIME_NPM_INSTALL_OPTIONAL_FLAGS = ["--include=optional"];
24211
+ RUNTIME_NPM_INSTALL_SUFFIX_FLAGS = ["--no-audit", "--no-fund"];
24035
24212
  EMBEDDED_POSTGRES_PACKAGE_NAME = "embedded-postgres";
24036
24213
  RUDDER_DESKTOP_MANAGED_POSTGRES_BIN_DIR_ENV = "RUDDER_DESKTOP_MANAGED_POSTGRES_BIN_DIR";
24037
24214
  RUDDER_POSTGRES_BIN_DIR_ENV = "RUDDER_POSTGRES_BIN_DIR";
@@ -24043,11 +24220,6 @@ var init_install = __esm({
24043
24220
  private: true,
24044
24221
  type: "module"
24045
24222
  };
24046
- NPM_PLATFORM_REPAIR_ENV = {
24047
- npm_config_registry: NPM_PUBLIC_REGISTRY_URL,
24048
- npm_config_update_notifier: "false",
24049
- NO_UPDATE_NOTIFIER: "1"
24050
- };
24051
24223
  RuntimeInstallError = class extends Error {
24052
24224
  cacheDir;
24053
24225
  command;
@@ -24065,7 +24237,7 @@ var init_install = __esm({
24065
24237
 
24066
24238
  // src/runtime/server-entry.ts
24067
24239
  import fs8 from "node:fs";
24068
- import path11 from "node:path";
24240
+ import path12 from "node:path";
24069
24241
  import { fileURLToPath as fileURLToPath5, pathToFileURL as pathToFileURL2 } from "node:url";
24070
24242
  function formatError(err) {
24071
24243
  if (err instanceof Error) {
@@ -24087,10 +24259,14 @@ function maybeEnableUiDevMiddleware(entrypoint) {
24087
24259
  }
24088
24260
  }
24089
24261
  function resolveDevServerEntry() {
24090
- const projectRoot = path11.resolve(path11.dirname(fileURLToPath5(import.meta.url)), "../../..");
24091
- return path11.resolve(projectRoot, "server/src/index.ts");
24262
+ const projectRoot = path12.resolve(path12.dirname(fileURLToPath5(import.meta.url)), "../../..");
24263
+ return path12.resolve(projectRoot, "server/src/index.ts");
24092
24264
  }
24093
24265
  async function loadServerRuntimeModule(options) {
24266
+ const runtimePackageDir = options.runtimePackageDir?.trim();
24267
+ if (runtimePackageDir) {
24268
+ return await importRuntimeServerModule(path12.resolve(runtimePackageDir));
24269
+ }
24094
24270
  const devEntry = resolveDevServerEntry();
24095
24271
  if (fs8.existsSync(devEntry)) {
24096
24272
  maybeEnableUiDevMiddleware(devEntry);
@@ -24113,20 +24289,20 @@ async function loadServerRuntimeModule(options) {
24113
24289
  async function startManagedServerFromRuntime(options) {
24114
24290
  try {
24115
24291
  const mod = await loadServerRuntimeModule(options);
24116
- return await startServerFromModule(mod);
24292
+ return await startServerFromModule(mod, options);
24117
24293
  } catch (err) {
24118
24294
  throw new Error(`Rudder server failed to start.
24119
24295
  ${formatError(err)}`);
24120
24296
  }
24121
24297
  }
24122
- async function startServerFromModule(mod) {
24298
+ async function startServerFromModule(mod, options = {}) {
24123
24299
  const startManagedLocalServer = mod.startManagedLocalServer;
24124
24300
  if (typeof startManagedLocalServer !== "function") {
24125
24301
  throw new Error("Rudder server runtime did not export startManagedLocalServer().");
24126
24302
  }
24127
24303
  return await startManagedLocalServer({
24128
24304
  ownerKind: "cli",
24129
- takeoverOnVersionMismatch: true
24305
+ takeoverOnVersionMismatch: options.takeoverOnVersionMismatch ?? true
24130
24306
  });
24131
24307
  }
24132
24308
  var RUDDER_POSTGRES_BIN_DIR_ENV2;
@@ -24226,23 +24402,85 @@ var init_auth_bootstrap_ceo = __esm({
24226
24402
  }
24227
24403
  });
24228
24404
 
24405
+ // src/config/local-env.ts
24406
+ function parseLocalEnvName(value) {
24407
+ if (!value) return null;
24408
+ const normalized = value.trim().toLowerCase().replace(/-/g, "_");
24409
+ return LOCAL_ENV_NAMES.includes(normalized) ? normalized : null;
24410
+ }
24411
+ function resolveLocalEnvProfile(value) {
24412
+ const name = parseLocalEnvName(value);
24413
+ return name ? LOCAL_ENV_PROFILES[name] : null;
24414
+ }
24415
+ function resolveActiveLocalEnvProfile() {
24416
+ return resolveLocalEnvProfile(process.env.RUDDER_LOCAL_ENV);
24417
+ }
24418
+ function applyLocalEnvProfile(input) {
24419
+ const profile = resolveLocalEnvProfile(input.localEnv ?? process.env.RUDDER_LOCAL_ENV);
24420
+ if (!profile) return null;
24421
+ process.env.RUDDER_LOCAL_ENV = profile.name;
24422
+ if (!input.instance?.trim()) {
24423
+ process.env.RUDDER_INSTANCE_ID = profile.instanceId;
24424
+ }
24425
+ if (!process.env.PORT?.trim()) {
24426
+ process.env.PORT = String(profile.port);
24427
+ }
24428
+ if (!process.env.RUDDER_EMBEDDED_POSTGRES_PORT?.trim()) {
24429
+ process.env.RUDDER_EMBEDDED_POSTGRES_PORT = String(profile.embeddedPostgresPort);
24430
+ }
24431
+ return profile;
24432
+ }
24433
+ var LOCAL_ENV_NAMES, LOCAL_ENV_PROFILES;
24434
+ var init_local_env = __esm({
24435
+ "src/config/local-env.ts"() {
24436
+ "use strict";
24437
+ LOCAL_ENV_NAMES = ["dev", "prod_local", "e2e"];
24438
+ LOCAL_ENV_PROFILES = {
24439
+ dev: {
24440
+ name: "dev",
24441
+ instanceId: "dev",
24442
+ port: 3100,
24443
+ embeddedPostgresPort: 54329,
24444
+ resettable: true,
24445
+ description: "Disposable local development instance"
24446
+ },
24447
+ prod_local: {
24448
+ name: "prod_local",
24449
+ instanceId: "default",
24450
+ port: 3200,
24451
+ embeddedPostgresPort: 54339,
24452
+ resettable: false,
24453
+ description: "Persistent local instance"
24454
+ },
24455
+ e2e: {
24456
+ name: "e2e",
24457
+ instanceId: "e2e",
24458
+ port: 3300,
24459
+ embeddedPostgresPort: 54349,
24460
+ resettable: true,
24461
+ description: "Isolated end-to-end test instance"
24462
+ }
24463
+ };
24464
+ }
24465
+ });
24466
+
24229
24467
  // src/utils/path-resolver.ts
24230
24468
  import fs11 from "node:fs";
24231
- import path19 from "node:path";
24469
+ import path22 from "node:path";
24232
24470
  function unique(items) {
24233
24471
  return Array.from(new Set(items));
24234
24472
  }
24235
24473
  function resolveRuntimeLikePath(value, configPath) {
24236
24474
  const expanded = expandHomePrefix(value);
24237
- if (path19.isAbsolute(expanded)) return path19.resolve(expanded);
24475
+ if (path22.isAbsolute(expanded)) return path22.resolve(expanded);
24238
24476
  const cwd = process.cwd();
24239
- const configDir = configPath ? path19.dirname(configPath) : null;
24240
- const workspaceRoot = configDir ? path19.resolve(configDir, "..") : cwd;
24477
+ const configDir = configPath ? path22.dirname(configPath) : null;
24478
+ const workspaceRoot = configDir ? path22.resolve(configDir, "..") : cwd;
24241
24479
  const candidates = unique([
24242
- ...configDir ? [path19.resolve(configDir, expanded)] : [],
24243
- path19.resolve(workspaceRoot, "server", expanded),
24244
- path19.resolve(workspaceRoot, expanded),
24245
- path19.resolve(cwd, expanded)
24480
+ ...configDir ? [path22.resolve(configDir, expanded)] : [],
24481
+ path22.resolve(workspaceRoot, "server", expanded),
24482
+ path22.resolve(workspaceRoot, expanded),
24483
+ path22.resolve(cwd, expanded)
24246
24484
  ]);
24247
24485
  return candidates.find((candidate) => fs11.existsSync(candidate)) ?? candidates[0];
24248
24486
  }
@@ -24256,7 +24494,7 @@ var init_path_resolver = __esm({
24256
24494
  // src/config/secrets-key.ts
24257
24495
  import { randomBytes as randomBytes2 } from "node:crypto";
24258
24496
  import fs12 from "node:fs";
24259
- import path20 from "node:path";
24497
+ import path23 from "node:path";
24260
24498
  function ensureLocalSecretsKeyFile(config, configPath) {
24261
24499
  if (config.secrets.provider !== "local_encrypted") {
24262
24500
  return { status: "skipped_provider", path: null };
@@ -24271,7 +24509,7 @@ function ensureLocalSecretsKeyFile(config, configPath) {
24271
24509
  if (fs12.existsSync(keyFilePath)) {
24272
24510
  return { status: "existing", path: keyFilePath };
24273
24511
  }
24274
- fs12.mkdirSync(path20.dirname(keyFilePath), { recursive: true });
24512
+ fs12.mkdirSync(path23.dirname(keyFilePath), { recursive: true });
24275
24513
  fs12.writeFileSync(keyFilePath, randomBytes2(32).toString("base64"), {
24276
24514
  encoding: "utf8",
24277
24515
  mode: 384
@@ -25357,7 +25595,7 @@ var init_port_check = __esm({
25357
25595
  // src/checks/secrets-check.ts
25358
25596
  import { randomBytes as randomBytes3 } from "node:crypto";
25359
25597
  import fs15 from "node:fs";
25360
- import path21 from "node:path";
25598
+ import path24 from "node:path";
25361
25599
  function decodeMasterKey(raw) {
25362
25600
  const trimmed = raw.trim();
25363
25601
  if (!trimmed) return null;
@@ -25427,7 +25665,7 @@ function secretsCheck(config, configPath) {
25427
25665
  message: `Secrets key file does not exist yet: ${keyFilePath}`,
25428
25666
  canRepair: true,
25429
25667
  repair: () => {
25430
- fs15.mkdirSync(path21.dirname(keyFilePath), { recursive: true });
25668
+ fs15.mkdirSync(path24.dirname(keyFilePath), { recursive: true });
25431
25669
  fs15.writeFileSync(keyFilePath, randomBytes3(32).toString("base64"), {
25432
25670
  encoding: "utf8",
25433
25671
  mode: 384
@@ -25697,7 +25935,8 @@ var init_doctor = __esm({
25697
25935
  });
25698
25936
 
25699
25937
  // src/install.ts
25700
- import { execFileSync as execFileSync2, spawnSync as spawnSync3 } from "node:child_process";
25938
+ import { execFileSync as execFileSync2, spawnSync as spawnSync4 } from "node:child_process";
25939
+ import path25 from "node:path";
25701
25940
  function normalizePath(value) {
25702
25941
  return (value ?? "").replaceAll("\\", "/").toLowerCase();
25703
25942
  }
@@ -25746,6 +25985,26 @@ function getGlobalInstalledPackageVersion(packageName, execFileSyncImpl = execFi
25746
25985
  return null;
25747
25986
  }
25748
25987
  }
25988
+ function resolveGlobalInstalledCliEntry(execFileSyncImpl = execFileSync2) {
25989
+ let globalRoot;
25990
+ try {
25991
+ const npm = resolveNpmCommandInvocation();
25992
+ globalRoot = execFileSyncImpl(
25993
+ npm.command,
25994
+ [...npm.args, "root", "--global"],
25995
+ {
25996
+ encoding: "utf8",
25997
+ stdio: ["ignore", "pipe", "ignore"]
25998
+ }
25999
+ ).trim();
26000
+ } catch {
26001
+ throw new Error("Could not resolve the global npm package directory for the Rudder browser app.");
26002
+ }
26003
+ if (!globalRoot) {
26004
+ throw new Error("npm returned an empty global package directory for the Rudder browser app.");
26005
+ }
26006
+ return path25.join(globalRoot, "@rudderhq", "cli", "dist", "index.js");
26007
+ }
25749
26008
  function hasPersistentBinaryOnPath(execFileSyncImpl = execFileSync2) {
25750
26009
  const { command, args } = resolveCommandLookupExecutable();
25751
26010
  try {
@@ -25781,10 +26040,10 @@ function detectPersistentCliState(options = {}) {
25781
26040
  };
25782
26041
  }
25783
26042
  function installPersistentCli(options) {
25784
- const spawnSyncImpl = options.spawnSyncImpl ?? spawnSync3;
26043
+ const spawnSyncImpl = options.spawnSyncImpl ?? spawnSync4;
25785
26044
  const command = `npm install --global ${options.installSpec}`;
25786
26045
  const initialResult = runNpmGlobalInstall(spawnSyncImpl, ["install", "--global", options.installSpec]);
25787
- const initialOutput = collectSpawnOutput2(initialResult);
26046
+ const initialOutput = collectSpawnOutput3(initialResult);
25788
26047
  if (initialResult.status === 0 || !isRudderBinConflict(initialOutput)) {
25789
26048
  return {
25790
26049
  ok: initialResult.status === 0,
@@ -25794,7 +26053,7 @@ function installPersistentCli(options) {
25794
26053
  }
25795
26054
  const forcedCommand = `npm install --global --force ${options.installSpec}`;
25796
26055
  const forcedResult = runNpmGlobalInstall(spawnSyncImpl, ["install", "--global", "--force", options.installSpec]);
25797
- const forcedOutput = collectSpawnOutput2(forcedResult);
26056
+ const forcedOutput = collectSpawnOutput3(forcedResult);
25798
26057
  return {
25799
26058
  ok: forcedResult.status === 0,
25800
26059
  command: forcedCommand,
@@ -25806,85 +26065,23 @@ function runNpmGlobalInstall(spawnSyncImpl, args) {
25806
26065
  return spawnSyncImpl(npm.command, [...npm.args, ...args], {
25807
26066
  encoding: "utf8",
25808
26067
  stdio: ["inherit", "pipe", "pipe"],
25809
- ...process.platform === "win32" ? { windowsHide: true } : {}
25810
- });
25811
- }
25812
- function collectSpawnOutput2(result) {
25813
- return [result.stdout, result.stderr, result.error instanceof Error ? result.error.message : null].filter((value) => typeof value === "string" && value.trim().length > 0).join("\n").trim();
25814
- }
25815
- function isRudderBinConflict(output) {
25816
- const normalized = output.toLowerCase().replaceAll("\\", "/");
25817
- return normalized.includes("eexist") && (normalized.includes(`/${CLI_BIN_NAME}`) || normalized.includes(`/${CLI_BIN_NAME}.cmd`) || normalized.includes(`/${CLI_BIN_NAME}.ps1`));
25818
- }
25819
- var CLI_NPM_PACKAGE_NAME, CLI_BIN_NAME;
25820
- var init_install2 = __esm({
25821
- "src/install.ts"() {
25822
- "use strict";
25823
- init_npm_command();
25824
- CLI_NPM_PACKAGE_NAME = "@rudderhq/cli";
25825
- CLI_BIN_NAME = "rudder";
25826
- }
25827
- });
25828
-
25829
- // src/config/local-env.ts
25830
- function parseLocalEnvName(value) {
25831
- if (!value) return null;
25832
- const normalized = value.trim().toLowerCase().replace(/-/g, "_");
25833
- return LOCAL_ENV_NAMES.includes(normalized) ? normalized : null;
25834
- }
25835
- function resolveLocalEnvProfile(value) {
25836
- const name = parseLocalEnvName(value);
25837
- return name ? LOCAL_ENV_PROFILES[name] : null;
26068
+ ...process.platform === "win32" ? { windowsHide: true } : {}
26069
+ });
25838
26070
  }
25839
- function resolveActiveLocalEnvProfile() {
25840
- return resolveLocalEnvProfile(process.env.RUDDER_LOCAL_ENV);
26071
+ function collectSpawnOutput3(result) {
26072
+ return [result.stdout, result.stderr, result.error instanceof Error ? result.error.message : null].filter((value) => typeof value === "string" && value.trim().length > 0).join("\n").trim();
25841
26073
  }
25842
- function applyLocalEnvProfile(input) {
25843
- const profile = resolveLocalEnvProfile(input.localEnv ?? process.env.RUDDER_LOCAL_ENV);
25844
- if (!profile) return null;
25845
- process.env.RUDDER_LOCAL_ENV = profile.name;
25846
- if (!input.instance?.trim()) {
25847
- process.env.RUDDER_INSTANCE_ID = profile.instanceId;
25848
- }
25849
- if (!process.env.PORT?.trim()) {
25850
- process.env.PORT = String(profile.port);
25851
- }
25852
- if (!process.env.RUDDER_EMBEDDED_POSTGRES_PORT?.trim()) {
25853
- process.env.RUDDER_EMBEDDED_POSTGRES_PORT = String(profile.embeddedPostgresPort);
25854
- }
25855
- return profile;
26074
+ function isRudderBinConflict(output) {
26075
+ const normalized = output.toLowerCase().replaceAll("\\", "/");
26076
+ return normalized.includes("eexist") && (normalized.includes(`/${CLI_BIN_NAME}`) || normalized.includes(`/${CLI_BIN_NAME}.cmd`) || normalized.includes(`/${CLI_BIN_NAME}.ps1`));
25856
26077
  }
25857
- var LOCAL_ENV_NAMES, LOCAL_ENV_PROFILES;
25858
- var init_local_env = __esm({
25859
- "src/config/local-env.ts"() {
26078
+ var CLI_NPM_PACKAGE_NAME, CLI_BIN_NAME;
26079
+ var init_install2 = __esm({
26080
+ "src/install.ts"() {
25860
26081
  "use strict";
25861
- LOCAL_ENV_NAMES = ["dev", "prod_local", "e2e"];
25862
- LOCAL_ENV_PROFILES = {
25863
- dev: {
25864
- name: "dev",
25865
- instanceId: "dev",
25866
- port: 3100,
25867
- embeddedPostgresPort: 54329,
25868
- resettable: true,
25869
- description: "Disposable local development instance"
25870
- },
25871
- prod_local: {
25872
- name: "prod_local",
25873
- instanceId: "default",
25874
- port: 3200,
25875
- embeddedPostgresPort: 54339,
25876
- resettable: false,
25877
- description: "Persistent local instance"
25878
- },
25879
- e2e: {
25880
- name: "e2e",
25881
- instanceId: "e2e",
25882
- port: 3300,
25883
- embeddedPostgresPort: 54349,
25884
- resettable: true,
25885
- description: "Isolated end-to-end test instance"
25886
- }
25887
- };
26082
+ init_npm_command();
26083
+ CLI_NPM_PACKAGE_NAME = "@rudderhq/cli";
26084
+ CLI_BIN_NAME = "rudder";
25888
26085
  }
25889
26086
  });
25890
26087
 
@@ -26003,7 +26200,7 @@ var init_run = __esm({
26003
26200
 
26004
26201
  // src/commands/onboard.ts
26005
26202
  import * as p14 from "@clack/prompts";
26006
- import path22 from "node:path";
26203
+ import path26 from "node:path";
26007
26204
  import pc13 from "picocolors";
26008
26205
  function parseBooleanFromEnv(rawValue) {
26009
26206
  if (rawValue === void 0) return null;
@@ -26036,7 +26233,7 @@ function parseEnumFromEnv(rawValue, allowedValues) {
26036
26233
  }
26037
26234
  function resolvePathFromEnv(rawValue) {
26038
26235
  if (!rawValue || rawValue.trim().length === 0) return null;
26039
- return path22.resolve(expandHomePrefix(rawValue.trim()));
26236
+ return path26.resolve(expandHomePrefix(rawValue.trim()));
26040
26237
  }
26041
26238
  function quickstartDefaultsFromEnv() {
26042
26239
  const instanceId = resolveRudderInstanceId();
@@ -28823,42 +29020,42 @@ var RudderApiClient = class {
28823
29020
  now: opts.now
28824
29021
  });
28825
29022
  }
28826
- get(path26, opts) {
28827
- return this.request(path26, { method: "GET" }, opts);
29023
+ get(path29, opts) {
29024
+ return this.request(path29, { method: "GET" }, opts);
28828
29025
  }
28829
- post(path26, body, opts) {
28830
- return this.request(path26, {
29026
+ post(path29, body, opts) {
29027
+ return this.request(path29, {
28831
29028
  method: "POST",
28832
29029
  body: body === void 0 ? void 0 : JSON.stringify(body)
28833
29030
  }, opts);
28834
29031
  }
28835
- postForm(path26, form, opts) {
28836
- return this.request(path26, {
29032
+ postForm(path29, form, opts) {
29033
+ return this.request(path29, {
28837
29034
  method: "POST",
28838
29035
  body: form
28839
29036
  }, opts);
28840
29037
  }
28841
- patch(path26, body, opts) {
28842
- return this.request(path26, {
29038
+ patch(path29, body, opts) {
29039
+ return this.request(path29, {
28843
29040
  method: "PATCH",
28844
29041
  body: body === void 0 ? void 0 : JSON.stringify(body)
28845
29042
  }, opts);
28846
29043
  }
28847
- put(path26, body, opts) {
28848
- return this.request(path26, {
29044
+ put(path29, body, opts) {
29045
+ return this.request(path29, {
28849
29046
  method: "PUT",
28850
29047
  body: body === void 0 ? void 0 : JSON.stringify(body)
28851
29048
  }, opts);
28852
29049
  }
28853
- delete(path26, opts) {
28854
- return this.request(path26, { method: "DELETE" }, opts);
29050
+ delete(path29, opts) {
29051
+ return this.request(path29, { method: "DELETE" }, opts);
28855
29052
  }
28856
29053
  setApiKey(apiKey) {
28857
29054
  this.apiKey = apiKey?.trim() || void 0;
28858
29055
  }
28859
- async request(path26, init, opts, hasRetriedAuth = false) {
28860
- const url = buildUrl(this.apiBase, path26);
28861
- const reservation = await this.issueTransportBudget.reserve(init.method, path26, init.body);
29056
+ async request(path29, init, opts, hasRetriedAuth = false) {
29057
+ const url = buildUrl(this.apiBase, path29);
29058
+ const reservation = await this.issueTransportBudget.reserve(init.method, path29, init.body);
28862
29059
  const headers = {
28863
29060
  accept: "application/json",
28864
29061
  ...toStringRecord(init.headers)
@@ -28896,14 +29093,14 @@ var RudderApiClient = class {
28896
29093
  const apiError = await toApiError(response);
28897
29094
  if (!hasRetriedAuth && this.recoverAuth) {
28898
29095
  const recoveredToken = await this.recoverAuth({
28899
- path: path26,
29096
+ path: path29,
28900
29097
  method: String(init.method ?? "GET").toUpperCase(),
28901
29098
  error: apiError
28902
29099
  });
28903
29100
  if (recoveredToken) {
28904
29101
  await this.issueTransportBudget.succeed(reservation);
28905
29102
  this.setApiKey(recoveredToken);
28906
- return this.request(path26, init, opts, true);
29103
+ return this.request(path29, init, opts, true);
28907
29104
  }
28908
29105
  }
28909
29106
  await this.issueTransportBudget.fail(reservation, apiError);
@@ -28924,8 +29121,8 @@ function shouldAttachAgentContext(method) {
28924
29121
  const normalized = String(method ?? "GET").toUpperCase();
28925
29122
  return normalized !== "GET" && normalized !== "HEAD";
28926
29123
  }
28927
- function buildUrl(apiBase, path26) {
28928
- const normalizedPath = path26.startsWith("/") ? path26 : `/${path26}`;
29124
+ function buildUrl(apiBase, path29) {
29125
+ const normalizedPath = path29.startsWith("/") ? path29 : `/${path29}`;
28929
29126
  const [pathname, query] = normalizedPath.split("?");
28930
29127
  const url = new URL3(apiBase);
28931
29128
  url.pathname = `${url.pathname.replace(/\/+$/, "")}${pathname}`;
@@ -31510,67 +31707,586 @@ function hasRunnableRudderOnPath(env) {
31510
31707
  function rpcResult(id, result) {
31511
31708
  return { jsonrpc: "2.0", id, result };
31512
31709
  }
31513
- function rpcError(id, code, message, data) {
31514
- return { jsonrpc: "2.0", id, error: { code, message, ...data === void 0 ? {} : { data } } };
31710
+ function rpcError(id, code, message, data) {
31711
+ return { jsonrpc: "2.0", id, error: { code, message, ...data === void 0 ? {} : { data } } };
31712
+ }
31713
+ function errorMessage(err) {
31714
+ return err instanceof Error ? err.message : String(err);
31715
+ }
31716
+ function errorDetails(err) {
31717
+ if (!(err instanceof Error)) return void 0;
31718
+ if (err instanceof ApiRequestError) {
31719
+ const details = isRecord3(err.details) ? err.details : err.details === void 0 ? {} : { upstreamDetails: err.details };
31720
+ return {
31721
+ code: err.code ?? "api_request_error",
31722
+ status: err.status,
31723
+ ...details
31724
+ };
31725
+ }
31726
+ const code = err.code;
31727
+ return code ? { code } : void 0;
31728
+ }
31729
+ function isRecord3(value) {
31730
+ return typeof value === "object" && value !== null && !Array.isArray(value);
31731
+ }
31732
+
31733
+ // src/commands/allowed-hostname.ts
31734
+ init_hostnames();
31735
+ init_store();
31736
+ import * as p from "@clack/prompts";
31737
+ import pc3 from "picocolors";
31738
+ async function addAllowedHostname(host, opts) {
31739
+ const configPath = resolveConfigPath(opts.config);
31740
+ const config = readConfig(opts.config);
31741
+ if (!config) {
31742
+ p.log.error(`No config found at ${configPath}. Run ${pc3.cyan("rudder onboard")} first.`);
31743
+ return;
31744
+ }
31745
+ const normalized = normalizeHostnameInput(host);
31746
+ const current = new Set((config.server.allowedHostnames ?? []).map((value) => value.trim().toLowerCase()).filter(Boolean));
31747
+ const existed = current.has(normalized);
31748
+ current.add(normalized);
31749
+ config.server.allowedHostnames = Array.from(current).sort();
31750
+ config.$meta.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
31751
+ config.$meta.source = "configure";
31752
+ writeConfig(config, opts.config);
31753
+ if (existed) {
31754
+ p.log.info(`Hostname ${pc3.cyan(normalized)} is already allowed.`);
31755
+ } else {
31756
+ p.log.success(`Added allowed hostname: ${pc3.cyan(normalized)}`);
31757
+ p.log.message(
31758
+ pc3.dim("Restart the Rudder server for this change to take effect.")
31759
+ );
31760
+ }
31761
+ if (!(config.server.deploymentMode === "authenticated" && config.server.exposure === "private")) {
31762
+ p.log.message(
31763
+ pc3.dim("Note: allowed hostnames are enforced only in authenticated/private mode.")
31764
+ );
31765
+ }
31766
+ }
31767
+
31768
+ // src/program.ts
31769
+ init_auth_bootstrap_ceo();
31770
+
31771
+ // src/commands/browser-app.ts
31772
+ import { spawn as spawn3, spawnSync as spawnSync3 } from "node:child_process";
31773
+ import { randomUUID as randomUUID2 } from "node:crypto";
31774
+ import { closeSync, existsSync as existsSync4, mkdirSync, openSync, readFileSync as readFileSync2, rmdirSync, statSync as statSync2, unlinkSync, writeFileSync } from "node:fs";
31775
+ import { readFile as readFile3, rm as rm3, writeFile as writeFile2 } from "node:fs/promises";
31776
+ import { homedir, tmpdir } from "node:os";
31777
+ import path14 from "node:path";
31778
+ import { setTimeout as delay } from "node:timers/promises";
31779
+
31780
+ // src/config/data-dir.ts
31781
+ init_home();
31782
+ import path13 from "node:path";
31783
+ function applyDataDirOverride(options, support = {}) {
31784
+ const rawDataDir = options.dataDir?.trim();
31785
+ if (!rawDataDir) return null;
31786
+ const resolvedDataDir = path13.resolve(expandHomePrefix(rawDataDir));
31787
+ process.env.RUDDER_HOME = resolvedDataDir;
31788
+ if (support.hasConfigOption) {
31789
+ const hasConfigOverride = Boolean(options.config?.trim()) || Boolean(process.env.RUDDER_CONFIG?.trim());
31790
+ if (!hasConfigOverride) {
31791
+ const instanceId = resolveRudderInstanceId(options.instance);
31792
+ process.env.RUDDER_INSTANCE_ID = instanceId;
31793
+ process.env.RUDDER_CONFIG = resolveDefaultConfigPath(instanceId);
31794
+ }
31795
+ }
31796
+ if (support.hasContextOption) {
31797
+ const hasContextOverride = Boolean(options.context?.trim()) || Boolean(process.env.RUDDER_CONTEXT?.trim());
31798
+ if (!hasContextOverride) {
31799
+ process.env.RUDDER_CONTEXT = resolveDefaultContextPath();
31800
+ }
31801
+ }
31802
+ return resolvedDataDir;
31803
+ }
31804
+
31805
+ // src/commands/browser-app.ts
31806
+ init_home();
31807
+ init_local_env();
31808
+ init_server_entry();
31809
+ init_version();
31810
+ var SMART_APP_CONTROL_REGISTRY_KEY = String.raw`HKLM\SYSTEM\CurrentControlSet\Control\CI\Policy`;
31811
+ var SMART_APP_CONTROL_REGISTRY_VALUE = "VerifiedAndReputablePolicyState";
31812
+ var BROWSER_APP_READY_TIMEOUT_MS = 9e4;
31813
+ var RUNTIME_HEALTH_POLL_MS = 2e3;
31814
+ var DESKTOP_TAKEOVER_LEASE_DIR = "browser-app-desktop-takeover.lock";
31815
+ var DESKTOP_TAKEOVER_PARTIAL_LEASE_GRACE_MS = 3e4;
31816
+ function resolveBrowserAppRuntimeVersion(env = process.env) {
31817
+ const version = resolveCliVersion(import.meta.url, env);
31818
+ return version === "0.0.0" ? "latest" : version;
31819
+ }
31820
+ function parseSmartAppControlState(output) {
31821
+ const line = output.split(/\r?\n/).find((candidate) => candidate.toLowerCase().includes(SMART_APP_CONTROL_REGISTRY_VALUE.toLowerCase()));
31822
+ if (!line) return "unknown";
31823
+ const match = line.match(/REG_DWORD\s+0x([0-9a-f]+)/iu);
31824
+ if (!match) return "unknown";
31825
+ const value = Number.parseInt(match[1], 16);
31826
+ if (value === 0) return "off";
31827
+ if (value === 1) return "on";
31828
+ if (value === 2) return "evaluation";
31829
+ return "unknown";
31830
+ }
31831
+ function detectSmartAppControlState(platform = process.platform, spawnSyncImpl = spawnSync3) {
31832
+ if (platform !== "win32") return "unknown";
31833
+ const result = spawnSyncImpl("reg.exe", [
31834
+ "query",
31835
+ SMART_APP_CONTROL_REGISTRY_KEY,
31836
+ "/v",
31837
+ SMART_APP_CONTROL_REGISTRY_VALUE
31838
+ ], {
31839
+ encoding: "utf8",
31840
+ stdio: ["ignore", "pipe", "ignore"],
31841
+ windowsHide: true
31842
+ });
31843
+ if (result.status !== 0 || typeof result.stdout !== "string") return "unknown";
31844
+ return parseSmartAppControlState(result.stdout);
31845
+ }
31846
+ function parseDesktopLaunchMode(value) {
31847
+ const normalized = value?.trim().toLowerCase() || "auto";
31848
+ if (normalized === "auto" || normalized === "native" || normalized === "browser") return normalized;
31849
+ throw new Error(`Desktop mode must be auto, native, or browser. Received ${value}.`);
31850
+ }
31851
+ function resolveDesktopLaunchMode(options = {}) {
31852
+ const requested = parseDesktopLaunchMode(options.requested);
31853
+ if (requested !== "auto") return requested;
31854
+ const platform = options.platform ?? process.platform;
31855
+ const state = options.smartAppControlState ?? detectSmartAppControlState(platform);
31856
+ return platform === "win32" && state === "on" ? "browser" : "native";
31857
+ }
31858
+ function resolveEdgeExecutable(env = process.env, pathExists3 = existsSync4) {
31859
+ const candidates = [
31860
+ env["PROGRAMFILES(X86)"] && path14.join(env["PROGRAMFILES(X86)"], "Microsoft", "Edge", "Application", "msedge.exe"),
31861
+ env.ProgramFiles && path14.join(env.ProgramFiles, "Microsoft", "Edge", "Application", "msedge.exe"),
31862
+ env.LOCALAPPDATA && path14.join(env.LOCALAPPDATA, "Microsoft", "Edge", "Application", "msedge.exe")
31863
+ ].filter((candidate) => Boolean(candidate));
31864
+ return candidates.find(pathExists3) ?? null;
31865
+ }
31866
+ function buildEdgeBrowserAppArgs(boardUrl) {
31867
+ return [
31868
+ `--app=${boardUrl}`,
31869
+ "--start-maximized",
31870
+ "--no-first-run"
31871
+ ];
31872
+ }
31873
+ function quoteWindowsArgument(value) {
31874
+ if (!/[\s"]/u.test(value)) return value;
31875
+ return `"${value.replace(/(\\*)"/gu, '$1$1\\"').replace(/(\\+)$/u, "$1$1")}"`;
31876
+ }
31877
+ function quotePowerShellString(value) {
31878
+ return `'${value.replaceAll("'", "''")}'`;
31879
+ }
31880
+ function buildWindowsBrowserAppShortcutScript(options) {
31881
+ const args = [
31882
+ options.cliEntryPath,
31883
+ "--local-env",
31884
+ options.localEnv,
31885
+ "browser-app",
31886
+ "--data-dir",
31887
+ options.dataDir,
31888
+ "--runtime-version",
31889
+ options.runtimeVersion
31890
+ ].map(quoteWindowsArgument).join(" ");
31891
+ return [
31892
+ "$shell = New-Object -ComObject WScript.Shell",
31893
+ `$shortcut = $shell.CreateShortcut(${quotePowerShellString(options.shortcutPath)})`,
31894
+ `$shortcut.TargetPath = ${quotePowerShellString(options.nodePath)}`,
31895
+ `$shortcut.Arguments = ${quotePowerShellString(args)}`,
31896
+ `$shortcut.WorkingDirectory = ${quotePowerShellString(options.workingDirectory)}`,
31897
+ "$shortcut.WindowStyle = 7",
31898
+ ...options.iconPath ? [`$shortcut.IconLocation = ${quotePowerShellString(options.iconPath)}`] : [],
31899
+ "$shortcut.Save()"
31900
+ ].join("; ");
31901
+ }
31902
+ function createWindowsBrowserAppShortcut(options) {
31903
+ const env = options.env ?? process.env;
31904
+ const appData = env.APPDATA?.trim() || path14.join(homedir(), "AppData", "Roaming");
31905
+ const shortcutPath = path14.join(appData, "Microsoft", "Windows", "Start Menu", "Programs", "Rudder.lnk");
31906
+ mkdirSync(path14.dirname(shortcutPath), { recursive: true });
31907
+ const result = (options.spawnSyncImpl ?? spawnSync3)("powershell.exe", [
31908
+ "-NoProfile",
31909
+ "-Command",
31910
+ buildWindowsBrowserAppShortcutScript({
31911
+ shortcutPath,
31912
+ nodePath: options.nodePath,
31913
+ cliEntryPath: options.cliEntryPath,
31914
+ localEnv: options.localEnv,
31915
+ dataDir: path14.resolve(options.dataDir),
31916
+ runtimeVersion: options.runtimeVersion,
31917
+ workingDirectory: options.workingDirectory,
31918
+ iconPath: options.iconPath
31919
+ })
31920
+ ], { stdio: "ignore", windowsHide: true });
31921
+ if (result.status !== 0) throw new Error("Could not create the Windows Rudder browser-app shortcut.");
31922
+ return shortcutPath;
31923
+ }
31924
+ function launchBrowserAppWindow(boardUrl, options = {}) {
31925
+ const env = options.env ?? process.env;
31926
+ const spawnImpl = options.spawnImpl ?? spawn3;
31927
+ const edge = resolveEdgeExecutable(env, options.pathExists);
31928
+ if (edge) {
31929
+ spawnImpl(edge, buildEdgeBrowserAppArgs(boardUrl), {
31930
+ detached: true,
31931
+ stdio: "ignore",
31932
+ windowsHide: false
31933
+ }).unref();
31934
+ return "edge";
31935
+ }
31936
+ spawnImpl("cmd.exe", ["/c", "start", "", boardUrl], {
31937
+ detached: true,
31938
+ stdio: "ignore",
31939
+ windowsHide: true
31940
+ }).unref();
31941
+ return "default";
31942
+ }
31943
+ function terminateDetachedBrowserAppProcess(child, options = {}) {
31944
+ const pid = child.pid;
31945
+ if (!Number.isSafeInteger(pid) || !pid || pid <= 0) {
31946
+ child.kill?.("SIGKILL");
31947
+ return;
31948
+ }
31949
+ if ((options.platform ?? process.platform) === "win32") {
31950
+ (options.spawnSyncImpl ?? spawnSync3)("taskkill.exe", ["/PID", String(pid), "/T", "/F"], {
31951
+ stdio: "ignore",
31952
+ windowsHide: true
31953
+ });
31954
+ return;
31955
+ }
31956
+ const processKill = options.processKill ?? ((targetPid, signal) => {
31957
+ process.kill(targetPid, signal);
31958
+ });
31959
+ try {
31960
+ processKill(-pid, "SIGKILL");
31961
+ } catch {
31962
+ try {
31963
+ processKill(pid, "SIGKILL");
31964
+ } catch {
31965
+ }
31966
+ }
31967
+ child.kill?.("SIGKILL");
31968
+ }
31969
+ function applyBrowserAppEnvironment(options = {}) {
31970
+ applyLocalEnvProfile(options);
31971
+ applyDataDirOverride(options);
31972
+ const profile = resolveActiveLocalEnvProfile() ?? applyLocalEnvProfile({ localEnv: "prod_local" });
31973
+ if (!profile) throw new Error("Rudder browser-app requires a local environment profile.");
31974
+ process.env.RUDDER_LOCAL_ENV = profile.name;
31975
+ process.env.RUDDER_INSTANCE_ID = profile.instanceId;
31976
+ process.env.PORT = String(profile.port);
31977
+ process.env.RUDDER_EMBEDDED_POSTGRES_PORT = String(profile.embeddedPostgresPort);
31978
+ process.env.RUDDER_DEPLOYMENT_MODE = "local_trusted";
31979
+ process.env.RUDDER_DEPLOYMENT_EXPOSURE = "private";
31980
+ process.env.HOST = "127.0.0.1";
31981
+ process.env.SERVE_UI = "true";
31982
+ process.env.RUDDER_UI_DEV_MIDDLEWARE = "false";
31983
+ process.env.RUDDER_OPEN_ON_LISTEN = "false";
31984
+ }
31985
+ async function writeReadyRecord(readyFile, record) {
31986
+ if (!readyFile) return;
31987
+ await writeFile2(readyFile, `${JSON.stringify(record)}
31988
+ `, "utf8");
31989
+ }
31990
+ function boardUrlFromServer(startedServer) {
31991
+ return startedServer.apiUrl.replace(/\/api\/?$/u, "");
31992
+ }
31993
+ async function waitForShutdownSignal() {
31994
+ await new Promise((resolve) => {
31995
+ const finish = () => resolve();
31996
+ process.once("SIGINT", finish);
31997
+ process.once("SIGTERM", finish);
31998
+ });
31999
+ }
32000
+ async function runtimeStillHealthy(apiUrl) {
32001
+ try {
32002
+ const response = await fetch(new URL("/api/health", apiUrl), {
32003
+ signal: AbortSignal.timeout(1e3),
32004
+ headers: { Accept: "application/json" }
32005
+ });
32006
+ return response.ok;
32007
+ } catch {
32008
+ return false;
32009
+ }
32010
+ }
32011
+ function processIsAlive(pid) {
32012
+ if (!Number.isSafeInteger(pid) || pid <= 0) return false;
32013
+ try {
32014
+ process.kill(pid, 0);
32015
+ return true;
32016
+ } catch (error) {
32017
+ return error.code === "EPERM";
32018
+ }
32019
+ }
32020
+ function acquireDesktopTakeoverLease(instanceId) {
32021
+ const instanceRoot = describeLocalInstancePaths(instanceId).instanceRoot;
32022
+ mkdirSync(instanceRoot, { recursive: true });
32023
+ const leaseDir = path14.join(instanceRoot, DESKTOP_TAKEOVER_LEASE_DIR);
32024
+ const leaseRecordPath = path14.join(leaseDir, "owner.json");
32025
+ const token = randomUUID2();
32026
+ const processStartedAt = Math.round(Date.now() - process.uptime() * 1e3);
32027
+ for (let attempt = 0; attempt < 2; attempt += 1) {
32028
+ try {
32029
+ mkdirSync(leaseDir);
32030
+ try {
32031
+ writeFileSync(
32032
+ leaseRecordPath,
32033
+ `${JSON.stringify({ pid: process.pid, processStartedAt, token })}
32034
+ `,
32035
+ { encoding: "utf8", flag: "wx" }
32036
+ );
32037
+ } catch (error) {
32038
+ try {
32039
+ rmdirSync(leaseDir);
32040
+ } catch {
32041
+ }
32042
+ throw error;
32043
+ }
32044
+ return () => {
32045
+ try {
32046
+ const current = JSON.parse(readFileSync2(leaseRecordPath, "utf8"));
32047
+ if (current.pid !== process.pid || current.token !== token) return;
32048
+ unlinkSync(leaseRecordPath);
32049
+ rmdirSync(leaseDir);
32050
+ } catch {
32051
+ }
32052
+ };
32053
+ } catch (error) {
32054
+ if (error.code !== "EEXIST") throw error;
32055
+ let existingPid = null;
32056
+ let existingProcessStartedAt = null;
32057
+ try {
32058
+ const existing = JSON.parse(readFileSync2(leaseRecordPath, "utf8"));
32059
+ existingPid = typeof existing.pid === "number" ? existing.pid : null;
32060
+ existingProcessStartedAt = typeof existing.processStartedAt === "number" ? existing.processStartedAt : null;
32061
+ } catch {
32062
+ let ageMs;
32063
+ try {
32064
+ ageMs = Date.now() - statSync2(leaseDir).mtimeMs;
32065
+ } catch (statError) {
32066
+ if (statError.code === "ENOENT") continue;
32067
+ throw statError;
32068
+ }
32069
+ if (ageMs < DESKTOP_TAKEOVER_PARTIAL_LEASE_GRACE_MS) return null;
32070
+ }
32071
+ const sameProcess = existingPid === process.pid && existingProcessStartedAt !== null && Math.abs(existingProcessStartedAt - processStartedAt) < 2e3;
32072
+ if (sameProcess || existingPid !== null && existingPid !== process.pid && processIsAlive(existingPid)) {
32073
+ return null;
32074
+ }
32075
+ try {
32076
+ unlinkSync(leaseRecordPath);
32077
+ } catch (unlinkError) {
32078
+ if (unlinkError.code !== "ENOENT") return null;
32079
+ }
32080
+ try {
32081
+ rmdirSync(leaseDir);
32082
+ } catch {
32083
+ return null;
32084
+ }
32085
+ }
32086
+ }
32087
+ return null;
32088
+ }
32089
+ async function runBrowserAppChild(options) {
32090
+ applyBrowserAppEnvironment(options);
32091
+ const runtimeVersion = options.runtimeVersion?.trim() || resolveBrowserAppRuntimeVersion();
32092
+ let startedServer = null;
32093
+ let readyWritten = false;
32094
+ let releaseDesktopTakeoverLease = null;
32095
+ const runtimePackageDir = process.env.RUDDER_BROWSER_APP_RUNTIME_PACKAGE_DIR?.trim();
32096
+ try {
32097
+ while (true) {
32098
+ startedServer = await startManagedServerFromRuntime({
32099
+ version: runtimeVersion,
32100
+ ...runtimePackageDir ? { runtimePackageDir } : {},
32101
+ // A native Desktop runtime owns the process while it is alive. Never
32102
+ // terminate it just to replace a mismatched browser-app version.
32103
+ takeoverOnVersionMismatch: false
32104
+ });
32105
+ const boardUrl = boardUrlFromServer(startedServer);
32106
+ if (!readyWritten) {
32107
+ await writeReadyRecord(options.readyFile, {
32108
+ ok: true,
32109
+ apiUrl: startedServer.apiUrl,
32110
+ boardUrl,
32111
+ runtimeMode: startedServer.runtime.mode
32112
+ });
32113
+ readyWritten = true;
32114
+ if (options.open !== false) launchBrowserAppWindow(boardUrl);
32115
+ }
32116
+ if (startedServer.runtime.mode === "owned") {
32117
+ releaseDesktopTakeoverLease?.();
32118
+ releaseDesktopTakeoverLease = null;
32119
+ await waitForShutdownSignal();
32120
+ await startedServer.dispose();
32121
+ return;
32122
+ }
32123
+ if (startedServer.runtime.ownerKind !== "desktop") return;
32124
+ releaseDesktopTakeoverLease ??= acquireDesktopTakeoverLease(startedServer.runtime.instanceId);
32125
+ if (!releaseDesktopTakeoverLease) return;
32126
+ while (await runtimeStillHealthy(startedServer.apiUrl)) {
32127
+ await delay(RUNTIME_HEALTH_POLL_MS);
32128
+ }
32129
+ await delay(500);
32130
+ }
32131
+ } catch (error) {
32132
+ if (!readyWritten) {
32133
+ await writeReadyRecord(options.readyFile, {
32134
+ ok: false,
32135
+ error: error instanceof Error ? error.message : String(error)
32136
+ });
32137
+ }
32138
+ throw error;
32139
+ } finally {
32140
+ releaseDesktopTakeoverLease?.();
32141
+ }
32142
+ }
32143
+ async function readReadyRecord(readyFile) {
32144
+ return JSON.parse(await readFile3(readyFile, "utf8"));
31515
32145
  }
31516
- function errorMessage(err) {
31517
- return err instanceof Error ? err.message : String(err);
32146
+ async function waitForReadyRecord(options) {
32147
+ const timeoutMs = options.timeoutMs ?? BROWSER_APP_READY_TIMEOUT_MS;
32148
+ const startedAt = Date.now();
32149
+ const childState = { stopped: null };
32150
+ const onExit = (code, signal) => {
32151
+ childState.stopped = { code, signal };
32152
+ };
32153
+ const onError = (error) => {
32154
+ childState.stopped = { code: null, signal: null, error };
32155
+ };
32156
+ options.child.once("exit", onExit);
32157
+ options.child.once("error", onError);
32158
+ try {
32159
+ while (Date.now() - startedAt < timeoutMs) {
32160
+ try {
32161
+ return await readReadyRecord(options.readyFile);
32162
+ } catch {
32163
+ const stopped = childState.stopped;
32164
+ if (stopped) {
32165
+ if (stopped.error) {
32166
+ throw new Error(`Rudder browser-app process failed before it was ready. See ${options.logPath}.`, {
32167
+ cause: stopped.error
32168
+ });
32169
+ }
32170
+ const outcome = stopped.signal ? `signal ${stopped.signal}` : `exit code ${stopped.code ?? "unknown"}`;
32171
+ throw new Error(
32172
+ `Rudder browser-app process stopped before it was ready (${outcome}). See ${options.logPath}.`
32173
+ );
32174
+ }
32175
+ await delay(200);
32176
+ }
32177
+ }
32178
+ throw new Error("Rudder browser-app did not become ready in time.");
32179
+ } finally {
32180
+ options.child.off("exit", onExit);
32181
+ options.child.off("error", onError);
32182
+ }
31518
32183
  }
31519
- function errorDetails(err) {
31520
- if (!(err instanceof Error)) return void 0;
31521
- if (err instanceof ApiRequestError) {
31522
- const details = isRecord3(err.details) ? err.details : err.details === void 0 ? {} : { upstreamDetails: err.details };
32184
+ async function launchDetachedBrowserApp(options) {
32185
+ applyLocalEnvProfile(options);
32186
+ applyDataDirOverride(options);
32187
+ const localProfile = resolveActiveLocalEnvProfile() ?? applyLocalEnvProfile({ localEnv: "prod_local" });
32188
+ if (!localProfile) throw new Error("Rudder browser-app requires a local environment profile.");
32189
+ const dataDir = resolveRudderHomeDir();
32190
+ const instanceId = resolveRudderInstanceId(localProfile.instanceId);
32191
+ const paths = describeLocalInstancePaths(instanceId);
32192
+ const logDir = path14.join(paths.instanceRoot, "logs");
32193
+ mkdirSync(logDir, { recursive: true });
32194
+ const logPath = path14.join(logDir, "browser-app.log");
32195
+ const readyFile = path14.join(tmpdir(), `rudder-browser-app-${process.pid}-${randomUUID2()}.json`);
32196
+ const logFd = openSync(logPath, "a");
32197
+ const spawnImpl = options.spawnImpl ?? spawn3;
32198
+ let child = null;
32199
+ let launchSucceeded = false;
32200
+ try {
32201
+ const spawnedChild = spawnImpl(options.nodePath ?? process.execPath, [
32202
+ options.cliEntryPath,
32203
+ "--local-env",
32204
+ localProfile.name,
32205
+ "browser-app",
32206
+ "--data-dir",
32207
+ dataDir,
32208
+ "--child",
32209
+ "--no-open",
32210
+ "--ready-file",
32211
+ readyFile,
32212
+ "--runtime-version",
32213
+ options.runtimeVersion
32214
+ ], {
32215
+ detached: true,
32216
+ windowsHide: true,
32217
+ stdio: ["ignore", logFd, logFd]
32218
+ });
32219
+ child = spawnedChild;
32220
+ await new Promise((resolve, reject) => {
32221
+ spawnedChild.once("spawn", resolve);
32222
+ spawnedChild.once("error", reject);
32223
+ });
32224
+ spawnedChild.unref();
32225
+ } catch (error) {
32226
+ if (child) {
32227
+ terminateDetachedBrowserAppProcess(child, {
32228
+ platform: options.platform,
32229
+ processKill: options.processKill,
32230
+ spawnSyncImpl: options.spawnSyncImpl
32231
+ });
32232
+ }
32233
+ throw error;
32234
+ } finally {
32235
+ closeSync(logFd);
32236
+ }
32237
+ try {
32238
+ const ready = await waitForReadyRecord({
32239
+ readyFile,
32240
+ child,
32241
+ logPath,
32242
+ timeoutMs: options.readyTimeoutMs
32243
+ });
32244
+ if (!ready.ok || !ready.apiUrl || !ready.boardUrl || !ready.runtimeMode) {
32245
+ throw new Error(ready.error || `Rudder browser-app failed to start. See ${logPath}.`);
32246
+ }
32247
+ const browser = options.open === false ? null : launchBrowserAppWindow(ready.boardUrl);
32248
+ launchSucceeded = true;
31523
32249
  return {
31524
- code: err.code ?? "api_request_error",
31525
- status: err.status,
31526
- ...details
32250
+ apiUrl: ready.apiUrl,
32251
+ boardUrl: ready.boardUrl,
32252
+ browser,
32253
+ logPath,
32254
+ runtimeMode: ready.runtimeMode
31527
32255
  };
32256
+ } finally {
32257
+ await rm3(readyFile, { force: true });
32258
+ if (!launchSucceeded && child) {
32259
+ terminateDetachedBrowserAppProcess(child, {
32260
+ platform: options.platform,
32261
+ processKill: options.processKill,
32262
+ spawnSyncImpl: options.spawnSyncImpl
32263
+ });
32264
+ }
31528
32265
  }
31529
- const code = err.code;
31530
- return code ? { code } : void 0;
31531
- }
31532
- function isRecord3(value) {
31533
- return typeof value === "object" && value !== null && !Array.isArray(value);
31534
32266
  }
31535
-
31536
- // src/commands/allowed-hostname.ts
31537
- init_hostnames();
31538
- init_store();
31539
- import * as p from "@clack/prompts";
31540
- import pc3 from "picocolors";
31541
- async function addAllowedHostname(host, opts) {
31542
- const configPath = resolveConfigPath(opts.config);
31543
- const config = readConfig(opts.config);
31544
- if (!config) {
31545
- p.log.error(`No config found at ${configPath}. Run ${pc3.cyan("rudder onboard")} first.`);
31546
- return;
31547
- }
31548
- const normalized = normalizeHostnameInput(host);
31549
- const current = new Set((config.server.allowedHostnames ?? []).map((value) => value.trim().toLowerCase()).filter(Boolean));
31550
- const existed = current.has(normalized);
31551
- current.add(normalized);
31552
- config.server.allowedHostnames = Array.from(current).sort();
31553
- config.$meta.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
31554
- config.$meta.source = "configure";
31555
- writeConfig(config, opts.config);
31556
- if (existed) {
31557
- p.log.info(`Hostname ${pc3.cyan(normalized)} is already allowed.`);
31558
- } else {
31559
- p.log.success(`Added allowed hostname: ${pc3.cyan(normalized)}`);
31560
- p.log.message(
31561
- pc3.dim("Restart the Rudder server for this change to take effect.")
31562
- );
32267
+ async function browserAppCommand(options) {
32268
+ if (process.platform !== "win32") {
32269
+ throw new Error("Rudder browser-app compatibility mode is currently available on Windows only.");
31563
32270
  }
31564
- if (!(config.server.deploymentMode === "authenticated" && config.server.exposure === "private")) {
31565
- p.log.message(
31566
- pc3.dim("Note: allowed hostnames are enforced only in authenticated/private mode.")
31567
- );
32271
+ const runtimeVersion = options.runtimeVersion?.trim() || resolveBrowserAppRuntimeVersion();
32272
+ if (options.child) {
32273
+ await runBrowserAppChild({ ...options, runtimeVersion });
32274
+ return;
31568
32275
  }
32276
+ const result = await launchDetachedBrowserApp({
32277
+ cliEntryPath: process.argv[1],
32278
+ localEnv: options.localEnv,
32279
+ dataDir: options.dataDir,
32280
+ runtimeVersion,
32281
+ open: options.open !== false
32282
+ });
32283
+ process.stdout.write(
32284
+ options.open === false ? `Rudder browser-app runtime is ready at ${result.boardUrl} (${result.runtimeMode})
32285
+ ` : `Rudder browser app opened at ${result.boardUrl} (${result.runtimeMode})
32286
+ `
32287
+ );
31569
32288
  }
31570
32289
 
31571
- // src/program.ts
31572
- init_auth_bootstrap_ceo();
31573
-
31574
32290
  // src/commands/client/activity.ts
31575
32291
  function registerActivityCommands(program) {
31576
32292
  const activity = program.command("activity").description("Activity log operations");
@@ -31583,8 +32299,8 @@ function registerActivityCommands(program) {
31583
32299
  if (opts.entityType) params.set("entityType", opts.entityType);
31584
32300
  if (opts.entityId) params.set("entityId", opts.entityId);
31585
32301
  const query = params.toString();
31586
- const path26 = `/api/orgs/${ctx.orgId}/activity${query ? `?${query}` : ""}`;
31587
- const rows = await ctx.api.get(path26) ?? [];
32302
+ const path29 = `/api/orgs/${ctx.orgId}/activity${query ? `?${query}` : ""}`;
32303
+ const rows = await ctx.api.get(path29) ?? [];
31588
32304
  if (ctx.json) {
31589
32305
  printOutput(rows, { json: true });
31590
32306
  return;
@@ -31616,7 +32332,7 @@ function registerActivityCommands(program) {
31616
32332
 
31617
32333
  // ../packages/agent-runtime-utils/dist/server-utils.cli.js
31618
32334
  import { promises as fs9 } from "node:fs";
31619
- import path12 from "node:path";
32335
+ import path15 from "node:path";
31620
32336
 
31621
32337
  // ../packages/agent-runtime-utils/dist/native-process-runner.js
31622
32338
  init_dist2();
@@ -32122,8 +32838,8 @@ var RUDDER_AGENT_HEARTBEAT_INSTRUCTION = [
32122
32838
  // ../packages/agent-runtime-utils/dist/server-utils.cli.js
32123
32839
  async function resolveRudderSkillsDir(moduleDir, additionalCandidates = []) {
32124
32840
  const candidates = [
32125
- ...RUDDER_SKILL_ROOT_RELATIVE_CANDIDATES.map((relativePath) => path12.resolve(moduleDir, relativePath)),
32126
- ...additionalCandidates.map((candidate) => path12.resolve(candidate))
32841
+ ...RUDDER_SKILL_ROOT_RELATIVE_CANDIDATES.map((relativePath) => path15.resolve(moduleDir, relativePath)),
32842
+ ...additionalCandidates.map((candidate) => path15.resolve(candidate))
32127
32843
  ];
32128
32844
  const seenRoots = /* @__PURE__ */ new Set();
32129
32845
  for (const root of candidates) {
@@ -32140,26 +32856,26 @@ async function removeMaintainerOnlySkillSymlinks(skillsHome, allowedSkillNames)
32140
32856
  return removeUnselectedRudderSkillSymlinks(skillsHome, allowedSkillNames);
32141
32857
  }
32142
32858
  async function readRudderMaterializedSkillSource(target) {
32143
- const manifestPath = path12.join(target, ".rudder", "materialized-skill.json");
32859
+ const manifestPath = path15.join(target, ".rudder", "materialized-skill.json");
32144
32860
  const raw = await fs9.readFile(manifestPath, "utf8").catch(() => null);
32145
32861
  if (!raw)
32146
32862
  return null;
32147
32863
  try {
32148
32864
  const parsed = parseObject(JSON.parse(raw));
32149
32865
  const sourcePath = asString(parsed.sourcePath, "").trim();
32150
- return sourcePath.length > 0 ? path12.resolve(sourcePath) : null;
32866
+ return sourcePath.length > 0 ? path15.resolve(sourcePath) : null;
32151
32867
  } catch {
32152
32868
  return null;
32153
32869
  }
32154
32870
  }
32155
32871
  async function removeUnselectedRudderSkillSymlinks(skillsHome, allowedSkillNames, knownSkillSources = []) {
32156
32872
  const allowed = new Set(Array.from(allowedSkillNames));
32157
- const knownSources = new Set(Array.from(knownSkillSources).map((value) => value.trim()).filter(Boolean).map((value) => path12.resolve(value)));
32873
+ const knownSources = new Set(Array.from(knownSkillSources).map((value) => value.trim()).filter(Boolean).map((value) => path15.resolve(value)));
32158
32874
  try {
32159
32875
  const entries = await fs9.readdir(skillsHome, { withFileTypes: true });
32160
32876
  const removed = [];
32161
32877
  for (const entry of entries) {
32162
- const target = path12.join(skillsHome, entry.name);
32878
+ const target = path15.join(skillsHome, entry.name);
32163
32879
  const existing = await fs9.lstat(target).catch(() => null);
32164
32880
  if (!existing)
32165
32881
  continue;
@@ -32168,8 +32884,8 @@ async function removeUnselectedRudderSkillSymlinks(skillsHome, allowedSkillNames
32168
32884
  const linkedPath = await fs9.readlink(target).catch(() => null);
32169
32885
  if (!linkedPath)
32170
32886
  continue;
32171
- const resolvedLinkedPath = path12.isAbsolute(linkedPath) ? linkedPath : path12.resolve(path12.dirname(target), linkedPath);
32172
- isRudderManagedSkill = knownSources.has(path12.resolve(resolvedLinkedPath)) || isMaintainerOnlySkillTarget(linkedPath) || isMaintainerOnlySkillTarget(resolvedLinkedPath);
32887
+ const resolvedLinkedPath = path15.isAbsolute(linkedPath) ? linkedPath : path15.resolve(path15.dirname(target), linkedPath);
32888
+ isRudderManagedSkill = knownSources.has(path15.resolve(resolvedLinkedPath)) || isMaintainerOnlySkillTarget(linkedPath) || isMaintainerOnlySkillTarget(resolvedLinkedPath);
32173
32889
  } else if (existing.isDirectory()) {
32174
32890
  const materializedSource = await readRudderMaterializedSkillSource(target);
32175
32891
  isRudderManagedSkill = materializedSource !== null && knownSources.has(materializedSource);
@@ -32191,7 +32907,7 @@ async function removeUnselectedRudderSkillSymlinks(skillsHome, allowedSkillNames
32191
32907
  init_dist2();
32192
32908
  import fs10 from "node:fs/promises";
32193
32909
  import os4 from "node:os";
32194
- import path13 from "node:path";
32910
+ import path16 from "node:path";
32195
32911
  import { fileURLToPath as fileURLToPath6 } from "node:url";
32196
32912
 
32197
32913
  // src/commands/client/help.ts
@@ -32215,16 +32931,16 @@ function formatHelpExample(example) {
32215
32931
  }
32216
32932
 
32217
32933
  // src/commands/client/agent.ts
32218
- var __moduleDir = path13.dirname(fileURLToPath6(import.meta.url));
32934
+ var __moduleDir = path16.dirname(fileURLToPath6(import.meta.url));
32219
32935
  function codexSkillsHome() {
32220
32936
  const fromEnv = process.env.CODEX_HOME?.trim();
32221
- const base = fromEnv && fromEnv.length > 0 ? fromEnv : path13.join(os4.homedir(), ".codex");
32222
- return path13.join(base, "skills");
32937
+ const base = fromEnv && fromEnv.length > 0 ? fromEnv : path16.join(os4.homedir(), ".codex");
32938
+ return path16.join(base, "skills");
32223
32939
  }
32224
32940
  function claudeSkillsHome() {
32225
32941
  const fromEnv = process.env.CLAUDE_HOME?.trim();
32226
- const base = fromEnv && fromEnv.length > 0 ? fromEnv : path13.join(os4.homedir(), ".claude");
32227
- return path13.join(base, "skills");
32942
+ const base = fromEnv && fromEnv.length > 0 ? fromEnv : path16.join(os4.homedir(), ".claude");
32943
+ return path16.join(base, "skills");
32228
32944
  }
32229
32945
  async function installSkillsForTarget(sourceSkillsDir, targetSkillsDir, tool2) {
32230
32946
  const summary = {
@@ -32243,8 +32959,8 @@ async function installSkillsForTarget(sourceSkillsDir, targetSkillsDir, tool2) {
32243
32959
  );
32244
32960
  for (const entry of entries) {
32245
32961
  if (!entry.isDirectory()) continue;
32246
- const source = path13.join(sourceSkillsDir, entry.name);
32247
- const target = path13.join(targetSkillsDir, entry.name);
32962
+ const source = path16.join(sourceSkillsDir, entry.name);
32963
+ const target = path16.join(targetSkillsDir, entry.name);
32248
32964
  const existing = await fs10.lstat(target).catch(() => null);
32249
32965
  if (existing) {
32250
32966
  if (existing.isSymbolicLink()) {
@@ -32265,7 +32981,7 @@ async function installSkillsForTarget(sourceSkillsDir, targetSkillsDir, tool2) {
32265
32981
  continue;
32266
32982
  }
32267
32983
  }
32268
- const resolvedLinkedPath = path13.isAbsolute(linkedPath) ? linkedPath : path13.resolve(path13.dirname(target), linkedPath);
32984
+ const resolvedLinkedPath = path16.isAbsolute(linkedPath) ? linkedPath : path16.resolve(path16.dirname(target), linkedPath);
32269
32985
  const linkedTargetExists = await fs10.stat(resolvedLinkedPath).then(() => true).catch(() => false);
32270
32986
  if (!linkedTargetExists) {
32271
32987
  await fs10.unlink(target);
@@ -32490,7 +33206,7 @@ function registerAgentCommands(program) {
32490
33206
  if (opts.markdown && opts.markdownFile) {
32491
33207
  throw new Error("Pass only one of --markdown or --markdown-file.");
32492
33208
  }
32493
- const markdown = opts.markdownFile ? await fs10.readFile(path13.resolve(opts.markdownFile), "utf8") : opts.markdown;
33209
+ const markdown = opts.markdownFile ? await fs10.readFile(path16.resolve(opts.markdownFile), "utf8") : opts.markdown;
32494
33210
  const payload = organizationSkillCreateSchema.parse({
32495
33211
  name: opts.name,
32496
33212
  slug: opts.slug?.trim() || null,
@@ -32669,7 +33385,7 @@ function registerAgentCommands(program) {
32669
33385
  }
32670
33386
  const installSummaries = [];
32671
33387
  if (opts.installSkills !== false) {
32672
- const skillsDir = await resolveRudderSkillsDir(__moduleDir, [path13.resolve(process.cwd(), "skills")]);
33388
+ const skillsDir = await resolveRudderSkillsDir(__moduleDir, [path16.resolve(process.cwd(), "skills")]);
32673
33389
  if (!skillsDir) {
32674
33390
  throw new Error(
32675
33391
  "Could not locate local Rudder skills directory. Expected ./skills in the repo checkout."
@@ -32757,10 +33473,10 @@ async function buildAgentUpdatePatch(opts) {
32757
33473
  if (opts.capabilities !== void 0) rawPatch.capabilities = opts.capabilities;
32758
33474
  if (opts.description !== void 0) rawPatch.capabilities = opts.description;
32759
33475
  if (opts.capabilitiesFile !== void 0) {
32760
- rawPatch.capabilities = await fs10.readFile(path13.resolve(opts.capabilitiesFile), "utf8");
33476
+ rawPatch.capabilities = await fs10.readFile(path16.resolve(opts.capabilitiesFile), "utf8");
32761
33477
  }
32762
33478
  if (opts.descriptionFile !== void 0) {
32763
- rawPatch.capabilities = await fs10.readFile(path13.resolve(opts.descriptionFile), "utf8");
33479
+ rawPatch.capabilities = await fs10.readFile(path16.resolve(opts.descriptionFile), "utf8");
32764
33480
  }
32765
33481
  if (clearCapabilities) rawPatch.capabilities = null;
32766
33482
  return updateAgentSchema.parse(rawPatch);
@@ -32783,8 +33499,8 @@ function parseJsonObject(value, name) {
32783
33499
 
32784
33500
  // src/commands/client/approval.ts
32785
33501
  init_dist2();
32786
- import { readFile as readFile2 } from "node:fs/promises";
32787
- import path14 from "node:path";
33502
+ import { readFile as readFile4 } from "node:fs/promises";
33503
+ import path17 from "node:path";
32788
33504
  function registerApprovalCommands(program) {
32789
33505
  const approval = program.command("approval").description("Approval operations");
32790
33506
  addCommonClientOptions(
@@ -32975,8 +33691,8 @@ async function readTextInputFile(inputPath, optionName) {
32975
33691
  if (inputPath === "-") {
32976
33692
  return readStdinText();
32977
33693
  }
32978
- const resolvedPath = path14.resolve(process.cwd(), inputPath);
32979
- return readFile2(resolvedPath, "utf8").catch((err) => {
33694
+ const resolvedPath = path17.resolve(process.cwd(), inputPath);
33695
+ return readFile4(resolvedPath, "utf8").catch((err) => {
32980
33696
  throw new Error(`Unable to read ${optionName} ${inputPath}: ${err instanceof Error ? err.message : String(err)}`);
32981
33697
  });
32982
33698
  }
@@ -33812,12 +34528,12 @@ async function readStdin() {
33812
34528
 
33813
34529
  // src/commands/client/company.ts
33814
34530
  import * as p3 from "@clack/prompts";
33815
- import { mkdir as mkdir2, readdir as readdir2, readFile as readFile3, stat as stat2, writeFile as writeFile2 } from "node:fs/promises";
33816
- import path16 from "node:path";
34531
+ import { mkdir as mkdir3, readdir as readdir2, readFile as readFile5, stat as stat2, writeFile as writeFile3 } from "node:fs/promises";
34532
+ import path19 from "node:path";
33817
34533
  import pc5 from "picocolors";
33818
34534
 
33819
34535
  // src/commands/client/zip.ts
33820
- import path15 from "node:path";
34536
+ import path18 from "node:path";
33821
34537
  import { inflateRawSync } from "node:zlib";
33822
34538
  var textDecoder = new TextDecoder();
33823
34539
  var binaryContentTypeByExtension = {
@@ -33845,7 +34561,7 @@ function sharedArchiveRoot(paths) {
33845
34561
  return firstSegments.every((parts) => parts.length > 1 && parts[0] === candidate) ? candidate : null;
33846
34562
  }
33847
34563
  function bytesToPortableFileEntry(pathValue, bytes) {
33848
- const contentType = binaryContentTypeByExtension[path15.extname(pathValue).toLowerCase()];
34564
+ const contentType = binaryContentTypeByExtension[path18.extname(pathValue).toLowerCase()];
33849
34565
  if (!contentType) return textDecoder.decode(bytes);
33850
34566
  return {
33851
34567
  encoding: "base64",
@@ -33933,7 +34649,7 @@ var IMPORT_INCLUDE_OPTIONS = [
33933
34649
  ];
33934
34650
  var IMPORT_PREVIEW_SAMPLE_LIMIT = 6;
33935
34651
  function readPortableFileEntry(filePath, contents) {
33936
- const contentType = binaryContentTypeByExtension[path16.extname(filePath).toLowerCase()];
34652
+ const contentType = binaryContentTypeByExtension[path19.extname(filePath).toLowerCase()];
33937
34653
  if (!contentType) return contents.toString("utf8");
33938
34654
  return {
33939
34655
  encoding: "base64",
@@ -33988,10 +34704,10 @@ function normalizePortablePath(filePath) {
33988
34704
  return filePath.replace(/\\/g, "/");
33989
34705
  }
33990
34706
  function shouldIncludePortableFile(filePath) {
33991
- const baseName = path16.basename(filePath);
34707
+ const baseName = path19.basename(filePath);
33992
34708
  const isMarkdown = baseName.endsWith(".md");
33993
34709
  const isPaperclipYaml = baseName === ".rudder.yaml" || baseName === ".rudder.yml";
33994
- const contentType = binaryContentTypeByExtension[path16.extname(baseName).toLowerCase()];
34710
+ const contentType = binaryContentTypeByExtension[path19.extname(baseName).toLowerCase()];
33995
34711
  return isMarkdown || isPaperclipYaml || Boolean(contentType);
33996
34712
  }
33997
34713
  function findPortableExtensionPath(files) {
@@ -34546,7 +35262,7 @@ function normalizeGithubImportSource(input, refOverride) {
34546
35262
  }
34547
35263
  async function pathExists(inputPath) {
34548
35264
  try {
34549
- await stat2(path16.resolve(inputPath));
35265
+ await stat2(path19.resolve(inputPath));
34550
35266
  return true;
34551
35267
  } catch {
34552
35268
  return false;
@@ -34556,55 +35272,55 @@ async function collectPackageFiles(root, current, files) {
34556
35272
  const entries = await readdir2(current, { withFileTypes: true });
34557
35273
  for (const entry of entries) {
34558
35274
  if (entry.name.startsWith(".git")) continue;
34559
- const absolutePath = path16.join(current, entry.name);
35275
+ const absolutePath = path19.join(current, entry.name);
34560
35276
  if (entry.isDirectory()) {
34561
35277
  await collectPackageFiles(root, absolutePath, files);
34562
35278
  continue;
34563
35279
  }
34564
35280
  if (!entry.isFile()) continue;
34565
- const relativePath = path16.relative(root, absolutePath).replace(/\\/g, "/");
35281
+ const relativePath = path19.relative(root, absolutePath).replace(/\\/g, "/");
34566
35282
  if (!shouldIncludePortableFile(relativePath)) continue;
34567
- files[relativePath] = readPortableFileEntry(relativePath, await readFile3(absolutePath));
35283
+ files[relativePath] = readPortableFileEntry(relativePath, await readFile5(absolutePath));
34568
35284
  }
34569
35285
  }
34570
35286
  async function resolveInlineSourceFromPath(inputPath) {
34571
- const resolved = path16.resolve(inputPath);
35287
+ const resolved = path19.resolve(inputPath);
34572
35288
  const resolvedStat = await stat2(resolved);
34573
- if (resolvedStat.isFile() && path16.extname(resolved).toLowerCase() === ".zip") {
34574
- const archive = await readZipArchive(await readFile3(resolved));
35289
+ if (resolvedStat.isFile() && path19.extname(resolved).toLowerCase() === ".zip") {
35290
+ const archive = await readZipArchive(await readFile5(resolved));
34575
35291
  const filteredFiles = Object.fromEntries(
34576
35292
  Object.entries(archive.files).filter(([relativePath]) => shouldIncludePortableFile(relativePath))
34577
35293
  );
34578
35294
  return {
34579
- rootPath: archive.rootPath ?? path16.basename(resolved, ".zip"),
35295
+ rootPath: archive.rootPath ?? path19.basename(resolved, ".zip"),
34580
35296
  files: filteredFiles
34581
35297
  };
34582
35298
  }
34583
- const rootDir = resolvedStat.isDirectory() ? resolved : path16.dirname(resolved);
35299
+ const rootDir = resolvedStat.isDirectory() ? resolved : path19.dirname(resolved);
34584
35300
  const files = {};
34585
35301
  await collectPackageFiles(rootDir, rootDir, files);
34586
35302
  return {
34587
- rootPath: path16.basename(rootDir),
35303
+ rootPath: path19.basename(rootDir),
34588
35304
  files
34589
35305
  };
34590
35306
  }
34591
35307
  async function writeExportToFolder(outDir, exported) {
34592
- const root = path16.resolve(outDir);
34593
- await mkdir2(root, { recursive: true });
35308
+ const root = path19.resolve(outDir);
35309
+ await mkdir3(root, { recursive: true });
34594
35310
  for (const [relativePath, content] of Object.entries(exported.files)) {
34595
35311
  const normalized = relativePath.replace(/\\/g, "/");
34596
- const filePath = path16.join(root, normalized);
34597
- await mkdir2(path16.dirname(filePath), { recursive: true });
35312
+ const filePath = path19.join(root, normalized);
35313
+ await mkdir3(path19.dirname(filePath), { recursive: true });
34598
35314
  const writeValue = portableFileEntryToWriteValue(content);
34599
35315
  if (typeof writeValue === "string") {
34600
- await writeFile2(filePath, writeValue, "utf8");
35316
+ await writeFile3(filePath, writeValue, "utf8");
34601
35317
  } else {
34602
- await writeFile2(filePath, writeValue);
35318
+ await writeFile3(filePath, writeValue);
34603
35319
  }
34604
35320
  }
34605
35321
  }
34606
35322
  async function confirmOverwriteExportDirectory(outDir) {
34607
- const root = path16.resolve(outDir);
35323
+ const root = path19.resolve(outDir);
34608
35324
  const stats = await stat2(root).catch(() => null);
34609
35325
  if (!stats) return;
34610
35326
  if (!stats.isDirectory()) {
@@ -34786,7 +35502,7 @@ function registerCompanyCommands(program) {
34786
35502
  printOutput(
34787
35503
  {
34788
35504
  ok: true,
34789
- out: path16.resolve(opts.out),
35505
+ out: path19.resolve(opts.out),
34790
35506
  rootPath: exported.rootPath,
34791
35507
  filesWritten: Object.keys(exported.files).length,
34792
35508
  rudderExtensionPath: exported.rudderExtensionPath,
@@ -35284,8 +36000,8 @@ function parseResultValue(value) {
35284
36000
 
35285
36001
  // src/commands/client/issue.ts
35286
36002
  init_dist2();
35287
- import { readFile as readFile4, stat as stat3 } from "node:fs/promises";
35288
- import path17 from "node:path";
36003
+ import { readFile as readFile6, stat as stat3 } from "node:fs/promises";
36004
+ import path20 from "node:path";
35289
36005
  function registerIssueCommands(program) {
35290
36006
  const issue = program.command("issue").description("Issue operations");
35291
36007
  addCommonClientOptions(
@@ -35649,8 +36365,8 @@ async function readTextInputFile2(inputPath, optionName) {
35649
36365
  if (inputPath === "-") {
35650
36366
  return readStdinText2();
35651
36367
  }
35652
- const resolvedPath = path17.resolve(process.cwd(), inputPath);
35653
- return readFile4(resolvedPath, "utf8").catch((err) => {
36368
+ const resolvedPath = path20.resolve(process.cwd(), inputPath);
36369
+ return readFile6(resolvedPath, "utf8").catch((err) => {
35654
36370
  throw new Error(`Unable to read ${optionName} ${inputPath}: ${err instanceof Error ? err.message : String(err)}`);
35655
36371
  });
35656
36372
  }
@@ -35706,16 +36422,16 @@ async function appendUploadedIssueImages(ctx, issueId, body, imagePaths) {
35706
36422
  ${imageBlock}` : imageBlock;
35707
36423
  }
35708
36424
  async function uploadIssueCommentImage(ctx, issue, imagePath) {
35709
- const resolvedPath = path17.resolve(process.cwd(), imagePath);
36425
+ const resolvedPath = path20.resolve(process.cwd(), imagePath);
35710
36426
  const stats = await stat3(resolvedPath).catch((err) => {
35711
36427
  throw new Error(`Unable to read image ${imagePath}: ${err instanceof Error ? err.message : String(err)}`);
35712
36428
  });
35713
36429
  if (!stats.isFile()) {
35714
36430
  throw new Error(`Image path must be a file: ${imagePath}`);
35715
36431
  }
35716
- const filename = path17.basename(resolvedPath);
36432
+ const filename = path20.basename(resolvedPath);
35717
36433
  const contentType = inferCommentImageContentType(filename);
35718
- const buffer = await readFile4(resolvedPath);
36434
+ const buffer = await readFile6(resolvedPath);
35719
36435
  if (buffer.length <= 0) {
35720
36436
  throw new Error(`Image is empty: ${imagePath}`);
35721
36437
  }
@@ -35732,7 +36448,7 @@ async function uploadIssueCommentImage(ctx, issue, imagePath) {
35732
36448
  return attachment;
35733
36449
  }
35734
36450
  function inferCommentImageContentType(filename) {
35735
- const ext = path17.extname(filename).toLowerCase();
36451
+ const ext = path20.extname(filename).toLowerCase();
35736
36452
  switch (ext) {
35737
36453
  case ".png":
35738
36454
  return "image/png";
@@ -35835,8 +36551,8 @@ function formatIssueSearchMatch(match) {
35835
36551
  }
35836
36552
 
35837
36553
  // src/commands/client/library.ts
35838
- import { readFile as readFile5 } from "node:fs/promises";
35839
- import path18 from "node:path";
36554
+ import { readFile as readFile7 } from "node:fs/promises";
36555
+ import path21 from "node:path";
35840
36556
  function toLibraryFileLinkResult(detail) {
35841
36557
  return {
35842
36558
  filePath: detail.filePath,
@@ -35981,8 +36697,8 @@ async function resolveBodyFileInput(inputPath) {
35981
36697
  if (inputPath === "-") {
35982
36698
  return readStdinText3();
35983
36699
  }
35984
- const resolvedPath = path18.resolve(process.cwd(), inputPath);
35985
- return readFile5(resolvedPath, "utf8").catch((err) => {
36700
+ const resolvedPath = path21.resolve(process.cwd(), inputPath);
36701
+ return readFile7(resolvedPath, "utf8").catch((err) => {
35986
36702
  throw new Error(`Unable to read --body-file ${inputPath}: ${err instanceof Error ? err.message : String(err)}`);
35987
36703
  });
35988
36704
  }
@@ -36850,8 +37566,8 @@ function registerUserCommands(program) {
36850
37566
  appendParam(params, "limit", opts.limit);
36851
37567
  appendParam(params, "cursor", opts.cursor);
36852
37568
  const query = params.toString();
36853
- const path26 = `/api/orgs/${ctx.orgId}/users/${encodeURIComponent(userId)}/activity-ledger${query ? `?${query}` : ""}`;
36854
- const result = await ctx.api.get(path26);
37569
+ const path29 = `/api/orgs/${ctx.orgId}/users/${encodeURIComponent(userId)}/activity-ledger${query ? `?${query}` : ""}`;
37570
+ const result = await ctx.api.get(path29);
36855
37571
  if (ctx.json) {
36856
37572
  printOutput(result, { json: true });
36857
37573
  return;
@@ -37351,7 +38067,7 @@ function quoteShellValue(value) {
37351
38067
  }
37352
38068
 
37353
38069
  // src/commands/heartbeat-run.ts
37354
- import { setTimeout as delay } from "node:timers/promises";
38070
+ import { setTimeout as delay2 } from "node:timers/promises";
37355
38071
  import pc11 from "picocolors";
37356
38072
 
37357
38073
  // src/agent-runtimes/http/format-event.ts
@@ -37596,7 +38312,7 @@ async function heartbeatRun(opts) {
37596
38312
  logOffset += Buffer.byteLength(logResult.content, "utf8");
37597
38313
  }
37598
38314
  }
37599
- await delay(POLL_INTERVAL_MS);
38315
+ await delay2(POLL_INTERVAL_MS);
37600
38316
  }
37601
38317
  if (finalStatus) {
37602
38318
  if (!debug && stdoutJsonBuffer.trim()) {
@@ -37665,14 +38381,14 @@ init_run();
37665
38381
 
37666
38382
  // src/commands/start.ts
37667
38383
  import * as p15 from "@clack/prompts";
37668
- import { spawn as spawn3, spawnSync as spawnSync4 } from "node:child_process";
37669
- import { createHash as createHash5, randomUUID as randomUUID2 } from "node:crypto";
37670
- import { constants as fsConstants, mkdirSync as mkdirSync2, readFileSync as readFileSync2 } from "node:fs";
37671
- import { access, chmod as chmod2, copyFile, cp, lstat, mkdir as mkdir3, mkdtemp as mkdtemp2, readdir as readdir3, readFile as readFile6, rm as rm3, stat as stat4, utimes, writeFile as writeFile3 } from "node:fs/promises";
37672
- import { homedir, tmpdir } from "node:os";
37673
- import path24 from "node:path";
37674
- import { clearTimeout as clearTimeout3, setTimeout as setTimeout3 } from "node:timers";
37675
- import { setTimeout as delay2 } from "node:timers/promises";
38384
+ import { spawn as spawn4, spawnSync as spawnSync5 } from "node:child_process";
38385
+ import { createHash as createHash5, randomUUID as randomUUID3 } from "node:crypto";
38386
+ import { constants as fsConstants, mkdirSync as mkdirSync3, readFileSync as readFileSync3 } from "node:fs";
38387
+ import { access, chmod as chmod2, copyFile, cp, lstat, mkdir as mkdir4, mkdtemp as mkdtemp2, readdir as readdir3, readFile as readFile8, rm as rm5, stat as stat4, utimes, writeFile as writeFile4 } from "node:fs/promises";
38388
+ import { homedir as homedir2, tmpdir as tmpdir2 } from "node:os";
38389
+ import path28 from "node:path";
38390
+ import { clearTimeout as clearTimeout4, setTimeout as setTimeout4 } from "node:timers";
38391
+ import { setTimeout as delay3 } from "node:timers/promises";
37676
38392
  import pc14 from "picocolors";
37677
38393
 
37678
38394
  // src/checksum-manifest.ts
@@ -37696,12 +38412,13 @@ function parseChecksumFile(contents) {
37696
38412
 
37697
38413
  // src/commands/start.ts
37698
38414
  init_home();
38415
+ init_local_env();
37699
38416
 
37700
38417
  // src/desktop-download.ts
37701
38418
  import { createHash as createHash4 } from "node:crypto";
37702
- import { createWriteStream as createWriteStream3, mkdirSync } from "node:fs";
37703
- import { rm as rm2 } from "node:fs/promises";
37704
- import path23 from "node:path";
38419
+ import { createWriteStream as createWriteStream3, mkdirSync as mkdirSync2 } from "node:fs";
38420
+ import { rm as rm4 } from "node:fs/promises";
38421
+ import path27 from "node:path";
37705
38422
  import { Readable as Readable2, Transform as Transform2 } from "node:stream";
37706
38423
  import { pipeline as pipeline3 } from "node:stream/promises";
37707
38424
  import { clearTimeout as clearTimeout2, setTimeout as setTimeout2 } from "node:timers";
@@ -37940,8 +38657,8 @@ async function resolveDesktopDownloadOrigins(options) {
37940
38657
  return mirrorElapsed === null ? ["github"] : ["github", "mirror"];
37941
38658
  }
37942
38659
  async function downloadAsset(asset, outputDir, progressFactory = createByteProgress, expectedChecksum, timeouts = {}) {
37943
- mkdirSync(outputDir, { recursive: true });
37944
- const outputPath = path23.join(outputDir, path23.basename(asset.name));
38660
+ mkdirSync2(outputDir, { recursive: true });
38661
+ const outputPath = path27.join(outputDir, path27.basename(asset.name));
37945
38662
  const idleTimeoutMs = timeouts.idleMs ?? DESKTOP_ASSET_IDLE_TIMEOUT_MS;
37946
38663
  const responseTimeoutMs = timeouts.responseMs ?? DESKTOP_ASSET_RESPONSE_TIMEOUT_MS;
37947
38664
  const failures = [];
@@ -37988,7 +38705,7 @@ async function downloadAsset(asset, outputDir, progressFactory = createByteProgr
37988
38705
  if (expectedChecksum && actualChecksum !== expectedChecksum.toLowerCase()) {
37989
38706
  progress.fail();
37990
38707
  progress = null;
37991
- await rm2(outputPath, { force: true });
38708
+ await rm4(outputPath, { force: true });
37992
38709
  failures.push(`Checksum mismatch for ${asset.name} from ${url}.`);
37993
38710
  continue;
37994
38711
  }
@@ -37997,7 +38714,7 @@ async function downloadAsset(asset, outputDir, progressFactory = createByteProgr
37997
38714
  } catch (error) {
37998
38715
  if (idleTimeout) clearTimeout2(idleTimeout);
37999
38716
  progress?.fail();
38000
- await rm2(outputPath, { force: true });
38717
+ await rm4(outputPath, { force: true });
38001
38718
  failures.push(`Failed to download ${asset.name} from ${url}: ${formatFetchError(error)}.`);
38002
38719
  }
38003
38720
  }
@@ -38009,51 +38726,8 @@ init_install2();
38009
38726
  init_install();
38010
38727
  init_version();
38011
38728
 
38012
- // src/commands/start-windows.ts
38013
- function powershellQuote(value) {
38014
- return `'${value.replaceAll("'", "''")}'`;
38015
- }
38016
- function buildWindowsZipExtractCommand(zipPath, outputDir) {
38017
- return {
38018
- command: "powershell.exe",
38019
- args: [
38020
- "-NoProfile",
38021
- "-NonInteractive",
38022
- "-ExecutionPolicy",
38023
- "Bypass",
38024
- "-Command",
38025
- `$ErrorActionPreference='Stop'; Expand-Archive -LiteralPath ${powershellQuote(zipPath)} -DestinationPath ${powershellQuote(outputDir)} -Force`
38026
- ]
38027
- };
38028
- }
38029
-
38030
- // src/commands/start.ts
38031
- var DESKTOP_UPDATE_QUIT_ARG = "--rudder-update-quit";
38032
- var DESKTOP_UPDATE_FORCE_ARG = "--rudder-update-force";
38033
- var STABLE_SEMVER_RE = /^[0-9]+\.[0-9]+\.[0-9]+$/;
38034
- var CANARY_SEMVER_RE = /^[0-9]+\.[0-9]+\.[0-9]+-canary\.[0-9]+$/;
38035
- var CLI_REGISTRY_LATEST_URL = "https://registry.npmjs.org/@rudderhq%2fcli/latest";
38036
- var LEGACY_UPDATE_QUIT_GRACE_MS = 1e4;
38037
- var UPDATE_QUIT_FORCE_DELAY_MS = 1e3;
38038
- var DESKTOP_APP_NAME = "Rudder";
38039
- var DESKTOP_METADATA_FILE = ".rudder-desktop-install.json";
38040
- var DESKTOP_CHECKSUM_ASSET_NAME = "SHASUMS256.txt";
38041
- var DESKTOP_ASSET_CACHE_DIR = "desktop-assets";
38042
- var DEFAULT_DESKTOP_ASSET_CACHE_MAX_ENTRIES = 2;
38043
- var DEFAULT_DESKTOP_ASSET_CACHE_MAX_AGE_MS = 14 * 24 * 60 * 60 * 1e3;
38044
- var DEFAULT_DESKTOP_ASSET_CACHE_MAX_BYTES = 768 * 1024 * 1024;
38045
- var DEFAULT_DESKTOP_ASSET_CACHE_KEEP_PREVIOUS = 1;
38046
- var DESKTOP_INSTALL_LOCK_TIMEOUT_MS = 60 * 60 * 1e3;
38047
- var DESKTOP_INSTALL_LOCK_POLL_MS = 250;
38048
- var DESKTOP_RUNTIME_PREPARE_TIMEOUT_MS = 9e4;
38049
- async function waitForDesktopRuntimeSmokeEvidence(envName) {
38050
- if (process.env.RUDDER_DESKTOP_SMOKE_AUTO_UPDATE_PUBLIC !== "1") return;
38051
- const value = Number(process.env[envName]);
38052
- if (!Number.isFinite(value) || value <= 0) return;
38053
- await delay2(Math.min(value, 1e4));
38054
- }
38055
- var DEFAULT_GITHUB_API_BASE_URL = "https://api.github.com";
38056
- var DEFAULT_GITHUB_DOWNLOAD_BASE_URL = "https://github.com";
38729
+ // src/commands/desktop-update-progress.ts
38730
+ import { clearTimeout as clearTimeout3, setTimeout as setTimeout3 } from "node:timers";
38057
38731
  function normalizeProgressTotal(totalBytes) {
38058
38732
  return typeof totalBytes === "number" && Number.isFinite(totalBytes) && totalBytes > 0 ? totalBytes : null;
38059
38733
  }
@@ -38201,6 +38875,52 @@ function createDesktopApplySignalController(input = process.stdin) {
38201
38875
  close: cleanup
38202
38876
  };
38203
38877
  }
38878
+
38879
+ // src/commands/start-windows.ts
38880
+ function powershellQuote(value) {
38881
+ return `'${value.replaceAll("'", "''")}'`;
38882
+ }
38883
+ function buildWindowsZipExtractCommand(zipPath, outputDir) {
38884
+ return {
38885
+ command: "powershell.exe",
38886
+ args: [
38887
+ "-NoProfile",
38888
+ "-NonInteractive",
38889
+ "-ExecutionPolicy",
38890
+ "Bypass",
38891
+ "-Command",
38892
+ `$ErrorActionPreference='Stop'; Expand-Archive -LiteralPath ${powershellQuote(zipPath)} -DestinationPath ${powershellQuote(outputDir)} -Force`
38893
+ ]
38894
+ };
38895
+ }
38896
+
38897
+ // src/commands/start.ts
38898
+ var DESKTOP_UPDATE_QUIT_ARG = "--rudder-update-quit";
38899
+ var DESKTOP_UPDATE_FORCE_ARG = "--rudder-update-force";
38900
+ var STABLE_SEMVER_RE = /^[0-9]+\.[0-9]+\.[0-9]+$/;
38901
+ var CANARY_SEMVER_RE = /^[0-9]+\.[0-9]+\.[0-9]+-canary\.[0-9]+$/;
38902
+ var CLI_REGISTRY_LATEST_URL = "https://registry.npmjs.org/@rudderhq%2fcli/latest";
38903
+ var LEGACY_UPDATE_QUIT_GRACE_MS = 1e4;
38904
+ var UPDATE_QUIT_FORCE_DELAY_MS = 1e3;
38905
+ var DESKTOP_APP_NAME = "Rudder";
38906
+ var DESKTOP_METADATA_FILE = ".rudder-desktop-install.json";
38907
+ var DESKTOP_CHECKSUM_ASSET_NAME = "SHASUMS256.txt";
38908
+ var DESKTOP_ASSET_CACHE_DIR = "desktop-assets";
38909
+ var DEFAULT_DESKTOP_ASSET_CACHE_MAX_ENTRIES = 2;
38910
+ var DEFAULT_DESKTOP_ASSET_CACHE_MAX_AGE_MS = 14 * 24 * 60 * 60 * 1e3;
38911
+ var DEFAULT_DESKTOP_ASSET_CACHE_MAX_BYTES = 768 * 1024 * 1024;
38912
+ var DEFAULT_DESKTOP_ASSET_CACHE_KEEP_PREVIOUS = 1;
38913
+ var DESKTOP_INSTALL_LOCK_TIMEOUT_MS = 60 * 60 * 1e3;
38914
+ var DESKTOP_INSTALL_LOCK_POLL_MS = 250;
38915
+ var DESKTOP_RUNTIME_PREPARE_TIMEOUT_MS = 9e4;
38916
+ async function waitForDesktopRuntimeSmokeEvidence(envName) {
38917
+ if (process.env.RUDDER_DESKTOP_SMOKE_AUTO_UPDATE_PUBLIC !== "1") return;
38918
+ const value = Number(process.env[envName]);
38919
+ if (!Number.isFinite(value) || value <= 0) return;
38920
+ await delay3(Math.min(value, 1e4));
38921
+ }
38922
+ var DEFAULT_GITHUB_API_BASE_URL = "https://api.github.com";
38923
+ var DEFAULT_GITHUB_DOWNLOAD_BASE_URL = "https://github.com";
38204
38924
  function resolveCurrentCliVersion(env = process.env) {
38205
38925
  const version = resolveCliVersion(import.meta.url, env);
38206
38926
  return version === "0.0.0" ? "latest" : version;
@@ -38224,7 +38944,7 @@ function compareStableSemver(a, b) {
38224
38944
  }
38225
38945
  async function fetchLatestCliVersion() {
38226
38946
  const controller = new AbortController();
38227
- const timeout = setTimeout3(() => controller.abort(), 2e3);
38947
+ const timeout = setTimeout4(() => controller.abort(), 2e3);
38228
38948
  try {
38229
38949
  const response = await fetch(CLI_REGISTRY_LATEST_URL, {
38230
38950
  signal: controller.signal,
@@ -38236,7 +38956,7 @@ async function fetchLatestCliVersion() {
38236
38956
  } catch {
38237
38957
  return null;
38238
38958
  } finally {
38239
- clearTimeout3(timeout);
38959
+ clearTimeout4(timeout);
38240
38960
  }
38241
38961
  }
38242
38962
  async function getCliUpdateNotice(currentVersion) {
@@ -38276,39 +38996,39 @@ function resolveDesktopAssetTarget(platform = process.platform, arch = process.a
38276
38996
  }
38277
38997
  throw new Error(`Rudder Desktop does not publish portable assets for ${platform}.`);
38278
38998
  }
38279
- function resolveDefaultDesktopInstallRoot(target, env = process.env, homeDir = homedir()) {
38280
- if (target.platform === "macos") return path24.join(homeDir, "Applications");
38999
+ function resolveDefaultDesktopInstallRoot(target, env = process.env, homeDir = homedir2()) {
39000
+ if (target.platform === "macos") return path28.join(homeDir, "Applications");
38281
39001
  if (target.platform === "windows") {
38282
- const localAppData = env.LOCALAPPDATA?.trim() || path24.join(homeDir, "AppData", "Local");
38283
- return path24.join(localAppData, "Programs", DESKTOP_APP_NAME);
39002
+ const localAppData = env.LOCALAPPDATA?.trim() || path28.join(homeDir, "AppData", "Local");
39003
+ return path28.join(localAppData, "Programs", DESKTOP_APP_NAME);
38284
39004
  }
38285
- return path24.join(homeDir, ".local", "share", "rudder");
39005
+ return path28.join(homeDir, ".local", "share", "rudder");
38286
39006
  }
38287
39007
  function resolveDesktopInstallPaths(target, installRoot) {
38288
- const root = path24.resolve(installRoot);
39008
+ const root = path28.resolve(installRoot);
38289
39009
  if (target.platform === "macos") {
38290
- const appPath2 = path24.join(root, `${DESKTOP_APP_NAME}.app`);
39010
+ const appPath2 = path28.join(root, `${DESKTOP_APP_NAME}.app`);
38291
39011
  return {
38292
39012
  installRoot: root,
38293
39013
  appPath: appPath2,
38294
- executablePath: path24.join(appPath2, "Contents", "MacOS", DESKTOP_APP_NAME),
38295
- metadataPath: path24.join(root, DESKTOP_METADATA_FILE)
39014
+ executablePath: path28.join(appPath2, "Contents", "MacOS", DESKTOP_APP_NAME),
39015
+ metadataPath: path28.join(root, DESKTOP_METADATA_FILE)
38296
39016
  };
38297
39017
  }
38298
39018
  if (target.platform === "windows") {
38299
39019
  return {
38300
39020
  installRoot: root,
38301
39021
  appPath: root,
38302
- executablePath: path24.join(root, `${DESKTOP_APP_NAME}.exe`),
38303
- metadataPath: path24.join(root, DESKTOP_METADATA_FILE)
39022
+ executablePath: path28.join(root, `${DESKTOP_APP_NAME}.exe`),
39023
+ metadataPath: path28.join(root, DESKTOP_METADATA_FILE)
38304
39024
  };
38305
39025
  }
38306
- const appPath = path24.join(root, `${DESKTOP_APP_NAME}.AppImage`);
39026
+ const appPath = path28.join(root, `${DESKTOP_APP_NAME}.AppImage`);
38307
39027
  return {
38308
39028
  installRoot: root,
38309
39029
  appPath,
38310
39030
  executablePath: appPath,
38311
- metadataPath: path24.join(root, DESKTOP_METADATA_FILE)
39031
+ metadataPath: path28.join(root, DESKTOP_METADATA_FILE)
38312
39032
  };
38313
39033
  }
38314
39034
  function normalizeAssetName(name) {
@@ -38410,11 +39130,11 @@ function selectChecksumAsset(assets) {
38410
39130
  }
38411
39131
  async function fetchWithTimeout2(url, init, timeoutMs) {
38412
39132
  const controller = new AbortController();
38413
- const timeout = setTimeout3(() => controller.abort(), timeoutMs);
39133
+ const timeout = setTimeout4(() => controller.abort(), timeoutMs);
38414
39134
  try {
38415
39135
  return await fetch(url, { ...init, signal: controller.signal });
38416
39136
  } finally {
38417
- clearTimeout3(timeout);
39137
+ clearTimeout4(timeout);
38418
39138
  }
38419
39139
  }
38420
39140
  function githubApiHeaders() {
@@ -38492,20 +39212,20 @@ function buildGithubReleaseAsset(repo, tag, assetName, downloadBaseUrl) {
38492
39212
  }
38493
39213
  function checksumForFile(filePath) {
38494
39214
  const hash = createHash5("sha256");
38495
- hash.update(readFileSync2(filePath));
39215
+ hash.update(readFileSync3(filePath));
38496
39216
  return hash.digest("hex");
38497
39217
  }
38498
39218
  function resolveAssetChecksum(checksums, assetName) {
38499
- const expected = checksums.get(path24.basename(assetName));
39219
+ const expected = checksums.get(path28.basename(assetName));
38500
39220
  if (!expected) {
38501
- throw new Error(`Desktop release checksums do not include ${path24.basename(assetName)}.`);
39221
+ throw new Error(`Desktop release checksums do not include ${path28.basename(assetName)}.`);
38502
39222
  }
38503
39223
  return expected;
38504
39224
  }
38505
39225
  function assertChecksumMatch(filePath, expected) {
38506
39226
  const actual = checksumForFile(filePath);
38507
39227
  if (actual !== expected.toLowerCase()) {
38508
- throw new Error(`Checksum mismatch for ${path24.basename(filePath)}.`);
39228
+ throw new Error(`Checksum mismatch for ${path28.basename(filePath)}.`);
38509
39229
  }
38510
39230
  return actual;
38511
39231
  }
@@ -38514,7 +39234,7 @@ async function downloadChecksums(checksumAsset, outputDir, progressFactory = cre
38514
39234
  throw new Error("Desktop release is missing SHASUMS256.txt.");
38515
39235
  }
38516
39236
  const checksumPath = await downloadAsset(checksumAsset, outputDir, progressFactory);
38517
- return parseChecksumFile(readFileSync2(checksumPath, "utf8"));
39237
+ return parseChecksumFile(readFileSync3(checksumPath, "utf8"));
38518
39238
  }
38519
39239
  function normalizeDesktopAssetChecksum(checksum) {
38520
39240
  const normalized = checksum.trim().toLowerCase();
@@ -38524,10 +39244,10 @@ function normalizeDesktopAssetChecksum(checksum) {
38524
39244
  return normalized;
38525
39245
  }
38526
39246
  function resolveDesktopAssetCacheDir(assetChecksum, homeDir = resolveRudderHomeDir()) {
38527
- return path24.join(homeDir, DESKTOP_ASSET_CACHE_DIR, normalizeDesktopAssetChecksum(assetChecksum));
39247
+ return path28.join(homeDir, DESKTOP_ASSET_CACHE_DIR, normalizeDesktopAssetChecksum(assetChecksum));
38528
39248
  }
38529
39249
  function resolveDesktopCachedAssetPath(assetName, assetChecksum, homeDir = resolveRudderHomeDir()) {
38530
- return path24.join(resolveDesktopAssetCacheDir(assetChecksum, homeDir), path24.basename(assetName));
39250
+ return path28.join(resolveDesktopAssetCacheDir(assetChecksum, homeDir), path28.basename(assetName));
38531
39251
  }
38532
39252
  async function pruneDesktopAssetCache(options = {}) {
38533
39253
  const homeDir = options.homeDir ?? resolveRudderHomeDir();
@@ -38548,7 +39268,7 @@ async function pruneDesktopAssetCache(options = {}) {
38548
39268
  const warnings = [];
38549
39269
  for (const entry of deletions) {
38550
39270
  try {
38551
- await rm3(entry.cacheDir, { recursive: true, force: true });
39271
+ await rm5(entry.cacheDir, { recursive: true, force: true });
38552
39272
  deleted.push({
38553
39273
  cacheDir: entry.cacheDir,
38554
39274
  checksum: entry.checksum,
@@ -38573,7 +39293,7 @@ async function maybePruneDesktopAssetCache(options) {
38573
39293
  return result.deleted.length > 0 || result.warnings.length > 0 ? result : null;
38574
39294
  }
38575
39295
  async function scanDesktopAssetCacheEntries(homeDir) {
38576
- const cacheRoot = path24.join(homeDir, DESKTOP_ASSET_CACHE_DIR);
39296
+ const cacheRoot = path28.join(homeDir, DESKTOP_ASSET_CACHE_DIR);
38577
39297
  const dirents = await readdir3(cacheRoot, { withFileTypes: true }).catch(() => null);
38578
39298
  if (!dirents) return [];
38579
39299
  const entries = [];
@@ -38585,7 +39305,7 @@ async function scanDesktopAssetCacheEntries(homeDir) {
38585
39305
  } catch {
38586
39306
  continue;
38587
39307
  }
38588
- const cacheDir = path24.join(cacheRoot, dirent.name);
39308
+ const cacheDir = path28.join(cacheRoot, dirent.name);
38589
39309
  const stats = await desktopCacheDirectoryStats(cacheDir);
38590
39310
  entries.push({
38591
39311
  cacheDir,
@@ -38609,7 +39329,7 @@ async function desktopCacheDirectoryStats(targetPath) {
38609
39329
  let lastUsedAtMs = Number(fallbackStat?.mtimeMs ?? 0);
38610
39330
  for (const dirent of dirents) {
38611
39331
  if (dirent.isSymbolicLink()) continue;
38612
- const entryPath = path24.join(targetPath, dirent.name);
39332
+ const entryPath = path28.join(targetPath, dirent.name);
38613
39333
  const entryStat = await stat4(entryPath).catch(() => null);
38614
39334
  if (!entryStat) continue;
38615
39335
  lastUsedAtMs = Math.max(lastUsedAtMs, Number(entryStat.mtimeMs ?? 0));
@@ -38683,21 +39403,21 @@ async function downloadDesktopAssetWithCache(asset, expectedChecksum, options =
38683
39403
  await touchDesktopCachedAsset(cachePath);
38684
39404
  return { path: cachePath, checksum, cacheStatus: "hit" };
38685
39405
  } catch {
38686
- await rm3(cachePath, { force: true });
39406
+ await rm5(cachePath, { force: true });
38687
39407
  }
38688
39408
  }
38689
- const outputDir = options.outputDir ?? await mkdtemp2(path24.join(tmpdir(), "rudder-desktop-installer."));
39409
+ const outputDir = options.outputDir ?? await mkdtemp2(path28.join(tmpdir2(), "rudder-desktop-installer."));
38690
39410
  const removeOutputDir = options.outputDir ? false : true;
38691
39411
  try {
38692
39412
  const downloadedPath = await downloadAsset(asset, outputDir, options.progressFactory, normalizedChecksum);
38693
39413
  const checksum = assertChecksumMatch(downloadedPath, normalizedChecksum);
38694
- await mkdir3(path24.dirname(cachePath), { recursive: true });
38695
- if (path24.resolve(downloadedPath) !== path24.resolve(cachePath)) {
39414
+ await mkdir4(path28.dirname(cachePath), { recursive: true });
39415
+ if (path28.resolve(downloadedPath) !== path28.resolve(cachePath)) {
38696
39416
  await copyFile(downloadedPath, cachePath);
38697
39417
  }
38698
39418
  return { path: cachePath, checksum, cacheStatus: "miss" };
38699
39419
  } finally {
38700
- if (removeOutputDir) await rm3(outputDir, { recursive: true, force: true });
39420
+ if (removeOutputDir) await rm5(outputDir, { recursive: true, force: true });
38701
39421
  }
38702
39422
  }
38703
39423
  async function pathExists2(targetPath) {
@@ -38709,12 +39429,12 @@ async function pathExists2(targetPath) {
38709
39429
  }
38710
39430
  }
38711
39431
  function resolveDesktopInstallLockPath(paths) {
38712
- const installRootHash = createHash5("sha256").update(path24.resolve(paths.installRoot)).digest("hex").slice(0, 16);
38713
- return path24.join(path24.dirname(paths.appPath), `.rudder-desktop-install-${installRootHash}.lock`);
39432
+ const installRootHash = createHash5("sha256").update(path28.resolve(paths.installRoot)).digest("hex").slice(0, 16);
39433
+ return path28.join(path28.dirname(paths.appPath), `.rudder-desktop-install-${installRootHash}.lock`);
38714
39434
  }
38715
39435
  async function readDesktopInstallLock(lockPath) {
38716
39436
  try {
38717
- const parsed = JSON.parse(await readFile6(lockPath, "utf8"));
39437
+ const parsed = JSON.parse(await readFile8(lockPath, "utf8"));
38718
39438
  if (typeof parsed.pid !== "number" || !Number.isInteger(parsed.pid) || parsed.pid <= 0 || typeof parsed.lockId !== "string" || typeof parsed.installRoot !== "string" || typeof parsed.createdAt !== "string") {
38719
39439
  return null;
38720
39440
  }
@@ -38730,20 +39450,20 @@ async function readDesktopInstallLock(lockPath) {
38730
39450
  }
38731
39451
  async function withDesktopInstallLock(paths, fn, options = {}) {
38732
39452
  const lockPath = resolveDesktopInstallLockPath(paths);
38733
- const lockDir = path24.dirname(lockPath);
39453
+ const lockDir = path28.dirname(lockPath);
38734
39454
  const timeoutMs = options.timeoutMs ?? DESKTOP_INSTALL_LOCK_TIMEOUT_MS;
38735
39455
  const pollMs = options.pollMs ?? DESKTOP_INSTALL_LOCK_POLL_MS;
38736
39456
  const startedAt = Date.now();
38737
39457
  const payload = {
38738
- lockId: randomUUID2(),
39458
+ lockId: randomUUID3(),
38739
39459
  pid: process.pid,
38740
- installRoot: path24.resolve(paths.installRoot),
39460
+ installRoot: path28.resolve(paths.installRoot),
38741
39461
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
38742
39462
  };
38743
- await mkdir3(lockDir, { recursive: true });
39463
+ await mkdir4(lockDir, { recursive: true });
38744
39464
  while (true) {
38745
39465
  try {
38746
- await writeFile3(lockPath, `${JSON.stringify(payload, null, 2)}
39466
+ await writeFile4(lockPath, `${JSON.stringify(payload, null, 2)}
38747
39467
  `, { encoding: "utf8", flag: "wx" });
38748
39468
  break;
38749
39469
  } catch (error) {
@@ -38752,7 +39472,7 @@ async function withDesktopInstallLock(paths, fn, options = {}) {
38752
39472
  const existing = await readDesktopInstallLock(lockPath);
38753
39473
  const stale = !existing || !processExists(existing.pid);
38754
39474
  if (stale) {
38755
- await rm3(lockPath, { force: true });
39475
+ await rm5(lockPath, { force: true });
38756
39476
  continue;
38757
39477
  }
38758
39478
  if (Date.now() - startedAt >= timeoutMs) {
@@ -38760,7 +39480,7 @@ async function withDesktopInstallLock(paths, fn, options = {}) {
38760
39480
  `Timed out waiting for Rudder Desktop install lock for ${paths.appPath}. Held by pid ${existing.pid} for ${existing.installRoot}.`
38761
39481
  );
38762
39482
  }
38763
- await delay2(pollMs);
39483
+ await delay3(pollMs);
38764
39484
  }
38765
39485
  }
38766
39486
  try {
@@ -38768,12 +39488,12 @@ async function withDesktopInstallLock(paths, fn, options = {}) {
38768
39488
  } finally {
38769
39489
  const existing = await readDesktopInstallLock(lockPath);
38770
39490
  if (existing?.lockId === payload.lockId) {
38771
- await rm3(lockPath, { force: true });
39491
+ await rm5(lockPath, { force: true });
38772
39492
  }
38773
39493
  }
38774
39494
  }
38775
39495
  function runChecked(command, args, options = {}) {
38776
- const result = spawnSync4(command, args, {
39496
+ const result = spawnSync5(command, args, {
38777
39497
  encoding: "utf8",
38778
39498
  stdio: ["ignore", "pipe", "pipe"],
38779
39499
  ...options
@@ -38796,8 +39516,8 @@ function isSuccessfulRobocopyExitCode(status) {
38796
39516
  return typeof status === "number" && status >= 0 && status <= 7;
38797
39517
  }
38798
39518
  async function extractZip(zipPath, outputDir, target) {
38799
- await rm3(outputDir, { recursive: true, force: true });
38800
- await mkdir3(outputDir, { recursive: true });
39519
+ await rm5(outputDir, { recursive: true, force: true });
39520
+ await mkdir4(outputDir, { recursive: true });
38801
39521
  if (target.platform === "macos") {
38802
39522
  runChecked("ditto", ["-x", "-k", zipPath, outputDir]);
38803
39523
  return;
@@ -38813,7 +39533,7 @@ async function findPath(root, predicate, maxDepth = 5) {
38813
39533
  async function visit(dir, depth) {
38814
39534
  const entries = await readdir3(dir, { withFileTypes: true });
38815
39535
  for (const entry of entries) {
38816
- const fullPath = path24.join(dir, entry.name);
39536
+ const fullPath = path28.join(dir, entry.name);
38817
39537
  if (predicate(fullPath, entry.isDirectory())) return fullPath;
38818
39538
  if (entry.isDirectory() && depth < maxDepth) {
38819
39539
  const nested = await visit(fullPath, depth + 1);
@@ -38825,22 +39545,22 @@ async function findPath(root, predicate, maxDepth = 5) {
38825
39545
  return await visit(root, 0);
38826
39546
  }
38827
39547
  async function findMacApp(extractDir) {
38828
- const direct = path24.join(extractDir, `${DESKTOP_APP_NAME}.app`);
39548
+ const direct = path28.join(extractDir, `${DESKTOP_APP_NAME}.app`);
38829
39549
  if (await pathExists2(direct)) return direct;
38830
- const found = await findPath(extractDir, (filePath, isDirectory) => isDirectory && path24.basename(filePath) === `${DESKTOP_APP_NAME}.app`);
39550
+ const found = await findPath(extractDir, (filePath, isDirectory) => isDirectory && path28.basename(filePath) === `${DESKTOP_APP_NAME}.app`);
38831
39551
  if (!found) throw new Error(`Portable macOS archive did not contain ${DESKTOP_APP_NAME}.app.`);
38832
39552
  return found;
38833
39553
  }
38834
39554
  async function findWindowsAppDir(extractDir) {
38835
- const direct = path24.join(extractDir, `${DESKTOP_APP_NAME}.exe`);
39555
+ const direct = path28.join(extractDir, `${DESKTOP_APP_NAME}.exe`);
38836
39556
  if (await pathExists2(direct)) return extractDir;
38837
- const executable = await findPath(extractDir, (filePath, isDirectory) => !isDirectory && path24.basename(filePath).toLowerCase() === `${DESKTOP_APP_NAME.toLowerCase()}.exe`);
39557
+ const executable = await findPath(extractDir, (filePath, isDirectory) => !isDirectory && path28.basename(filePath).toLowerCase() === `${DESKTOP_APP_NAME.toLowerCase()}.exe`);
38838
39558
  if (!executable) throw new Error(`Portable Windows archive did not contain ${DESKTOP_APP_NAME}.exe.`);
38839
- return path24.dirname(executable);
39559
+ return path28.dirname(executable);
38840
39560
  }
38841
39561
  async function readInstallMetadata(metadataPath) {
38842
39562
  try {
38843
- const parsed = JSON.parse(await readFile6(metadataPath, "utf8"));
39563
+ const parsed = JSON.parse(await readFile8(metadataPath, "utf8"));
38844
39564
  if (parsed.version !== 1) return null;
38845
39565
  return parsed;
38846
39566
  } catch {
@@ -38854,7 +39574,7 @@ function isInstalledDesktopCurrent(metadata, releaseTag, assetName, assetChecksu
38854
39574
  }
38855
39575
  function forceQuitDesktopProcess(pid, target) {
38856
39576
  if (target.platform === "windows") {
38857
- spawnSync4("taskkill.exe", ["/PID", String(pid), "/T", "/F"], { stdio: "ignore" });
39577
+ spawnSync5("taskkill.exe", ["/PID", String(pid), "/T", "/F"], { stdio: "ignore" });
38858
39578
  return;
38859
39579
  }
38860
39580
  try {
@@ -38862,15 +39582,15 @@ function forceQuitDesktopProcess(pid, target) {
38862
39582
  } catch {
38863
39583
  }
38864
39584
  }
38865
- function quotePowerShellString(value) {
39585
+ function quotePowerShellString2(value) {
38866
39586
  return `'${value.replaceAll("'", "''")}'`;
38867
39587
  }
38868
39588
  function findDesktopExecutablePids(executablePath, target) {
38869
39589
  if (target.platform === "windows") {
38870
- const result2 = spawnSync4("powershell.exe", [
39590
+ const result2 = spawnSync5("powershell.exe", [
38871
39591
  "-NoProfile",
38872
39592
  "-Command",
38873
- `Get-CimInstance Win32_Process | Where-Object { $_.ExecutablePath -eq ${quotePowerShellString(executablePath)} } | Select-Object -ExpandProperty ProcessId`
39593
+ `Get-CimInstance Win32_Process | Where-Object { $_.ExecutablePath -eq ${quotePowerShellString2(executablePath)} } | Select-Object -ExpandProperty ProcessId`
38874
39594
  ], {
38875
39595
  encoding: "utf8",
38876
39596
  stdio: ["ignore", "pipe", "ignore"]
@@ -38878,7 +39598,7 @@ function findDesktopExecutablePids(executablePath, target) {
38878
39598
  if (result2.status !== 0) return [];
38879
39599
  return result2.stdout.split(/\r?\n/).map((line) => Number.parseInt(line.trim(), 10)).filter((pid) => Number.isInteger(pid) && pid > 0 && pid !== process.pid);
38880
39600
  }
38881
- const result = spawnSync4("ps", ["-eo", "pid=,args="], {
39601
+ const result = spawnSync5("ps", ["-eo", "pid=,args="], {
38882
39602
  encoding: "utf8",
38883
39603
  stdio: ["ignore", "pipe", "ignore"]
38884
39604
  });
@@ -38901,16 +39621,16 @@ async function waitForUpdateQuitResponse(responsePath, timeoutMs = 8e3) {
38901
39621
  const startedAt = Date.now();
38902
39622
  while (Date.now() - startedAt < timeoutMs) {
38903
39623
  if (await pathExists2(responsePath)) {
38904
- return JSON.parse(await readFile6(responsePath, "utf8"));
39624
+ return JSON.parse(await readFile8(responsePath, "utf8"));
38905
39625
  }
38906
- await delay2(200);
39626
+ await delay3(200);
38907
39627
  }
38908
39628
  return null;
38909
39629
  }
38910
39630
  async function requestDesktopQuit(executablePath, target, options = {}) {
38911
39631
  if (!await pathExists2(executablePath)) return { ok: true, status: "not_running" };
38912
- const responsePath = path24.join(tmpdir(), `rudder-update-quit-${process.pid}-${Date.now()}.json`);
38913
- const result = spawnSync4(executablePath, [
39632
+ const responsePath = path28.join(tmpdir2(), `rudder-update-quit-${process.pid}-${Date.now()}.json`);
39633
+ const result = spawnSync5(executablePath, [
38914
39634
  `${DESKTOP_UPDATE_QUIT_ARG}=${responsePath}`,
38915
39635
  ...options.forceUpdate ? [DESKTOP_UPDATE_FORCE_ARG] : []
38916
39636
  ], {
@@ -38924,7 +39644,7 @@ async function requestDesktopQuit(executablePath, target, options = {}) {
38924
39644
  try {
38925
39645
  return await waitForUpdateQuitResponse(responsePath, options.responseTimeoutMs);
38926
39646
  } finally {
38927
- await rm3(responsePath, { force: true });
39647
+ await rm5(responsePath, { force: true });
38928
39648
  }
38929
39649
  }
38930
39650
  function processExists(pid) {
@@ -38947,7 +39667,7 @@ async function waitForProcessExit(pid, timeoutMs = 2e4, intervalMs = 250) {
38947
39667
  const startedAt = Date.now();
38948
39668
  while (Date.now() - startedAt < timeoutMs) {
38949
39669
  if (!processExists(pid)) return true;
38950
- await delay2(intervalMs);
39670
+ await delay3(intervalMs);
38951
39671
  }
38952
39672
  return !processExists(pid);
38953
39673
  }
@@ -38960,11 +39680,11 @@ async function waitForProcessesExit(pids, waitForExit) {
38960
39680
  async function removePathWithRetry(targetPath, attempts = 5) {
38961
39681
  for (let attempt = 0; attempt < attempts; attempt += 1) {
38962
39682
  try {
38963
- await rm3(targetPath, { recursive: true, force: true });
39683
+ await rm5(targetPath, { recursive: true, force: true });
38964
39684
  if (!await pathExists2(targetPath)) return true;
38965
39685
  } catch {
38966
39686
  }
38967
- await delay2(500);
39687
+ await delay3(500);
38968
39688
  }
38969
39689
  return false;
38970
39690
  }
@@ -38974,7 +39694,7 @@ async function prepareForDesktopReplace(paths, target, options = {}) {
38974
39694
  const findPids = options.findDesktopExecutablePids ?? findDesktopExecutablePids;
38975
39695
  async function forceQuitPidAndConfirm(pid) {
38976
39696
  forceQuitPid(pid, target);
38977
- await delay2(options.updateQuitForceDelayMs ?? UPDATE_QUIT_FORCE_DELAY_MS);
39697
+ await delay3(options.updateQuitForceDelayMs ?? UPDATE_QUIT_FORCE_DELAY_MS);
38978
39698
  if (!await waitForExit(pid)) {
38979
39699
  throw new Error(`Rudder Desktop process ${pid} did not exit after force-quit fallback. Close Rudder and rerun start.`);
38980
39700
  }
@@ -38984,7 +39704,7 @@ async function prepareForDesktopReplace(paths, target, options = {}) {
38984
39704
  for (const pid of uniquePids) {
38985
39705
  forceQuitPid(pid, target);
38986
39706
  }
38987
- await delay2(options.updateQuitForceDelayMs ?? UPDATE_QUIT_FORCE_DELAY_MS);
39707
+ await delay3(options.updateQuitForceDelayMs ?? UPDATE_QUIT_FORCE_DELAY_MS);
38988
39708
  if (!await waitForProcessesExit(uniquePids, waitForExit)) {
38989
39709
  throw new Error(`Rudder Desktop process${uniquePids.length === 1 ? "" : "es"} ${uniquePids.join(", ")} did not exit after force-quit fallback. Close Rudder and rerun start.`);
38990
39710
  }
@@ -39006,7 +39726,7 @@ async function prepareForDesktopReplace(paths, target, options = {}) {
39006
39726
  );
39007
39727
  options.onActiveRunsWaiting?.(quitResponse.totalRuns);
39008
39728
  const pollIntervalMs = options.activeRunPollIntervalMs ?? 15e3;
39009
- forceUpdate = options.waitForForceUpdate ? await options.waitForForceUpdate(pollIntervalMs) : (await delay2(pollIntervalMs), false);
39729
+ forceUpdate = options.waitForForceUpdate ? await options.waitForForceUpdate(pollIntervalMs) : (await delay3(pollIntervalMs), false);
39010
39730
  quitResponse = await requestQuit();
39011
39731
  }
39012
39732
  if (quitResponse && !quitResponse.ok && quitResponse.status === "active_runs") {
@@ -39034,7 +39754,7 @@ async function prepareForDesktopReplace(paths, target, options = {}) {
39034
39754
  p15.log.warn(
39035
39755
  `Existing Rudder Desktop acknowledged update quit without a process id; waiting ${Math.ceil(graceMs / 1e3)}s before replacement.`
39036
39756
  );
39037
- await delay2(graceMs);
39757
+ await delay3(graceMs);
39038
39758
  if (managedExecutablePids.length > 0 && !await waitForProcessesExit(managedExecutablePids, waitForExit)) {
39039
39759
  p15.log.warn(
39040
39760
  `Existing Rudder Desktop did not exit after acknowledging update quit; attempting path-scoped force-quit for process${managedExecutablePids.length === 1 ? "" : "es"} ${managedExecutablePids.join(", ")}.`
@@ -39051,7 +39771,7 @@ async function prepareForDesktopReplace(paths, target, options = {}) {
39051
39771
  throw new Error("Existing Rudder Desktop did not respond to the update quit request. Close Rudder and rerun start.");
39052
39772
  }
39053
39773
  } else {
39054
- await delay2(options.updateQuitForceDelayMs ?? UPDATE_QUIT_FORCE_DELAY_MS);
39774
+ await delay3(options.updateQuitForceDelayMs ?? UPDATE_QUIT_FORCE_DELAY_MS);
39055
39775
  }
39056
39776
  }
39057
39777
  const replacePath = target.platform === "windows" ? paths.installRoot : paths.appPath;
@@ -39068,13 +39788,13 @@ async function prepareForDesktopReplace(paths, target, options = {}) {
39068
39788
  throw new Error(`Failed to replace existing Rudder Desktop at ${replacePath}. Close Rudder and rerun start.`);
39069
39789
  }
39070
39790
  async function installPortableDesktop(installerPath, paths, target) {
39071
- await mkdir3(paths.installRoot, { recursive: true });
39791
+ await mkdir4(paths.installRoot, { recursive: true });
39072
39792
  if (target.platform === "linux") {
39073
39793
  await copyFile(installerPath, paths.appPath);
39074
39794
  await chmod2(paths.appPath, 493);
39075
39795
  return;
39076
39796
  }
39077
- const extractDir = await mkdtemp2(path24.join(tmpdir(), "rudder-desktop-extract."));
39797
+ const extractDir = await mkdtemp2(path28.join(tmpdir2(), "rudder-desktop-extract."));
39078
39798
  try {
39079
39799
  await extractZip(installerPath, extractDir, target);
39080
39800
  if (target.platform === "macos") {
@@ -39083,17 +39803,17 @@ async function installPortableDesktop(installerPath, paths, target) {
39083
39803
  return;
39084
39804
  }
39085
39805
  const appSource = await findWindowsAppDir(extractDir);
39086
- await mkdir3(path24.dirname(paths.installRoot), { recursive: true });
39806
+ await mkdir4(path28.dirname(paths.installRoot), { recursive: true });
39087
39807
  await copyPortableAppBundle(appSource, paths.installRoot);
39088
39808
  } finally {
39089
- await rm3(extractDir, { recursive: true, force: true });
39809
+ await rm5(extractDir, { recursive: true, force: true });
39090
39810
  }
39091
39811
  }
39092
39812
  async function copyPortableAppBundle(sourcePath, destinationPath) {
39093
39813
  if (process.platform === "win32") {
39094
- await mkdir3(destinationPath, { recursive: true });
39814
+ await mkdir4(destinationPath, { recursive: true });
39095
39815
  const command = buildWindowsRobocopyMirrorCommand(sourcePath, destinationPath);
39096
- const result = spawnSync4(command.command, command.args, {
39816
+ const result = spawnSync5(command.command, command.args, {
39097
39817
  encoding: "utf8",
39098
39818
  stdio: ["ignore", "pipe", "pipe"]
39099
39819
  });
@@ -39104,7 +39824,7 @@ async function copyPortableAppBundle(sourcePath, destinationPath) {
39104
39824
  }
39105
39825
  async function removeMacQuarantine(paths, target) {
39106
39826
  if (target.platform !== "macos") return;
39107
- const result = spawnSync4("xattr", ["-dr", "com.apple.quarantine", paths.appPath], { stdio: "ignore" });
39827
+ const result = spawnSync5("xattr", ["-dr", "com.apple.quarantine", paths.appPath], { stdio: "ignore" });
39108
39828
  if (result.status !== 0) {
39109
39829
  p15.log.warn(`Could not remove macOS quarantine attributes from ${paths.appPath}.`);
39110
39830
  }
@@ -39124,26 +39844,26 @@ function buildLinuxDesktopEntry(executablePath) {
39124
39844
  ].join("\n");
39125
39845
  }
39126
39846
  async function writeLinuxLaunchers(paths) {
39127
- const desktopDir = path24.join(homedir(), ".local", "share", "applications");
39128
- await mkdir3(desktopDir, { recursive: true });
39129
- await writeFile3(path24.join(desktopDir, "rudder.desktop"), buildLinuxDesktopEntry(paths.executablePath), "utf8");
39130
- const binDir = path24.join(homedir(), ".local", "bin");
39131
- await mkdir3(binDir, { recursive: true });
39132
- const wrapperPath = path24.join(binDir, "rudder-desktop");
39847
+ const desktopDir = path28.join(homedir2(), ".local", "share", "applications");
39848
+ await mkdir4(desktopDir, { recursive: true });
39849
+ await writeFile4(path28.join(desktopDir, "rudder.desktop"), buildLinuxDesktopEntry(paths.executablePath), "utf8");
39850
+ const binDir = path28.join(homedir2(), ".local", "bin");
39851
+ await mkdir4(binDir, { recursive: true });
39852
+ const wrapperPath = path28.join(binDir, "rudder-desktop");
39133
39853
  const escaped = paths.executablePath.replaceAll("'", `'"'"'`);
39134
- await writeFile3(wrapperPath, `#!/bin/sh
39854
+ await writeFile4(wrapperPath, `#!/bin/sh
39135
39855
  exec '${escaped}' "$@"
39136
39856
  `, "utf8");
39137
39857
  await chmod2(wrapperPath, 493);
39138
39858
  }
39139
39859
  function buildWindowsShortcutScript(executablePath) {
39140
- const appData = process.env.APPDATA?.trim() || path24.join(homedir(), "AppData", "Roaming");
39141
- const shortcutPath = path24.join(appData, "Microsoft", "Windows", "Start Menu", "Programs", "Rudder.lnk");
39860
+ const appData = process.env.APPDATA?.trim() || path28.join(homedir2(), "AppData", "Roaming");
39861
+ const shortcutPath = path28.join(appData, "Microsoft", "Windows", "Start Menu", "Programs", "Rudder.lnk");
39142
39862
  return [
39143
39863
  "$shell = New-Object -ComObject WScript.Shell",
39144
39864
  `$shortcut = $shell.CreateShortcut(${powershellQuote(shortcutPath)})`,
39145
39865
  `$shortcut.TargetPath = ${powershellQuote(executablePath)}`,
39146
- `$shortcut.WorkingDirectory = ${powershellQuote(path24.dirname(executablePath))}`,
39866
+ `$shortcut.WorkingDirectory = ${powershellQuote(path28.dirname(executablePath))}`,
39147
39867
  "$shortcut.Save()"
39148
39868
  ].join("; ");
39149
39869
  }
@@ -39153,7 +39873,7 @@ async function createPlatformLaunchers(paths, target) {
39153
39873
  return;
39154
39874
  }
39155
39875
  if (target.platform === "windows") {
39156
- const result = spawnSync4("powershell.exe", [
39876
+ const result = spawnSync5("powershell.exe", [
39157
39877
  "-NoProfile",
39158
39878
  "-ExecutionPolicy",
39159
39879
  "Bypass",
@@ -39165,17 +39885,17 @@ async function createPlatformLaunchers(paths, target) {
39165
39885
  }
39166
39886
  function launchDesktop(paths, target) {
39167
39887
  if (target.platform === "macos") {
39168
- spawn3("open", [paths.appPath], { detached: true, stdio: "ignore" }).unref();
39888
+ spawn4("open", [paths.appPath], { detached: true, stdio: "ignore" }).unref();
39169
39889
  return;
39170
39890
  }
39171
39891
  if (target.platform === "windows") {
39172
- spawn3("cmd.exe", ["/c", "start", "", paths.executablePath], { detached: true, stdio: "ignore" }).unref();
39892
+ spawn4("cmd.exe", ["/c", "start", "", paths.executablePath], { detached: true, stdio: "ignore" }).unref();
39173
39893
  return;
39174
39894
  }
39175
- spawn3(paths.executablePath, [], { detached: true, stdio: "ignore" }).unref();
39895
+ spawn4(paths.executablePath, [], { detached: true, stdio: "ignore" }).unref();
39176
39896
  }
39177
39897
  async function writeInstallMetadata(paths, releaseTag, assetName, assetChecksum, assetKind = "full") {
39178
- mkdirSync2(path24.dirname(paths.metadataPath), { recursive: true });
39898
+ mkdirSync3(path28.dirname(paths.metadataPath), { recursive: true });
39179
39899
  const metadata = {
39180
39900
  version: 1,
39181
39901
  releaseTag,
@@ -39184,8 +39904,8 @@ async function writeInstallMetadata(paths, releaseTag, assetName, assetChecksum,
39184
39904
  assetKind,
39185
39905
  installedAt: (/* @__PURE__ */ new Date()).toISOString()
39186
39906
  };
39187
- mkdirSync2(paths.installRoot, { recursive: true });
39188
- await writeFile3(paths.metadataPath, `${JSON.stringify(metadata, null, 2)}
39907
+ mkdirSync3(paths.installRoot, { recursive: true });
39908
+ await writeFile4(paths.metadataPath, `${JSON.stringify(metadata, null, 2)}
39189
39909
  `, "utf8");
39190
39910
  }
39191
39911
  async function runStartPhase(message, successMessage, task, progressPhase) {
@@ -39214,10 +39934,27 @@ async function runStartPhase(message, successMessage, task, progressPhase) {
39214
39934
  }
39215
39935
  }
39216
39936
  async function startCommand(opts) {
39217
- const installCli = opts.cli !== false;
39937
+ applyLocalEnvProfile(opts);
39938
+ applyDataDirOverride(opts);
39218
39939
  const serverOnly = opts.serverOnly === true;
39219
- const installDesktop = !serverOnly && opts.desktop !== false;
39220
- const installRuntime = opts.runtime !== false;
39940
+ const installApp = !serverOnly && opts.desktop !== false;
39941
+ const requestedDesktopMode = parseDesktopLaunchMode(opts.desktopMode);
39942
+ const desktopTarget = installApp ? resolveDesktopAssetTarget() : null;
39943
+ const automaticCompatibilityCheck = requestedDesktopMode === "auto" && opts.desktopMode !== void 0;
39944
+ const smartAppControlState = desktopTarget?.platform === "windows" && automaticCompatibilityCheck ? detectSmartAppControlState() : "unknown";
39945
+ const desktopMode = installApp ? resolveDesktopLaunchMode({
39946
+ requested: requestedDesktopMode,
39947
+ platform: process.platform,
39948
+ smartAppControlState
39949
+ }) : "native";
39950
+ if (desktopMode === "browser" && desktopTarget?.platform !== "windows") {
39951
+ throw new Error("Rudder browser-app compatibility mode is currently available only on Windows.");
39952
+ }
39953
+ const installDesktop = installApp && desktopMode === "native";
39954
+ const installBrowserApp = installApp && desktopMode === "browser";
39955
+ const browserLocalProfile = installBrowserApp ? resolveActiveLocalEnvProfile() ?? applyLocalEnvProfile({ localEnv: "prod_local" }) : null;
39956
+ const installCli = opts.cli !== false || installBrowserApp;
39957
+ const installRuntime = opts.runtime !== false || installBrowserApp;
39221
39958
  const repo = opts.repo?.trim() || DEFAULT_DESKTOP_RELEASE_REPO;
39222
39959
  const version = opts.targetVersion?.trim() || opts.version?.trim() || resolveCurrentCliVersion();
39223
39960
  const dryRun = opts.dryRun === true;
@@ -39231,7 +39968,7 @@ async function startCommand(opts) {
39231
39968
  if (!exactDesktopAssetPath || !exactDesktopAssetChecksum || !exactDesktopAssetName || !exactDesktopReleaseDigest) {
39232
39969
  throw new Error("Exact Desktop asset mode requires path, checksum, asset name, and release digest.");
39233
39970
  }
39234
- if (!path24.isAbsolute(exactDesktopAssetPath) || exactDesktopAssetName.includes("/") || !/^[a-f0-9]{64}$/iu.test(exactDesktopAssetChecksum) || !/^[a-f0-9]{64}$/iu.test(exactDesktopReleaseDigest)) {
39971
+ if (!path28.isAbsolute(exactDesktopAssetPath) || exactDesktopAssetName.includes("/") || !/^[a-f0-9]{64}$/iu.test(exactDesktopAssetChecksum) || !/^[a-f0-9]{64}$/iu.test(exactDesktopReleaseDigest)) {
39235
39972
  throw new Error("Exact Desktop asset mode received invalid candidate identity.");
39236
39973
  }
39237
39974
  if (opts.desktopAssetKind && opts.desktopAssetKind !== "full" && opts.desktopAssetKind !== "shell") {
@@ -39244,10 +39981,20 @@ async function startCommand(opts) {
39244
39981
  if (error.code !== "EPIPE") throw error;
39245
39982
  });
39246
39983
  }
39247
- if (!installCli && !installDesktop && !installRuntime) {
39984
+ if (!installCli && !installApp && !installRuntime) {
39248
39985
  throw new Error("Nothing to start. Remove --no-cli, --no-runtime, --no-desktop, or --server-only.");
39249
39986
  }
39250
39987
  p15.intro(pc14.bgCyan(pc14.black(serverOnly ? " rudder start --server-only " : " rudder start ")));
39988
+ if (installBrowserApp) {
39989
+ p15.log.warn(
39990
+ requestedDesktopMode === "browser" ? "Using the requested Windows browser-app compatibility mode." : "Windows Smart App Control is on, so Rudder will use browser-app compatibility mode instead of the unsigned Desktop executable."
39991
+ );
39992
+ p15.log.message(
39993
+ pc14.dim(
39994
+ "This is a loopback-only local_trusted client without the packaged Desktop Account Gate. Local data stays in place; Electron-only Browser and App Builder bridges are unavailable."
39995
+ )
39996
+ );
39997
+ }
39251
39998
  if (opts.versionCheck !== false) {
39252
39999
  const updateNotice = await getCliUpdateNotice(version);
39253
40000
  if (updateNotice) p15.log.warn(updateNotice);
@@ -39339,15 +40086,86 @@ async function startCommand(opts) {
39339
40086
  spinner3.stop(`${pc14.cyan("rudder")} CLI installed.`);
39340
40087
  }
39341
40088
  }
40089
+ if (installBrowserApp) {
40090
+ const target = desktopTarget;
40091
+ const installRoot = opts.desktopInstallDir ? path28.resolve(opts.desktopInstallDir) : resolveDefaultDesktopInstallRoot(target);
40092
+ const installPaths = resolveDesktopInstallPaths(target, installRoot);
40093
+ const runtimeVersion = version;
40094
+ if (!browserLocalProfile) throw new Error("Rudder browser-app requires a local environment profile.");
40095
+ const dataDir = resolveRudderHomeDir();
40096
+ p15.log.step("Preparing Windows browser app");
40097
+ p15.log.message(`Runtime: ${pc14.cyan(runtimeVersion)}`);
40098
+ p15.log.message(`Workspace: ${pc14.cyan(`${browserLocalProfile.name}/${browserLocalProfile.instanceId}`)}`);
40099
+ if (dryRun) {
40100
+ p15.log.message(
40101
+ `[dry-run] Would create a Rudder Start Menu shortcut backed by Node and open the local workspace in Microsoft Edge app mode.`
40102
+ );
40103
+ p15.outro(pc14.green("Dry run complete."));
40104
+ return;
40105
+ }
40106
+ const cliEntryPath = resolveGlobalInstalledCliEntry();
40107
+ if (!await pathExists2(cliEntryPath)) {
40108
+ throw new Error(`Persistent Rudder CLI entry was not found at ${cliEntryPath}.`);
40109
+ }
40110
+ await mkdir4(installRoot, { recursive: true });
40111
+ const edgePath = resolveEdgeExecutable();
40112
+ const nativeIconPath = await pathExists2(installPaths.executablePath) ? installPaths.executablePath : null;
40113
+ const shortcutPath = createWindowsBrowserAppShortcut({
40114
+ nodePath: process.execPath,
40115
+ cliEntryPath,
40116
+ localEnv: browserLocalProfile.name,
40117
+ dataDir,
40118
+ runtimeVersion,
40119
+ workingDirectory: installRoot,
40120
+ iconPath: nativeIconPath ?? edgePath
40121
+ });
40122
+ p15.log.success(`Rudder browser-app shortcut is ready at ${pc14.cyan(shortcutPath)}.`);
40123
+ let applySignalController = null;
40124
+ if (desktopProgressJson && opts.desktopWaitForApply === true) {
40125
+ writeDesktopProgress({
40126
+ phase: "ready_to_install",
40127
+ message: "Windows browser-app compatibility mode is ready.",
40128
+ percent: 100
40129
+ });
40130
+ applySignalController = createDesktopApplySignalController();
40131
+ await applySignalController.waitForInitialSignal();
40132
+ applySignalController.close();
40133
+ writeDesktopProgress({
40134
+ phase: "preparing_restart",
40135
+ message: "Starting the Windows browser app...",
40136
+ percent: 100
40137
+ });
40138
+ }
40139
+ if (opts.open !== false) {
40140
+ const launch = await launchDetachedBrowserApp({
40141
+ cliEntryPath,
40142
+ localEnv: browserLocalProfile.name,
40143
+ dataDir,
40144
+ runtimeVersion,
40145
+ open: true
40146
+ });
40147
+ p15.log.success(`Rudder browser app opened at ${pc14.cyan(launch.boardUrl)}.`);
40148
+ p15.log.message(pc14.dim(`Background runtime log: ${launch.logPath}`));
40149
+ if (desktopProgressJson) {
40150
+ writeDesktopProgress({
40151
+ phase: "closing",
40152
+ message: "Rudder browser app is ready. You can close the native Desktop window.",
40153
+ percent: 100
40154
+ });
40155
+ }
40156
+ }
40157
+ p15.outro(pc14.green("Rudder start complete."));
40158
+ return;
40159
+ }
39342
40160
  if (installDesktop) {
39343
40161
  const downloadSource = resolveDesktopDownloadSource(opts.downloadSource);
39344
40162
  const mirrorBaseUrl = resolveDesktopReleaseMirrorBaseUrl(repo);
39345
40163
  const smokeReleaseBaseUrls = resolveDesktopSmokeReleaseBaseUrls();
39346
- const target = resolveDesktopAssetTarget();
40164
+ const target = desktopTarget;
39347
40165
  const tag = resolveDesktopReleaseTag(version);
39348
- const installRoot = opts.desktopInstallDir ? path24.resolve(opts.desktopInstallDir) : resolveDefaultDesktopInstallRoot(target);
40166
+ const installRoot = opts.desktopInstallDir ? path28.resolve(opts.desktopInstallDir) : resolveDefaultDesktopInstallRoot(target);
39349
40167
  const installPaths = resolveDesktopInstallPaths(target, installRoot);
39350
- const outputDir = opts.outputDir ? path24.resolve(opts.outputDir) : await mkdtemp2(path24.join(tmpdir(), "rudder-desktop-installer."));
40168
+ const outputDir = opts.outputDir ? path28.resolve(opts.outputDir) : await mkdtemp2(path28.join(tmpdir2(), "rudder-desktop-installer."));
39351
40169
  p15.log.step("Installing desktop app");
39352
40170
  p15.log.message(`Release: ${pc14.cyan(`${repo}@${tag}`)}`);
39353
40171
  p15.log.message(`Target: ${pc14.cyan(`${target.platform}/${target.arch}`)}`);
@@ -39393,7 +40211,7 @@ async function startCommand(opts) {
39393
40211
  if (linkDescriptor.isSymbolicLink()) throw new Error("Exact Desktop asset must not be a symbolic link.");
39394
40212
  const checksum = await runStartPhase(
39395
40213
  "Verifying staged Desktop checksum...",
39396
- `Verified ${pc14.cyan(path24.basename(exactDesktopAssetPath))}.`,
40214
+ `Verified ${pc14.cyan(path28.basename(exactDesktopAssetPath))}.`,
39397
40215
  () => assertChecksumMatch(exactDesktopAssetPath, expectedChecksum),
39398
40216
  desktopProgressJson ? "verifying_checksum" : null
39399
40217
  );
@@ -39512,7 +40330,7 @@ async function startCommand(opts) {
39512
40330
  }
39513
40331
  const checksum = await runStartPhase(
39514
40332
  "Verifying Desktop checksum...",
39515
- `Verified ${pc14.cyan(path24.basename(verifiedAsset.path))}.`,
40333
+ `Verified ${pc14.cyan(path28.basename(verifiedAsset.path))}.`,
39516
40334
  () => assertChecksumMatch(verifiedAsset.path, expectedChecksum),
39517
40335
  desktopProgressJson ? "verifying_checksum" : null
39518
40336
  );
@@ -39524,7 +40342,7 @@ async function startCommand(opts) {
39524
40342
  assetName: selectedAsset.name,
39525
40343
  assetChecksum: checksum,
39526
40344
  assetKind: selectedAssetKind,
39527
- stagedArtifactPath: path24.resolve(verifiedAsset.path),
40345
+ stagedArtifactPath: path28.resolve(verifiedAsset.path),
39528
40346
  stagedArtifactDigest: checksum,
39529
40347
  releaseDigest: createHash5("sha256").update(JSON.stringify({
39530
40348
  releaseTag,
@@ -39615,31 +40433,6 @@ async function startCommand(opts) {
39615
40433
  p15.outro(pc14.green("Rudder start complete."));
39616
40434
  }
39617
40435
 
39618
- // src/config/data-dir.ts
39619
- init_home();
39620
- import path25 from "node:path";
39621
- function applyDataDirOverride(options, support = {}) {
39622
- const rawDataDir = options.dataDir?.trim();
39623
- if (!rawDataDir) return null;
39624
- const resolvedDataDir = path25.resolve(expandHomePrefix(rawDataDir));
39625
- process.env.RUDDER_HOME = resolvedDataDir;
39626
- if (support.hasConfigOption) {
39627
- const hasConfigOverride = Boolean(options.config?.trim()) || Boolean(process.env.RUDDER_CONFIG?.trim());
39628
- if (!hasConfigOverride) {
39629
- const instanceId = resolveRudderInstanceId(options.instance);
39630
- process.env.RUDDER_INSTANCE_ID = instanceId;
39631
- process.env.RUDDER_CONFIG = resolveDefaultConfigPath(instanceId);
39632
- }
39633
- }
39634
- if (support.hasContextOption) {
39635
- const hasContextOverride = Boolean(options.context?.trim()) || Boolean(process.env.RUDDER_CONTEXT?.trim());
39636
- if (!hasContextOverride) {
39637
- process.env.RUDDER_CONTEXT = resolveDefaultContextPath();
39638
- }
39639
- }
39640
- return resolvedDataDir;
39641
- }
39642
-
39643
40436
  // src/program.ts
39644
40437
  init_env();
39645
40438
  init_local_env();
@@ -39681,7 +40474,8 @@ function createProgram() {
39681
40474
  });
39682
40475
  loadRudderEnvFile(options.config);
39683
40476
  });
39684
- program.command("start").description("Start Rudder Desktop and prepare the matching persistent CLI").option("--server-only", "Prepare the Rudder server runtime and persistent CLI without installing Desktop").option("--no-cli", "Skip persistent CLI installation").option("--no-runtime", "Skip Rudder runtime installation").option("--no-desktop", "Skip desktop app installation").option("--version <version>", "Rudder version to start (default: current CLI version)").option("--target-version <version>", "Rudder version to start; avoids the root CLI version flag").option("--repo <owner/repo>", "GitHub repository that hosts desktop releases").option("--download-source <source>", "Desktop download source: auto, cn, or global").option("--output-dir <path>", "Directory for downloaded desktop release assets").option("--desktop-install-dir <path>", "Directory for the portable Desktop install").option("--no-open", "Install Desktop without launching it").option("--wait-for-active-runs", "Wait for active Rudder runs to finish before replacing Desktop", false).option("--desktop-progress-json", "Emit newline-delimited Desktop update progress events").option("--desktop-wait-for-apply", "Wait for an apply signal after downloading and verifying the Desktop update", false).option("--desktop-prepare-only", "Download and verify the Desktop update without installing or launching it", false).option("--desktop-asset-path <path>", "Use one previously staged, exact Desktop asset path").option("--desktop-asset-checksum <sha256>", "SHA-256 for the exact staged Desktop asset").option("--desktop-asset-name <name>", "Asset name bound to the exact staged Desktop candidate").option("--desktop-asset-kind <kind>", "Asset kind bound to the exact staged Desktop candidate (full or shell)").option("--desktop-release-digest <sha256>", "Release digest bound to the exact staged Desktop candidate").addOption(new Option("--desktop-runtime-best-effort").hideHelp()).option("--no-version-check", "Skip checking npm for a newer Rudder CLI version").option("--dry-run", "Print the start actions without changing the machine", false).action(startCommand);
40477
+ program.command("start").description("Start Rudder Desktop and prepare the matching persistent CLI").option("--server-only", "Prepare the Rudder server runtime and persistent CLI without installing Desktop").option("--no-cli", "Skip persistent CLI installation").option("--no-runtime", "Skip Rudder runtime installation").option("--no-desktop", "Skip desktop app installation").option("--version <version>", "Rudder version to start (default: current CLI version)").option("--target-version <version>", "Rudder version to start; avoids the root CLI version flag").option("--repo <owner/repo>", "GitHub repository that hosts desktop releases").option("--download-source <source>", "Desktop download source: auto, cn, or global").option("--output-dir <path>", "Directory for downloaded desktop release assets").option("--desktop-install-dir <path>", "Directory for the portable Desktop install").option("--desktop-mode <mode>", "Desktop launch mode: auto, native, or browser", "auto").option("-d, --data-dir <path>", DATA_DIR_OPTION_HELP).option("--no-open", "Install Desktop without launching it").option("--wait-for-active-runs", "Wait for active Rudder runs to finish before replacing Desktop", false).option("--desktop-progress-json", "Emit newline-delimited Desktop update progress events").option("--desktop-wait-for-apply", "Wait for an apply signal after downloading and verifying the Desktop update", false).option("--desktop-prepare-only", "Download and verify the Desktop update without installing or launching it", false).option("--desktop-asset-path <path>", "Use one previously staged, exact Desktop asset path").option("--desktop-asset-checksum <sha256>", "SHA-256 for the exact staged Desktop asset").option("--desktop-asset-name <name>", "Asset name bound to the exact staged Desktop candidate").option("--desktop-asset-kind <kind>", "Asset kind bound to the exact staged Desktop candidate (full or shell)").option("--desktop-release-digest <sha256>", "Release digest bound to the exact staged Desktop candidate").addOption(new Option("--desktop-runtime-best-effort").hideHelp()).option("--no-version-check", "Skip checking npm for a newer Rudder CLI version").option("--dry-run", "Print the start actions without changing the machine", false).action(startCommand);
40478
+ program.command("browser-app").description("Open Rudder in a system browser app window").option("--runtime-version <version>", "Rudder server runtime version").option("-d, --data-dir <path>", DATA_DIR_OPTION_HELP).option("--child", "Run the hidden browser-app server child", false).option("--ready-file <path>", "Internal startup handoff file").option("--no-open", "Start or attach to the local runtime without opening the app window").action(browserAppCommand);
39685
40479
  program.command("onboard").description("Interactive first-run setup wizard").option("-c, --config <path>", "Path to config file").option("-d, --data-dir <path>", DATA_DIR_OPTION_HELP).option("-y, --yes", "Accept defaults (quickstart + start immediately)", false).option("--run", "Start Rudder immediately after saving config", false).action(onboard);
39686
40480
  program.command("doctor").description("Run diagnostic checks on your Rudder setup").option("-c, --config <path>", "Path to config file").option("-d, --data-dir <path>", DATA_DIR_OPTION_HELP).option("--repair", "Attempt to repair issues automatically").alias("--fix").option("-y, --yes", "Skip repair confirmation prompts").action(async (opts) => {
39687
40481
  await doctor(opts);