visual-remote 0.1.2 → 0.2.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.
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
+ import { realpathSync } from "node:fs";
4
5
  import { resolve as resolve8 } from "node:path";
5
6
  import { pathToFileURL } from "node:url";
6
7
  import { Command, InvalidArgumentError } from "commander";
@@ -1438,8 +1439,8 @@ var CodexAdapter = class {
1438
1439
  };
1439
1440
 
1440
1441
  // ../../packages/bridge-core/src/config/loader.ts
1441
- import { readFile, realpath } from "node:fs/promises";
1442
- import { basename, isAbsolute, join, relative, resolve, sep } from "node:path";
1442
+ import { readFile, realpath, stat as stat2 } from "node:fs/promises";
1443
+ import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
1443
1444
  import { parse as parseYaml } from "yaml";
1444
1445
  import { ZodError } from "zod";
1445
1446
 
@@ -1626,11 +1627,42 @@ function isWithinRoot(root, candidate) {
1626
1627
  const pathFromRoot = relative(root, candidate);
1627
1628
  return pathFromRoot === "" || !pathFromRoot.startsWith(`..${sep}`) && pathFromRoot !== "..";
1628
1629
  }
1630
+ async function configExists(root) {
1631
+ try {
1632
+ await stat2(join(root, CONFIG_PATH));
1633
+ return true;
1634
+ } catch (error) {
1635
+ if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
1636
+ return false;
1637
+ }
1638
+ throw error;
1639
+ }
1640
+ }
1641
+ async function discoverVisualDevConfigRoot(startDirectory, repositoryRoot) {
1642
+ const repoRoot = await realpath(repositoryRoot);
1643
+ let cursor = await realpath(startDirectory);
1644
+ if (!isWithinRoot(repoRoot, cursor)) {
1645
+ throw new VisualDevConfigError(`Project directory is outside Git worktree: ${cursor}`);
1646
+ }
1647
+ while (true) {
1648
+ if (await configExists(cursor)) return cursor;
1649
+ if (cursor === repoRoot) return repoRoot;
1650
+ const parent = dirname(cursor);
1651
+ if (parent === cursor || !isWithinRoot(repoRoot, parent)) return repoRoot;
1652
+ cursor = parent;
1653
+ }
1654
+ }
1629
1655
  async function loadVisualDevConfig(repositoryRoot, options = {}) {
1630
1656
  const repoRoot = await realpath(repositoryRoot);
1631
- const configPath = join(repoRoot, CONFIG_PATH);
1632
- const localConfigPath = join(repoRoot, LOCAL_CONFIG_PATH);
1633
- const projectId = basename(repoRoot);
1657
+ const configRoot = await realpath(options.configRoot ?? repoRoot);
1658
+ if (!isWithinRoot(repoRoot, configRoot)) {
1659
+ throw new VisualDevConfigError(
1660
+ `Config directory is outside Git worktree: ${configRoot}`
1661
+ );
1662
+ }
1663
+ const configPath = join(configRoot, CONFIG_PATH);
1664
+ const localConfigPath = join(configRoot, LOCAL_CONFIG_PATH);
1665
+ const projectId = basename(configRoot);
1634
1666
  const baseDocument = await readYamlMapping(configPath, options.requireConfig ?? false);
1635
1667
  const localDocument = await readYamlMapping(localConfigPath, false);
1636
1668
  const loadedFiles = [];
@@ -1657,7 +1689,7 @@ async function loadVisualDevConfig(repositoryRoot, options = {}) {
1657
1689
  filePath: localDocument === void 0 ? configPath : localConfigPath
1658
1690
  });
1659
1691
  }
1660
- const unresolvedWorkspace = isAbsolute(config.project.workspace) ? config.project.workspace : resolve(repoRoot, config.project.workspace);
1692
+ const unresolvedWorkspace = isAbsolute(config.project.workspace) ? config.project.workspace : resolve(configRoot, config.project.workspace);
1661
1693
  let workspaceRoot;
