visual-remote 0.1.3 → 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.
@@ -1439,8 +1439,8 @@ var CodexAdapter = class {
1439
1439
  };
1440
1440
 
1441
1441
  // ../../packages/bridge-core/src/config/loader.ts
1442
- import { readFile, realpath } from "node:fs/promises";
1443
- 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";
1444
1444
  import { parse as parseYaml } from "yaml";
1445
1445
  import { ZodError } from "zod";
1446
1446
 
@@ -1627,11 +1627,42 @@ function isWithinRoot(root, candidate) {
1627
1627
  const pathFromRoot = relative(root, candidate);
1628
1628
  return pathFromRoot === "" || !pathFromRoot.startsWith(`..${sep}`) && pathFromRoot !== "..";
1629
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
+ }
1630
1655
  async function loadVisualDevConfig(repositoryRoot, options = {}) {
1631
1656
  const repoRoot = await realpath(repositoryRoot);
1632
- const configPath = join(repoRoot, CONFIG_PATH);
1633
- const localConfigPath = join(repoRoot, LOCAL_CONFIG_PATH);
1634
- 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);
1635
1666
  const baseDocument = await readYamlMapping(configPath, options.requireConfig ?? false);
1636
1667
  const localDocument = await readYamlMapping(localConfigPath, false);
1637
1668
  const loadedFiles = [];
@@ -1658,7 +1689,7 @@ async function loadVisualDevConfig(repositoryRoot, options = {}) {
1658
1689
  filePath: localDocument === void 0 ? configPath : localConfigPath
1659
1690
  });
1660
1691
  }
1661
- 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);
1662
1693
  let workspaceRoot;