1662
1694
  try {
1663
1695
  workspaceRoot = await realpath(unresolvedWorkspace);
@@ -1676,6 +1708,7 @@ async function loadVisualDevConfig(repositoryRoot, options = {}) {
1676
1708
  return {
1677
1709
  config,
1678
1710
  repoRoot,
1711
+ configRoot,
1679
1712
  workspaceRoot,
1680
1713
  configPath,
1681
1714
  localConfigPath,
@@ -1963,7 +1996,7 @@ import {
1963
1996
  rm
1964
1997
  } from "node:fs/promises";
1965
1998
  import { tmpdir } from "node:os";
1966
- import { dirname, relative as relative3, resolve as resolve4, sep as sep3 } from "node:path";
1999
+ import { dirname as dirname2, relative as relative3, resolve as resolve4, sep as sep3 } from "node:path";
1967
2000
  var SNAPSHOT_ENV = {
1968
2001
  GIT_AUTHOR_NAME: "Visual Bridge",
1969
2002
  GIT_AUTHOR_EMAIL: "visual-bridge@localhost",
@@ -2316,7 +2349,7 @@ var GitTransactionManager = class _GitTransactionManager {
2316
2349
  } catch (error) {
2317
2350
  if (error.code !== "ENOENT") throw error;
2318
2351
  }
2319
- await this.#removeEmptyParents(dirname(absolute));
2352
+ await this.#removeEmptyParents(dirname2(absolute));
2320
2353
  }
2321
2354
  async #removeEmptyParents(start) {
2322
2355
  let cursor = start;
@@ -2326,13 +2359,13 @@ var GitTransactionManager = class _GitTransactionManager {
2326
2359
  } catch (error) {
2327
2360
  const code = error.code;
2328
2361
  if (code === "ENOENT") {
2329
- cursor = dirname(cursor);
2362
+ cursor = dirname2(cursor);
2330
2363
  continue;
2331
2364
  }
2332
2365
  if (code === "ENOTEMPTY" || code === "EEXIST") return;
2333
2366
  throw error;
2334
2367
  }
2335
- cursor = dirname(cursor);
2368
+ cursor = dirname2(cursor);
2336
2369
  }
2337
2370
  }
2338
2371
  async #assertSnapshotRef(ref) {
@@ -2352,7 +2385,7 @@ var GitTransactionManager = class _GitTransactionManager {
2352
2385
  // ../../packages/bridge-core/src/storage/sqlite-task-store.ts
2353
2386
  import { mkdirSync } from "node:fs";
2354
2387
  import { createRequire } from "node:module";
2355
- import { dirname as dirname2 } from "node:path";
2388
+ import { dirname as dirname3 } from "node:path";
2356
2389
  var requireNodeBuiltin = createRequire(import.meta.url);
2357
2390
  var optional = (value) => value ?? void 0;
2358
2391
  function parseJson(value, fallback) {
@@ -2444,7 +2477,7 @@ function taskParams(task) {
2444
2477
  var SqliteTaskStore = class {
2445
2478
  #db;
2446
2479
  constructor(filename) {
2447
- if (filename !== ":memory:") mkdirSync(dirname2(filename), { recursive: true, mode: 448 });
2480
+ if (filename !== ":memory:") mkdirSync(dirname3(filename), { recursive: true, mode: 448 });
2448
2481
  const { DatabaseSync } = requireNodeBuiltin("node:sqlite");
2449
2482
  this.#db = new DatabaseSync(filename);
2450
2483
  this.#db.exec(`
@@ -4588,7 +4621,9 @@ ${output2}` : ""}`
4588
4621
 
4589
4622
  // ../../packages/bridge-core/src/bridge/default-control-service.ts
4590
4623
  async function createDefaultControlService(context, environment = process.env) {
4591
- const loaded = await loadVisualDevConfig(context.repoRoot);
4624
+ const loaded = await loadVisualDevConfig(context.repoRoot, {
4625
+ ...context.configRoot === void 0 ? {} : { configRoot: context.configRoot }
4626
+ });
4592
4627
  if (loaded.config.agent.adapter !== "codex") {
4593
4628
  throw new Error(
4594
4629
  `Agent adapter ${loaded.config.agent.adapter} is not implemented in this MVP build`
@@ -4881,6 +4916,7 @@ async function startBridgeCore(options, dependencies) {
4881
4916
  mode: options.mode,
4882
4917
  projectId: loadedConfig.config.project.id,
4883
4918
  repoRoot: loadedConfig.repoRoot,
4919
+ configRoot: loadedConfig.configRoot,
4884
4920
  workspaceRoot: loadedConfig.workspaceRoot,
4885
4921
  upstreamUrl: options.upstreamUrl
4886
4922
  };
@@ -4950,8 +4986,10 @@ async function startBridgeCore(options, dependencies) {
4950
4986
  }
4951
4987
  }
4952
4988
  async function startAttachBridge(options, dependencies = {}) {
4953
- const repoRoot = await discoverGitWorktreeRoot(dependencies.cwd ?? process.cwd());
4954
- const loadedConfig = await loadVisualDevConfig(repoRoot);
4989
+ const cwd = dependencies.cwd ?? process.cwd();
4990
+ const repoRoot = await discoverGitWorktreeRoot(cwd);
4991
+ const configRoot = await discoverVisualDevConfigRoot(cwd, repoRoot);
4992
+ const loadedConfig = await loadVisualDevConfig(repoRoot, { configRoot });
4955
4993
  return await startBridgeCore(
4956
4994
  {
4957
4995
  mode: "attach",
@@ -4965,8 +5003,13 @@ async function startAttachBridge(options, dependencies = {}) {
4965
5003
  );
4966
5004
  }
4967
5005
  async function startManagedBridge(options = {}, dependencies = {}) {
4968
- const repoRoot = await discoverGitWorktreeRoot(dependencies.cwd ?? process.cwd());
4969
- const loadedConfig = await loadVisualDevConfig(repoRoot, { requireConfig: true });
5006
+ const cwd = dependencies.cwd ?? process.cwd();
5007
+ const repoRoot = await discoverGitWorktreeRoot(cwd);
5008
+ const configRoot = await discoverVisualDevConfigRoot(cwd, repoRoot);
5009
+ const loadedConfig = await loadVisualDevConfig(repoRoot, {
5010
+ requireConfig: true,
5011
+ configRoot
5012
+ });
4970
5013
  const command = loadedConfig.config.upstream.command;
4971
5014
  if (command === void 0) {
4972
5015
  throw new Error("visual dev requires upstream.command in .visualdev/config.yaml");
@@ -5075,14 +5118,14 @@ function formatBridgeSummary(bridge) {
5075
5118
 
5076
5119
  // src/doctor.ts
5077
5120
  import { constants } from "node:fs";
5078
- import { access as access2, stat as stat2 } from "node:fs/promises";
5079
- import { delimiter, isAbsolute as isAbsolute5, join as join4, resolve as resolve7 } from "node:path";
5121
+ import { access as access2, stat as stat3 } from "node:fs/promises";
5122
+ import { delimiter, isAbsolute as isAbsolute5, join as join4, relative as relative6, resolve as resolve7 } from "node:path";
5080
5123
  import { execFile as execFile2 } from "node:child_process";
5081
5124
  import { promisify as promisify2 } from "node:util";
5082
5125
  var execFileAsync2 = promisify2(execFile2);
5083
5126
  async function fileExists(path) {
5084
5127
  try {
5085
- await stat2(path);
5128
+ await stat3(path);
5086
5129
  return true;
5087
5130
  } catch (error) {
5088
5131
  if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
@@ -5130,14 +5173,19 @@ async function runDoctor(dependencies = {}) {
5130
5173
  return checks;
5131
5174
  }
5132
5175
  try {
5133
- const loaded = await loadVisualDevConfig(repoRoot);
5176
+ const configRoot = await discoverVisualDevConfigRoot(
5177
+ dependencies.cwd ?? process.cwd(),
5178
+ repoRoot
5179
+ );
5180
+ const loaded = await loadVisualDevConfig(repoRoot, { configRoot });
5134
5181
  checks.push({
5135
5182
  name: "config",
5136
5183
  status: loaded.loadedFiles.length === 0 ? "warning" : "pass",
5137
5184
  message: loaded.loadedFiles.length === 0 ? "No .visualdev/config.yaml; attach defaults are available." : loaded.loadedFiles.join(", ")
5138
5185
  });
5139
5186
  if (await fileExists(loaded.localConfigPath)) {
5140
- const ignored = await isIgnored(repoRoot, ".visualdev/config.local.yaml");
5187
+ const localConfigRelativePath = relative6(repoRoot, loaded.localConfigPath);
5188
+ const ignored = await isIgnored(repoRoot, localConfigRelativePath);
5141
5189
  checks.push({
5142
5190
  name: "local-config-ignore",
5143
5191
  status: ignored ? "pass" : "warning",
@@ -5175,15 +5223,23 @@ function formatDoctorChecks(checks) {
5175
5223
  }
5176
5224
 
5177
5225
  // src/init.ts
5178
- import { readFile as readFile5, mkdir as mkdir3, stat as stat3, writeFile as writeFile3 } from "node:fs/promises";
5179
- import { basename as basename2, dirname as dirname3, join as join5 } from "node:path";
5226
+ import { spawn as spawn6 } from "node:child_process";
5227
+ import { readFile as readFile5, mkdir as mkdir3, realpath as realpath10, stat as stat4, writeFile as writeFile3 } from "node:fs/promises";
5228
+ import { basename as basename2, dirname as dirname4, join as join5, relative as relative7 } from "node:path";
5180
5229
  import { stringify as stringifyYaml } from "yaml";
5230
+ var VITE_CONFIG_FILES = [
5231
+ "vite.config.ts",
5232
+ "vite.config.mts",
5233
+ "vite.config.js",
5234
+ "vite.config.mjs"
5235
+ ];
5236
+ var VITE_IMPORT = 'import { visualRemote } from "visual-remote/vite";';
5181
5237
  function isMissingFile(error) {
5182
5238
  return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
5183
5239
  }
5184
5240
  async function fileExists2(path) {
5185
5241
  try {
5186
- await stat3(path);
5242
+ await stat4(path);
5187
5243
  return true;
5188
5244
  } catch (error) {
5189
5245
  if (isMissingFile(error)) return false;
@@ -5195,7 +5251,7 @@ function packageManagerFromField(value) {
5195
5251
  const name = value.split("@", 1)[0];
5196
5252
  return name === "bun" || name === "npm" || name === "pnpm" || name === "yarn" ? name : void 0;
5197
5253
  }
5198
- async function detectPackageManager(repoRoot, manifest) {
5254
+ async function detectPackageManager(projectRoot, repoRoot, manifest) {
5199
5255
  const declared = packageManagerFromField(manifest.packageManager);
5200
5256
  if (declared !== void 0) return declared;
5201
5257
  const lockfiles = [
@@ -5205,8 +5261,10 @@ async function detectPackageManager(repoRoot, manifest) {
5205
5261
  ["bun", "bun.lockb"],
5206
5262
  ["npm", "package-lock.json"]
5207
5263
  ];
5208
- for (const [manager, filename] of lockfiles) {
5209
- if (await fileExists2(join5(repoRoot, filename))) return manager;
5264
+ for (const root of projectRoot === repoRoot ? [projectRoot] : [projectRoot, repoRoot]) {
5265
+ for (const [manager, filename] of lockfiles) {
5266
+ if (await fileExists2(join5(root, filename))) return manager;
5267
+ }
5210
5268
  }
5211
5269
  return "npm";
5212
5270
  }
@@ -5216,6 +5274,19 @@ function readDevScript(manifest) {
5216
5274
  }
5217
5275
  return manifest.scripts.dev.trim();
5218
5276
  }
5277
+ function packageRecord(value) {
5278
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
5279
+ }
5280
+ function isViteProject(manifest, devScript) {
5281
+ const packages = {
5282
+ ...packageRecord(manifest.dependencies),
5283
+ ...packageRecord(manifest.devDependencies)
5284
+ };
5285
+ return "vite" in packages || /(^|[\s;&|])vite(?:\s|$)/.test(devScript);
5286
+ }
5287
+ function hasVisualRemote(manifest) {
5288
+ return "visual-remote" in packageRecord(manifest.dependencies) || "visual-remote" in packageRecord(manifest.devDependencies);
5289
+ }
5219
5290
  function devCommand(manager, script) {
5220
5291
  const command = manager === "pnpm" ? ["corepack", "pnpm", "run", "dev"] : manager === "yarn" ? ["corepack", "yarn", "run", "dev"] : manager === "bun" ? ["bun", "run", "dev"] : ["npm", "run", "dev"];
5221
5292
  const next = /(^|[\s;&|])next(?:\s|$)/.test(script);
@@ -5228,14 +5299,14 @@ function devCommand(manager, script) {
5228
5299
  "{upstreamPort}"
5229
5300
  ];
5230
5301
  }
5231
- async function readManifest(repoRoot) {
5232
- const manifestPath = join5(repoRoot, "package.json");
5302
+ async function readManifest(projectRoot) {
5303
+ const manifestPath = join5(projectRoot, "package.json");
5233
5304
  let source;
5234
5305
  try {
5235
5306
  source = await readFile5(manifestPath, "utf8");
5236
5307
  } catch (error) {
5237
5308
  if (isMissingFile(error)) {
5238
- throw new Error("visual init requires package.json at the Git worktree root");
5309
+ throw new Error("visual init requires package.json in the current directory");
5239
5310
  }
5240
5311
  throw error;
5241
5312
  }
@@ -5250,55 +5321,163 @@ async function readManifest(repoRoot) {
5250
5321
  }
5251
5322
  return value;
5252
5323
  }
5253
- async function initializeVisualDev(dependencies = {}) {
5254
- const repoRoot = await discoverGitWorktreeRoot(dependencies.cwd ?? process.cwd());
5255
- const configPath = join5(repoRoot, CONFIG_PATH);
5256
- if (await fileExists2(configPath)) {
5257
- return { created: false, configPath };
5324
+ async function findViteConfig(projectRoot) {
5325
+ for (const filename of VITE_CONFIG_FILES) {
5326
+ const candidate = join5(projectRoot, filename);
5327
+ if (await fileExists2(candidate)) return candidate;
5258
5328
  }
5259
- const manifest = await readManifest(repoRoot);
5260
- const devScript = readDevScript(manifest);
5261
- const packageManager = await detectPackageManager(repoRoot, manifest);
5262
- const document = {
5263
- version: 1,
5264
- project: {
5265
- id: basename2(repoRoot),
5266
- workspace: "."
5267
- },
5268
- gateway: {
5269
- host: "0.0.0.0",
5270
- port: "auto"
5271
- },
5272
- upstream: {
5273
- port: "auto",
5274
- command: devCommand(packageManager, devScript)
5275
- }
5329
+ throw new Error(
5330
+ "visual init found Vite but could not find vite.config.ts, .mts, .js, or .mjs"
5331
+ );
5332
+ }
5333
+ function insertViteImport(source) {
5334
+ const lines = source.split("\n");
5335
+ let index = 0;
5336
+ while (lines[index]?.startsWith("///")) index += 1;
5337
+ lines.splice(index, 0, VITE_IMPORT);
5338
+ return lines.join("\n");
5339
+ }
5340
+ function transformViteConfig(source) {
5341
+ if (source.includes("visual-remote/vite") && /\bvisualRemote\s*\(/.test(source)) {
5342
+ return source;
5343
+ }
5344
+ let transformed = source.includes("visual-remote/vite") ? source : insertViteImport(source);
5345
+ const pluginsPattern = /(\bplugins\s*:\s*\[)/;
5346
+ if (pluginsPattern.test(transformed)) {
5347
+ return transformed.replace(
5348
+ pluginsPattern,
5349
+ (match, _prefix, offset, fullSource) => `${match}visualRemote(),${fullSource[offset + match.length] === "\n" ? "" : " "}`
5350
+ );
5351
+ }
5352
+ const objectConfigPattern = /(defineConfig\s*\(\s*\{)/;
5353
+ if (objectConfigPattern.test(transformed)) {
5354
+ return transformed.replace(
5355
+ objectConfigPattern,
5356
+ "$1\n plugins: [visualRemote()],"
5357
+ );
5358
+ }
5359
+ throw new Error(
5360
+ "visual init could not add visualRemote() to the Vite plugins array"
5361
+ );
5362
+ }
5363
+ async function configureVite(configPath) {
5364
+ const source = await readFile5(configPath, "utf8");
5365
+ const transformed = transformViteConfig(source);
5366
+ if (transformed === source) return false;
5367
+ await writeFile3(configPath, transformed, "utf8");
5368
+ return true;
5369
+ }
5370
+ function installCommand(request) {
5371
+ if (request.packageManager === "pnpm") {
5372
+ return {
5373
+ command: "corepack",
5374
+ args: ["pnpm", "add", "--save-dev", request.packageSpec]
5375
+ };
5376
+ }
5377
+ if (request.packageManager === "yarn") {
5378
+ return {
5379
+ command: "corepack",
5380
+ args: ["yarn", "add", "--dev", request.packageSpec]
5381
+ };
5382
+ }
5383
+ if (request.packageManager === "bun") {
5384
+ return { command: "bun", args: ["add", "--dev", request.packageSpec] };
5385
+ }
5386
+ return {
5387
+ command: "npm",
5388
+ args: ["install", "--save-dev", request.packageSpec]
5276
5389
  };
5277
- await mkdir3(dirname3(configPath), { recursive: true });
5278
- try {
5279
- await writeFile3(configPath, stringifyYaml(document), {
5280
- encoding: "utf8",
5281
- flag: "wx"
5390
+ }
5391
+ async function installPackage(request) {
5392
+ const { command, args } = installCommand(request);
5393
+ await new Promise((resolvePromise, reject) => {
5394
+ const child = spawn6(command, args, {
5395
+ cwd: request.cwd,
5396
+ env: process.env,
5397
+ stdio: "inherit",
5398
+ windowsHide: true
5282
5399
  });
5283
- } catch (error) {
5284
- if (typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST") {
5285
- return { created: false, configPath };
5400
+ child.once("error", reject);
5401
+ child.once("exit", (code, signal) => {
5402
+ if (code === 0) {
5403
+ resolvePromise();
5404
+ return;
5405
+ }
5406
+ reject(
5407
+ new Error(
5408
+ `${command} ${args.join(" ")} failed${signal === null ? ` with exit code ${code ?? "unknown"}` : ` with ${signal}`}`
5409
+ )
5410
+ );
5411
+ });
5412
+ });
5413
+ }
5414
+ async function initializeVisualDev(dependencies = {}) {
5415
+ const projectRoot = await realpath10(dependencies.cwd ?? process.cwd());
5416
+ const repoRoot = await discoverGitWorktreeRoot(projectRoot);
5417
+ const manifest = await readManifest(projectRoot);
5418
+ const devScript = readDevScript(manifest);
5419
+ if (!isViteProject(manifest, devScript)) {
5420
+ throw new Error("visual init currently supports Vite projects");
5421
+ }
5422
+ const packageManager = await detectPackageManager(projectRoot, repoRoot, manifest);
5423
+ const integrationPath = await findViteConfig(projectRoot);
5424
+ const packageInstalled = !hasVisualRemote(manifest);
5425
+ if (packageInstalled) {
5426
+ await (dependencies.installPackage ?? installPackage)({
5427
+ cwd: projectRoot,
5428
+ packageManager,
5429
+ packageSpec: "visual-remote@latest"
5430
+ });
5431
+ }
5432
+ const integrationChanged = await configureVite(integrationPath);
5433
+ const configPath = join5(projectRoot, CONFIG_PATH);
5434
+ const created = !await fileExists2(configPath);
5435
+ if (created) {
5436
+ const document = {
5437
+ version: 1,
5438
+ project: {
5439
+ id: basename2(projectRoot),
5440
+ workspace: "."
5441
+ },
5442
+ gateway: {
5443
+ host: "0.0.0.0",
5444
+ port: "auto"
5445
+ },
5446
+ upstream: {
5447
+ port: "auto",
5448
+ command: devCommand(packageManager, devScript)
5449
+ }
5450
+ };
5451
+ await mkdir3(dirname4(configPath), { recursive: true });
5452
+ try {
5453
+ await writeFile3(configPath, stringifyYaml(document), {
5454
+ encoding: "utf8",
5455
+ flag: "wx"
5456
+ });
5457
+ } catch (error) {
5458
+ if (!isMissingFile(error) && (typeof error !== "object" || error === null || !("code" in error) || error.code !== "EEXIST")) {
5459
+ throw error;
5460
+ }
5286
5461
  }
5287
- throw error;
5288
5462
  }
5289
- return { created: true, configPath, devScript, packageManager };
5463
+ return {
5464
+ created,
5465
+ configPath,
5466
+ devScript,
5467
+ packageManager,
5468
+ integrationPath,
5469
+ integrationChanged,
5470
+ packageInstalled
5471
+ };
5290
5472
  }
5291
5473
  function formatInitResult(result) {
5292
- if (!result.created) {
5293
- return [
5294
- `Already initialized: ${CONFIG_PATH}`,
5295
- "Next: npx --yes visual-remote@latest dev"
5296
- ].join("\n");
5297
- }
5474
+ const configLabel = result.created ? "Created" : "Existing";
5475
+ const integrationLabel = result.integrationChanged ? "Configured" : "Existing";
5298
5476
  return [
5299
- `Created: ${CONFIG_PATH}`,
5300
- `Detected: ${result.packageManager} dev (${result.devScript})`,
5301
- "Next: npx --yes visual-remote@latest dev"
5477
+ `${configLabel}: ${relative7(process.cwd(), result.configPath) || CONFIG_PATH}`,
5478
+ `${integrationLabel}: ${relative7(process.cwd(), result.integrationPath)}`,
5479
+ result.packageInstalled ? "Installed: visual-remote@latest" : "Installed: visual-remote",
5480
+ "Next: Start the app normally and open its original URL."
5302
5481
  ].join("\n");
5303
5482
  }
5304
5483
 
@@ -5352,7 +5531,7 @@ function setExitCode(dependencies, code) {
5352
5531
  }
5353
5532
  }
5354
5533
  function createCli(dependencies = {}) {
5355
- const program = new Command().name("visual").description("Visual Remote Dev Bridge").version("0.1.2");
5534
+ const program = new Command().name("visual").description("Visual Remote Dev Bridge").version("0.2.0");
5356
5535
  program.command("init").description("Create .visualdev/config.yaml for the current project").action(async () => {
5357
5536
  const result = await initializeVisualDev(dependencies);
5358
5537
  output(dependencies, formatInitResult(result));
@@ -5402,8 +5581,15 @@ function createCli(dependencies = {}) {
5402
5581
  async function main(argv = process.argv, dependencies = {}) {
5403
5582
  await createCli(dependencies).parseAsync(argv);
5404
5583
  }
5584
+ function isDirectEntry(entryPath2) {
5585
+ try {
5586
+ return pathToFileURL(realpathSync(resolve8(entryPath2))).href === import.meta.url;
5587
+ } catch {
5588
+ return false;
5589
+ }
5590
+ }
5405
5591
  var entryPath = process.argv[1];
5406
- if (entryPath !== void 0 && pathToFileURL(resolve8(entryPath)).href === import.meta.url) {
5592
+ if (entryPath !== void 0 && isDirectEntry(entryPath)) {
5407
5593
  void main().catch((error) => {
5408
5594
  process.stderr.write(
5409
5595
  `${error instanceof Error ? error.message : "Unknown Visual Bridge error"}
@@ -5424,5 +5610,6 @@ export {
5424
5610
  runBridgeUntilSignal,
5425
5611
  runDoctor,
5426
5612
  startAttachBridge,
5427
- startManagedBridge
5613
+ startManagedBridge,
5614
+ transformViteConfig
5428
5615
  };