1663
1694
  try {
1664
1695
  workspaceRoot = await realpath(unresolvedWorkspace);
@@ -1677,6 +1708,7 @@ async function loadVisualDevConfig(repositoryRoot, options = {}) {
1677
1708
  return {
1678
1709
  config,
1679
1710
  repoRoot,
1711
+ configRoot,
1680
1712
  workspaceRoot,
1681
1713
  configPath,
1682
1714
  localConfigPath,
@@ -1964,7 +1996,7 @@ import {
1964
1996
  rm
1965
1997
  } from "node:fs/promises";
1966
1998
  import { tmpdir } from "node:os";
1967
- 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";
1968
2000
  var SNAPSHOT_ENV = {
1969
2001
  GIT_AUTHOR_NAME: "Visual Bridge",
1970
2002
  GIT_AUTHOR_EMAIL: "visual-bridge@localhost",
@@ -2317,7 +2349,7 @@ var GitTransactionManager = class _GitTransactionManager {
2317
2349
  } catch (error) {
2318
2350
  if (error.code !== "ENOENT") throw error;
2319
2351
  }
2320
- await this.#removeEmptyParents(dirname(absolute));
2352
+ await this.#removeEmptyParents(dirname2(absolute));
2321
2353
  }
2322
2354
  async #removeEmptyParents(start) {
2323
2355
  let cursor = start;
@@ -2327,13 +2359,13 @@ var GitTransactionManager = class _GitTransactionManager {
2327
2359
  } catch (error) {
2328
2360
  const code = error.code;
2329
2361
  if (code === "ENOENT") {
2330
- cursor = dirname(cursor);
2362
+ cursor = dirname2(cursor);
2331
2363
  continue;
2332
2364
  }
2333
2365
  if (code === "ENOTEMPTY" || code === "EEXIST") return;
2334
2366
  throw error;
2335
2367
  }
2336
- cursor = dirname(cursor);
2368
+ cursor = dirname2(cursor);
2337
2369
  }
2338
2370
  }
2339
2371
  async #assertSnapshotRef(ref) {
@@ -2353,7 +2385,7 @@ var GitTransactionManager = class _GitTransactionManager {
2353
2385
  // ../../packages/bridge-core/src/storage/sqlite-task-store.ts
2354
2386
  import { mkdirSync } from "node:fs";
2355
2387
  import { createRequire } from "node:module";
2356
- import { dirname as dirname2 } from "node:path";
2388
+ import { dirname as dirname3 } from "node:path";
2357
2389
  var requireNodeBuiltin = createRequire(import.meta.url);
2358
2390
  var optional = (value) => value ?? void 0;
2359
2391
  function parseJson(value, fallback) {
@@ -2445,7 +2477,7 @@ function taskParams(task) {
2445
2477
  var SqliteTaskStore = class {
2446
2478
  #db;
2447
2479
  constructor(filename) {
2448
- if (filename !== ":memory:") mkdirSync(dirname2(filename), { recursive: true, mode: 448 });
2480
+ if (filename !== ":memory:") mkdirSync(dirname3(filename), { recursive: true, mode: 448 });
2449
2481
  const { DatabaseSync } = requireNodeBuiltin("node:sqlite");
2450
2482
  this.#db = new DatabaseSync(filename);
2451
2483
  this.#db.exec(`
@@ -4589,7 +4621,9 @@ ${output2}` : ""}`
4589
4621
 
4590
4622
  // ../../packages/bridge-core/src/bridge/default-control-service.ts
4591
4623
  async function createDefaultControlService(context, environment = process.env) {
4592
- const loaded = await loadVisualDevConfig(context.repoRoot);
4624
+ const loaded = await loadVisualDevConfig(context.repoRoot, {
4625
+ ...context.configRoot === void 0 ? {} : { configRoot: context.configRoot }
4626
+ });
4593
4627
  if (loaded.config.agent.adapter !== "codex") {
4594
4628
  throw new Error(
4595
4629
  `Agent adapter ${loaded.config.agent.adapter} is not implemented in this MVP build`
@@ -4882,6 +4916,7 @@ async function startBridgeCore(options, dependencies) {
4882
4916
  mode: options.mode,
4883
4917
  projectId: loadedConfig.config.project.id,
4884
4918
  repoRoot: loadedConfig.repoRoot,
4919
+ configRoot: loadedConfig.configRoot,
4885
4920
  workspaceRoot: loadedConfig.workspaceRoot,
4886
4921
  upstreamUrl: options.upstreamUrl
4887
4922
  };
@@ -4951,8 +4986,10 @@ async function startBridgeCore(options, dependencies) {
4951
4986
  }
4952
4987
  }
4953
4988
  async function startAttachBridge(options, dependencies = {}) {
4954
- const repoRoot = await discoverGitWorktreeRoot(dependencies.cwd ?? process.cwd());
4955
- 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 });
4956
4993
  return await startBridgeCore(
4957
4994
  {
4958
4995
  mode: "attach",
@@ -4966,8 +5003,13 @@ async function startAttachBridge(options, dependencies = {}) {
4966
5003
  );
4967
5004
  }
4968
5005
  async function startManagedBridge(options = {}, dependencies = {}) {
4969
- const repoRoot = await discoverGitWorktreeRoot(dependencies.cwd ?? process.cwd());
4970
- 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
+ });
4971
5013
  const command = loadedConfig.config.upstream.command;
4972
5014
  if (command === void 0) {
4973
5015
  throw new Error("visual dev requires upstream.command in .visualdev/config.yaml");
@@ -5076,14 +5118,14 @@ function formatBridgeSummary(bridge) {
5076
5118
 
5077
5119
  // src/doctor.ts
5078
5120
  import { constants } from "node:fs";
5079
- import { access as access2, stat as stat2 } from "node:fs/promises";
5080
- 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";
5081
5123
  import { execFile as execFile2 } from "node:child_process";
5082
5124
  import { promisify as promisify2 } from "node:util";
5083
5125
  var execFileAsync2 = promisify2(execFile2);
5084
5126
  async function fileExists(path) {
5085
5127
  try {
5086
- await stat2(path);
5128
+ await stat3(path);
5087
5129
  return true;
5088
5130
  } catch (error) {
5089
5131
  if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
@@ -5131,14 +5173,19 @@ async function runDoctor(dependencies = {}) {
5131
5173
  return checks;
5132
5174
  }
5133
5175
  try {
5134
- 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 });
5135
5181
  checks.push({
5136
5182
  name: "config",
5137
5183
  status: loaded.loadedFiles.length === 0 ? "warning" : "pass",
5138
5184
  message: loaded.loadedFiles.length === 0 ? "No .visualdev/config.yaml; attach defaults are available." : loaded.loadedFiles.join(", ")
5139
5185
  });
5140
5186
  if (await fileExists(loaded.localConfigPath)) {
5141
- const ignored = await isIgnored(repoRoot, ".visualdev/config.local.yaml");
5187
+ const localConfigRelativePath = relative6(repoRoot, loaded.localConfigPath);
5188
+ const ignored = await isIgnored(repoRoot, localConfigRelativePath);
5142
5189
  checks.push({
5143
5190
  name: "local-config-ignore",
5144
5191
  status: ignored ? "pass" : "warning",
@@ -5176,15 +5223,23 @@ function formatDoctorChecks(checks) {
5176
5223
  }
5177
5224
 
5178
5225
  // src/init.ts
5179
- import { readFile as readFile5, mkdir as mkdir3, stat as stat3, writeFile as writeFile3 } from "node:fs/promises";
5180
- 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";
5181
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";';
5182
5237
  function isMissingFile(error) {
5183
5238
  return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
5184
5239
  }
5185
5240
  async function fileExists2(path) {
5186
5241
  try {
5187
- await stat3(path);
5242
+ await stat4(path);
5188
5243
  return true;
5189
5244
  } catch (error) {
5190
5245
  if (isMissingFile(error)) return false;
@@ -5196,7 +5251,7 @@ function packageManagerFromField(value) {
5196
5251
  const name = value.split("@", 1)[0];
5197
5252
  return name === "bun" || name === "npm" || name === "pnpm" || name === "yarn" ? name : void 0;
5198
5253
  }
5199
- async function detectPackageManager(repoRoot, manifest) {
5254
+ async function detectPackageManager(projectRoot, repoRoot, manifest) {
5200
5255
  const declared = packageManagerFromField(manifest.packageManager);
5201
5256
  if (declared !== void 0) return declared;
5202
5257
  const lockfiles = [
@@ -5206,8 +5261,10 @@ async function detectPackageManager(repoRoot, manifest) {
5206
5261
  ["bun", "bun.lockb"],
5207
5262
  ["npm", "package-lock.json"]
5208
5263
  ];
5209
- for (const [manager, filename] of lockfiles) {
5210
- 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
+ }
5211
5268
  }
5212
5269
  return "npm";
5213
5270
  }
@@ -5217,6 +5274,19 @@ function readDevScript(manifest) {
5217
5274
  }
5218
5275
  return manifest.scripts.dev.trim();
5219
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
+ }
5220
5290
  function devCommand(manager, script) {
5221
5291
  const command = manager === "pnpm" ? ["corepack", "pnpm", "run", "dev"] : manager === "yarn" ? ["corepack", "yarn", "run", "dev"] : manager === "bun" ? ["bun", "run", "dev"] : ["npm", "run", "dev"];
5222
5292
  const next = /(^|[\s;&|])next(?:\s|$)/.test(script);
@@ -5229,14 +5299,14 @@ function devCommand(manager, script) {
5229
5299
  "{upstreamPort}"
5230
5300
  ];
5231
5301
  }
5232
- async function readManifest(repoRoot) {
5233
- const manifestPath = join5(repoRoot, "package.json");
5302
+ async function readManifest(projectRoot) {
5303
+ const manifestPath = join5(projectRoot, "package.json");
5234
5304
  let source;
5235
5305
  try {
5236
5306
  source = await readFile5(manifestPath, "utf8");
5237
5307
  } catch (error) {
5238
5308
  if (isMissingFile(error)) {
5239
- 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");
5240
5310
  }
5241
5311
  throw error;
5242
5312
  }
@@ -5251,55 +5321,163 @@ async function readManifest(repoRoot) {
5251
5321
  }
5252
5322
  return value;
5253
5323
  }
5254
- async function initializeVisualDev(dependencies = {}) {
5255
- const repoRoot = await discoverGitWorktreeRoot(dependencies.cwd ?? process.cwd());
5256
- const configPath = join5(repoRoot, CONFIG_PATH);
5257
- if (await fileExists2(configPath)) {
5258
- 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;
5259
5328
  }
5260
- const manifest = await readManifest(repoRoot);
5261
- const devScript = readDevScript(manifest);
5262
- const packageManager = await detectPackageManager(repoRoot, manifest);
5263
- const document = {
5264
- version: 1,
5265
- project: {
5266
- id: basename2(repoRoot),
5267
- workspace: "."
5268
- },
5269
- gateway: {
5270
- host: "0.0.0.0",
5271
- port: "auto"
5272
- },
5273
- upstream: {
5274
- port: "auto",
5275
- command: devCommand(packageManager, devScript)
5276
- }
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]
5277
5389
  };
5278
- await mkdir3(dirname3(configPath), { recursive: true });
5279
- try {
5280
- await writeFile3(configPath, stringifyYaml(document), {
5281
- encoding: "utf8",
5282
- 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
5283
5399
  });
5284
- } catch (error) {
5285
- if (typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST") {
5286
- 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
+ }
5287
5461
  }
5288
- throw error;
5289
5462
  }
5290
- return { created: true, configPath, devScript, packageManager };
5463
+ return {
5464
+ created,
5465
+ configPath,
5466
+ devScript,
5467
+ packageManager,
5468
+ integrationPath,
5469
+ integrationChanged,
5470
+ packageInstalled
5471
+ };
5291
5472
  }
5292
5473
  function formatInitResult(result) {
5293
- if (!result.created) {
5294
- return [
5295
- `Already initialized: ${CONFIG_PATH}`,
5296
- "Next: npx --yes visual-remote@latest dev"
5297
- ].join("\n");
5298
- }
5474
+ const configLabel = result.created ? "Created" : "Existing";
5475
+ const integrationLabel = result.integrationChanged ? "Configured" : "Existing";
5299
5476
  return [
5300
- `Created: ${CONFIG_PATH}`,
5301
- `Detected: ${result.packageManager} dev (${result.devScript})`,
5302
- "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."
5303
5481
  ].join("\n");
5304
5482
  }
5305
5483
 
@@ -5353,7 +5531,7 @@ function setExitCode(dependencies, code) {
5353
5531
  }
5354
5532
  }
5355
5533
  function createCli(dependencies = {}) {
5356
- const program = new Command().name("visual").description("Visual Remote Dev Bridge").version("0.1.3");
5534
+ const program = new Command().name("visual").description("Visual Remote Dev Bridge").version("0.2.0");
5357
5535
  program.command("init").description("Create .visualdev/config.yaml for the current project").action(async () => {
5358
5536
  const result = await initializeVisualDev(dependencies);
5359
5537
  output(dependencies, formatInitResult(result));
@@ -5432,5 +5610,6 @@ export {
5432
5610
  runBridgeUntilSignal,
5433
5611
  runDoctor,
5434
5612
  startAttachBridge,
5435
- startManagedBridge
5613
+ startManagedBridge,
5614
+ transformViteConfig
5436
5615
  };