crosssync 0.1.0 → 0.1.2

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
@@ -3126,12 +3126,36 @@ var require_config = __commonJS({
3126
3126
  Object.defineProperty(exports2, "__esModule", { value: true });
3127
3127
  exports2.SYNC_STRATEGIES = void 0;
3128
3128
  exports2.resolveExportRetention = resolveExportRetention3;
3129
+ exports2.parseProfileList = parseProfileList2;
3130
+ exports2.addProfilesToSelection = addProfilesToSelection3;
3129
3131
  exports2.createDefaultConfig = createDefaultConfig3;
3130
3132
  var constants_1 = require_constants();
3131
3133
  exports2.SYNC_STRATEGIES = ["merge", "export"];
3132
3134
  function resolveExportRetention3(config) {
3133
3135
  return config.exports?.keep ?? constants_1.DEFAULT_EXPORT_RETENTION;
3134
3136
  }
3137
+ function parseProfileList2(value) {
3138
+ const names = [];
3139
+ for (const part of value.split(",")) {
3140
+ const name = part.trim();
3141
+ if (name.length > 0 && !names.includes(name)) {
3142
+ names.push(name);
3143
+ }
3144
+ }
3145
+ return names;
3146
+ }
3147
+ function addProfilesToSelection3(current, additions) {
3148
+ if (current.trim() === "all") {
3149
+ return "all";
3150
+ }
3151
+ const names = parseProfileList2(current);
3152
+ for (const name of additions) {
3153
+ if (name.trim().length > 0 && !names.includes(name.trim())) {
3154
+ names.push(name.trim());
3155
+ }
3156
+ }
3157
+ return names.join(",");
3158
+ }
3135
3159
  function createDefaultConfig3(options) {
3136
3160
  return {
3137
3161
  version: constants_1.CONFIG_VERSION,
@@ -3182,7 +3206,7 @@ var require_utils = __commonJS({
3182
3206
  exports2.toChromiumTime = toChromiumTime;
3183
3207
  exports2.resolveHomeDir = resolveHomeDir3;
3184
3208
  exports2.resolveBrowserDataDir = resolveBrowserDataDir;
3185
- exports2.listProfiles = listProfiles;
3209
+ exports2.listProfiles = listProfiles2;
3186
3210
  exports2.resolveProfileDir = resolveProfileDir;
3187
3211
  exports2.resolveCrossSyncDirs = resolveCrossSyncDirs2;
3188
3212
  exports2.loadSqliteDriver = loadSqliteDriver;
@@ -3194,7 +3218,7 @@ var require_utils = __commonJS({
3194
3218
  exports2.isBookmarkFile = isBookmarkFile;
3195
3219
  exports2.isHistoryEntry = isHistoryEntry;
3196
3220
  exports2.isLogLevel = isLogLevel2;
3197
- exports2.isBrowserName = isBrowserName2;
3221
+ exports2.isBrowserName = isBrowserName3;
3198
3222
  exports2.isCliConfig = isCliConfig3;
3199
3223
  var fs_1 = __importDefault(require("fs"));
3200
3224
  var os_1 = __importDefault(require("os"));
@@ -3314,7 +3338,7 @@ var require_utils = __commonJS({
3314
3338
  const key = platform === "darwin" ? "darwin" : "linux";
3315
3339
  return path_1.default.join(home, ...segments[key]);
3316
3340
  }
3317
- function listProfiles(dataDir) {
3341
+ function listProfiles2(dataDir) {
3318
3342
  let entries;
3319
3343
  try {
3320
3344
  entries = fs_1.default.readdirSync(dataDir, { withFileTypes: true });
@@ -3419,7 +3443,7 @@ var require_utils = __commonJS({
3419
3443
  function isLogLevel2(value) {
3420
3444
  return typeof value === "string" && constants_1.LOG_LEVELS.includes(value);
3421
3445
  }
3422
- function isBrowserName2(value) {
3446
+ function isBrowserName3(value) {
3423
3447
  return typeof value === "string" && constants_1.BROWSERS.includes(value);
3424
3448
  }
3425
3449
  function isCliConfig3(value) {
@@ -3787,7 +3811,7 @@ var require_chromium = __commonJS({
3787
3811
  Object.defineProperty(exports2, "__esModule", { value: true });
3788
3812
  exports2.toHistoryEntry = toHistoryEntry;
3789
3813
  exports2.countBookmarkFileNodes = countBookmarkFileNodes;
3790
- exports2.createBrowserReader = createBrowserReader2;
3814
+ exports2.createBrowserReader = createBrowserReader3;
3791
3815
  var path_1 = __importDefault(require("path"));
3792
3816
  var shared_1 = require_dist();
3793
3817
  function toHistoryEntry(row) {
@@ -3810,17 +3834,18 @@ var require_chromium = __commonJS({
3810
3834
  }
3811
3835
  return total;
3812
3836
  }
3813
- function createBrowserReader2(browser, options = {}) {
3837
+ function createBrowserReader3(browser, options = {}) {
3814
3838
  const dataDir = options.dataDir ?? (0, shared_1.resolveBrowserDataDir)(browser, { platform: options.platform, env: options.env });
3815
3839
  const bookmarksPath = (profile) => path_1.default.join((0, shared_1.resolveProfileDir)(dataDir, profile), shared_1.BOOKMARKS_FILE_NAME);
3816
3840
  const historyPath = (profile) => path_1.default.join((0, shared_1.resolveProfileDir)(dataDir, profile), shared_1.HISTORY_FILE_NAME);
3817
3841
  const profiles = () => (0, shared_1.listProfiles)(dataDir);
3818
3842
  const resolveSelectedProfiles = (profile) => {
3819
3843
  const found = profiles();
3820
- if (profile === "all") {
3844
+ if (profile.trim() === "all") {
3821
3845
  return found;
3822
3846
  }
3823
- return found.includes(profile) ? [profile] : [];
3847
+ const requested = (0, shared_1.parseProfileList)(profile);
3848
+ return requested.filter((name) => found.includes(name));
3824
3849
  };
3825
3850
  const readBookmarks = (profile) => {
3826
3851
  const filePath = bookmarksPath(profile);
@@ -3886,12 +3911,12 @@ var require_readers = __commonJS({
3886
3911
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
3887
3912
  };
3888
3913
  Object.defineProperty(exports2, "__esModule", { value: true });
3889
- exports2.createConfiguredBrowserReaders = createConfiguredBrowserReaders3;
3914
+ exports2.createConfiguredBrowserReaders = createConfiguredBrowserReaders5;
3890
3915
  exports2.supportedBrowsers = supportedBrowsers;
3891
3916
  var shared_1 = require_dist();
3892
3917
  var chromium_1 = require_chromium();
3893
3918
  __exportStar(require_chromium(), exports2);
3894
- function createConfiguredBrowserReaders3(config, options = {}) {
3919
+ function createConfiguredBrowserReaders5(config, options = {}) {
3895
3920
  const readers = [];
3896
3921
  for (const browser of shared_1.BROWSERS) {
3897
3922
  const browserConfig = config.browsers[browser];
@@ -4197,7 +4222,9 @@ var require_sync = __commonJS({
4197
4222
  for (const reader of readers) {
4198
4223
  const profiles = reader.resolveProfiles(config.profile);
4199
4224
  if (profiles.length === 0) {
4200
- warnings.push(`No ${reader.browser} profile found under ${reader.dataDir}.`);
4225
+ const available = reader.profiles();
4226
+ const suffix = available.length > 0 ? ` Available: ${available.join(", ")}.` : "";
4227
+ warnings.push(`No ${reader.browser} profile found under ${reader.dataDir}.${suffix}`);
4201
4228
  continue;
4202
4229
  }
4203
4230
  for (const profile of profiles) {
@@ -4501,7 +4528,7 @@ var {
4501
4528
  } = import_index.default;
4502
4529
 
4503
4530
  // src/constants.ts
4504
- var CLI_VERSION = "0.1.0";
4531
+ var CLI_VERSION = "0.1.2";
4505
4532
  var CLI_NAME = "crosssync";
4506
4533
  var CLI_DESCRIPTION = "Cross-browser bookmark & history sync CLI (Chrome + Edge)";
4507
4534
  var WINDOWS_TASK_NAME = "CrossSync";
@@ -4573,7 +4600,9 @@ function readMergedData(config, options = {}) {
4573
4600
  }
4574
4601
  const profiles = reader.resolveProfiles(options.profile ?? config.profile);
4575
4602
  if (profiles.length === 0) {
4576
- warnings.push(`No ${reader.browser} profile found under ${reader.dataDir}.`);
4603
+ const available = reader.profiles();
4604
+ const suffix = available.length > 0 ? ` Available: ${available.join(", ")}.` : "";
4605
+ warnings.push(`No ${reader.browser} profile found under ${reader.dataDir}.${suffix}`);
4577
4606
  continue;
4578
4607
  }
4579
4608
  for (const profile of profiles) {
@@ -5450,6 +5479,7 @@ function pruneExports(exportDir, keep) {
5450
5479
  }
5451
5480
 
5452
5481
  // src/commands/sync.ts
5482
+ var readline = __toESM(require("readline/promises"));
5453
5483
  var import_shared10 = __toESM(require_dist());
5454
5484
  var import_core4 = __toESM(require_dist2());
5455
5485
  function resolveTargets(options) {
@@ -5498,9 +5528,114 @@ function buildSyncConfig(config, options) {
5498
5528
  }
5499
5529
  };
5500
5530
  }
5501
- function runSyncCommand(context, options = {}) {
5531
+ async function ensureProfilesSelected(context, options) {
5532
+ if (options.profile !== void 0 || options.json) {
5533
+ return;
5534
+ }
5535
+ const interactive = options.selectProfiles !== void 0 || process.stdin.isTTY === true && process.stdout.isTTY === true;
5536
+ if (!interactive) {
5537
+ return;
5538
+ }
5539
+ const effective = buildSyncConfig(context.config, options);
5540
+ const readers = (0, import_core4.createConfiguredBrowserReaders)(effective, { platform: options.platform });
5541
+ const select = options.selectProfiles ?? promptForProfiles;
5542
+ let changed = false;
5543
+ for (const reader of readers) {
5544
+ if (reader.resolveProfiles(context.config.profile).length > 0) {
5545
+ continue;
5546
+ }
5547
+ const available = reader.profiles();
5548
+ if (available.length === 0) {
5549
+ continue;
5550
+ }
5551
+ const selected = await select({
5552
+ browser: reader.browser,
5553
+ dataDir: reader.dataDir,
5554
+ available,
5555
+ current: context.config.profile
5556
+ });
5557
+ if (!selected || selected.length === 0) {
5558
+ continue;
5559
+ }
5560
+ const valid = selected.filter((name) => available.includes(name));
5561
+ if (valid.length === 0) {
5562
+ continue;
5563
+ }
5564
+ context.config.profile = (0, import_shared10.addProfilesToSelection)(context.config.profile, valid);
5565
+ changed = true;
5566
+ }
5567
+ if (changed) {
5568
+ saveConfigFile(context.dirs.configFile, context.config);
5569
+ context.io.out(`Profile selection saved: ${context.config.profile}`);
5570
+ }
5571
+ }
5572
+ async function promptForProfiles(request) {
5573
+ const output = process.stdout;
5574
+ output.write(`
5575
+ No ${request.browser} profile matched "${request.current}".
5576
+ `);
5577
+ output.write(`Available ${request.browser} profiles in ${request.dataDir}:
5578
+ `);
5579
+ request.available.forEach((name, index) => {
5580
+ output.write(` ${index + 1}) ${name}
5581
+ `);
5582
+ });
5583
+ const rl = readline.createInterface({ input: process.stdin, output });
5584
+ try {
5585
+ for (; ; ) {
5586
+ const answer = await rl.question(
5587
+ 'Select profiles (comma-separated numbers or names, "all", empty to skip): '
5588
+ );
5589
+ const parsed = parseProfileAnswer(answer, request.available);
5590
+ if (parsed !== void 0) {
5591
+ return parsed;
5592
+ }
5593
+ output.write("Invalid selection; please try again.\n");
5594
+ }
5595
+ } catch {
5596
+ return null;
5597
+ } finally {
5598
+ rl.close();
5599
+ }
5600
+ }
5601
+ function parseProfileAnswer(answer, available) {
5602
+ const trimmed = answer.trim();
5603
+ if (trimmed.length === 0) {
5604
+ return null;
5605
+ }
5606
+ if (trimmed.toLowerCase() === "all") {
5607
+ return [...available];
5608
+ }
5609
+ const selected = [];
5610
+ for (const token of trimmed.split(",")) {
5611
+ const value = token.trim();
5612
+ if (value.length === 0) {
5613
+ continue;
5614
+ }
5615
+ if (/^\d+$/.test(value)) {
5616
+ const index = Number(value) - 1;
5617
+ if (index < 0 || index >= available.length) {
5618
+ return void 0;
5619
+ }
5620
+ const name = available[index];
5621
+ if (!selected.includes(name)) {
5622
+ selected.push(name);
5623
+ }
5624
+ continue;
5625
+ }
5626
+ if (!available.includes(value)) {
5627
+ return void 0;
5628
+ }
5629
+ if (!selected.includes(value)) {
5630
+ selected.push(value);
5631
+ }
5632
+ }
5633
+ return selected.length > 0 ? selected : void 0;
5634
+ }
5635
+ async function runSyncCommand(context, options = {}) {
5502
5636
  const targets = resolveTargets(options);
5503
5637
  const strategy = resolveStrategy(options.strategy) ?? context.config.sync.strategy;
5638
+ await ensureProfilesSelected(context, options);
5504
5639
  const config = buildSyncConfig(context.config, options);
5505
5640
  const report = (0, import_core4.runSync)({
5506
5641
  config,
@@ -5694,14 +5829,132 @@ function formatLogEntry(entry) {
5694
5829
  return `${timestamp} [${entry.level.toUpperCase()}] ${entry.message}${meta}`;
5695
5830
  }
5696
5831
 
5697
- // src/commands/status.ts
5698
- var import_path7 = __toESM(require("path"));
5832
+ // src/commands/profiles.ts
5699
5833
  var import_shared13 = __toESM(require_dist());
5700
5834
  var import_core7 = __toESM(require_dist2());
5835
+ function parseProfileNames(value) {
5836
+ if (value.trim().toLowerCase() === "all") {
5837
+ return "all";
5838
+ }
5839
+ const names = (0, import_shared13.parseProfileList)(value);
5840
+ if (names.length === 0) {
5841
+ throw new Error("Profile list is empty.");
5842
+ }
5843
+ for (const name of names) {
5844
+ if (!import_shared13.PROFILE_NAME_PATTERN.test(name)) {
5845
+ throw new Error(`Invalid profile name "${name}". Use "Default" or "Profile N".`);
5846
+ }
5847
+ }
5848
+ return names;
5849
+ }
5850
+ function listProfiles(context, options) {
5851
+ const filter = options.browser ?? "all";
5852
+ if (filter !== "all" && !(0, import_shared13.isBrowserName)(filter)) {
5853
+ context.io.err(`Unknown browser "${filter}". Use one of: ${import_shared13.BROWSERS.join(", ")}, all.`);
5854
+ return 1;
5855
+ }
5856
+ const selection = context.config.profile;
5857
+ const selected = selection.trim() === "all" ? null : (0, import_shared13.parseProfileList)(selection);
5858
+ for (const browser of import_shared13.BROWSERS) {
5859
+ if (filter !== "all" && browser !== filter) {
5860
+ continue;
5861
+ }
5862
+ const browserConfig = context.config.browsers[browser];
5863
+ const reader = (0, import_core7.createBrowserReader)(browser, {
5864
+ dataDir: browserConfig.dataDir,
5865
+ platform: options.platform,
5866
+ env: options.env
5867
+ });
5868
+ const available = reader.profiles();
5869
+ context.io.out(`${browser}: ${reader.dataDir}${browserConfig.enabled ? "" : " [disabled]"}`);
5870
+ if (available.length === 0) {
5871
+ context.io.out(" (no profiles found)");
5872
+ continue;
5873
+ }
5874
+ for (const name of available) {
5875
+ const isSelected = selected === null || selected.includes(name);
5876
+ context.io.out(` ${name}${isSelected ? " [selected]" : ""}`);
5877
+ }
5878
+ const missing = selected?.filter((name) => !available.includes(name)) ?? [];
5879
+ if (missing.length > 0) {
5880
+ context.io.out(` (configured but not found: ${missing.join(", ")})`);
5881
+ }
5882
+ }
5883
+ context.io.out(`Selected profile(s): ${selection}`);
5884
+ return 0;
5885
+ }
5886
+ function expandAllProfiles(context, options) {
5887
+ const names = [];
5888
+ const readers = (0, import_core7.createConfiguredBrowserReaders)(context.config, {
5889
+ platform: options.platform,
5890
+ env: options.env
5891
+ });
5892
+ for (const reader of readers) {
5893
+ for (const name of reader.profiles()) {
5894
+ if (!names.includes(name)) {
5895
+ names.push(name);
5896
+ }
5897
+ }
5898
+ }
5899
+ return names;
5900
+ }
5901
+ function removeProfiles(context, current, names, options) {
5902
+ if (names === "all") {
5903
+ throw new Error("Refusing to remove every profile; use --reset or --set instead.");
5904
+ }
5905
+ const base = current.trim() === "all" ? expandAllProfiles(context, options).join(",") : current;
5906
+ const remaining = (0, import_shared13.parseProfileList)(base).filter((name) => !names.includes(name));
5907
+ if (remaining.length === (0, import_shared13.parseProfileList)(base).length) {
5908
+ throw new Error(`None of the selected profiles matched: ${names.join(", ")}.`);
5909
+ }
5910
+ if (remaining.length === 0) {
5911
+ throw new Error("Refusing to remove every profile; use --reset or --set instead.");
5912
+ }
5913
+ return remaining.join(",");
5914
+ }
5915
+ function runProfilesCommand(context, options = {}) {
5916
+ const mutating = options.set !== void 0 || options.add !== void 0 || options.remove !== void 0 || options.all === true || options.reset === true;
5917
+ if (!mutating) {
5918
+ return listProfiles(context, options);
5919
+ }
5920
+ if (options.browser !== void 0 && options.browser !== "all") {
5921
+ context.io.err("--browser only applies when listing; profile changes are global.");
5922
+ return 1;
5923
+ }
5924
+ try {
5925
+ let next = context.config.profile;
5926
+ if (options.reset) {
5927
+ next = import_shared13.DEFAULT_PROFILE;
5928
+ } else if (options.all) {
5929
+ next = "all";
5930
+ } else if (options.set !== void 0) {
5931
+ const names = parseProfileNames(options.set);
5932
+ next = names === "all" ? "all" : names.join(",");
5933
+ } else if (options.add !== void 0) {
5934
+ const names = parseProfileNames(options.add);
5935
+ next = names === "all" ? "all" : (0, import_shared13.addProfilesToSelection)(next, names);
5936
+ } else if (options.remove !== void 0) {
5937
+ next = removeProfiles(context, next, parseProfileNames(options.remove), options);
5938
+ }
5939
+ const nextConfig = { ...context.config, profile: next };
5940
+ saveConfigFile(context.dirs.configFile, nextConfig);
5941
+ context.config = nextConfig;
5942
+ context.io.out(`profile = ${JSON.stringify(next)}`);
5943
+ return 0;
5944
+ } catch (error) {
5945
+ context.io.err(error instanceof Error ? error.message : String(error));
5946
+ return 1;
5947
+ }
5948
+ }
5949
+
5950
+ // src/commands/status.ts
5951
+ var import_path7 = __toESM(require("path"));
5952
+ var import_shared14 = __toESM(require_dist());
5953
+ var import_core8 = __toESM(require_dist2());
5701
5954
  function buildStatusReport(context, options = {}) {
5702
5955
  const { config, dirs } = context;
5703
5956
  const running = new Map(
5704
- (0, import_core7.getRunningBrowsers)({ platform: options.platform }).map((status) => [
5957
+ (0, import_core8.getRunningBrowsers)({ platform: options.platform }).map((status) => [
5705
5958
  status.browser,
5706
5959
  status.running
5707
5960
  ])
@@ -5716,14 +5969,14 @@ function buildStatusReport(context, options = {}) {
5716
5969
  for (const profile of reader.resolveProfiles(config.profile)) {
5717
5970
  profiles.push({
5718
5971
  profile,
5719
- bookmarks: (0, import_shared13.pathExists)(reader.bookmarksPath(profile)),
5720
- history: (0, import_shared13.pathExists)(reader.historyPath(profile))
5972
+ bookmarks: (0, import_shared14.pathExists)(reader.bookmarksPath(profile)),
5973
+ history: (0, import_shared14.pathExists)(reader.historyPath(profile))
5721
5974
  });
5722
5975
  }
5723
5976
  browsers.push({
5724
5977
  browser,
5725
5978
  dataDir: reader.dataDir,
5726
- exists: (0, import_shared13.pathExists)(reader.dataDir),
5979
+ exists: (0, import_shared14.pathExists)(reader.dataDir),
5727
5980
  running: running.get(browser) ?? false,
5728
5981
  profiles
5729
5982
  });
@@ -5737,14 +5990,14 @@ function buildStatusReport(context, options = {}) {
5737
5990
  });
5738
5991
  }
5739
5992
  }
5740
- const backups = (0, import_core7.listBackups)(config.backupDir);
5993
+ const backups = (0, import_core8.listBackups)(config.backupDir);
5741
5994
  const exports2 = listExports(config.exportDir, 1);
5742
5995
  return {
5743
5996
  version: CLI_VERSION,
5744
5997
  configFile: dirs.configFile,
5745
5998
  dataDir: config.dataDir,
5746
5999
  logLevel: config.logLevel,
5747
- logFile: import_path7.default.join(config.logDir, import_shared13.LOG_FILE_NAME),
6000
+ logFile: import_path7.default.join(config.logDir, import_shared14.LOG_FILE_NAME),
5748
6001
  profile: config.profile,
5749
6002
  schedule: { ...config.schedule },
5750
6003
  browsers,
@@ -5757,7 +6010,7 @@ function buildStatusReport(context, options = {}) {
5757
6010
  };
5758
6011
  }
5759
6012
  function createReader(browser, dataDir, options) {
5760
- return (0, import_core7.createBrowserReader)(browser, {
6013
+ return (0, import_core8.createBrowserReader)(browser, {
5761
6014
  dataDir,
5762
6015
  platform: options.platform,
5763
6016
  env: options.env
@@ -5806,11 +6059,16 @@ function createCliContext(options = {}) {
5806
6059
  function buildProgram(contextFactory = createCliContext) {
5807
6060
  const program2 = new Command();
5808
6061
  program2.name(CLI_NAME).description(CLI_DESCRIPTION).version(CLI_VERSION, "-v, --version", "print the CrossSync version").option("--home-dir <path>", "use an alternate home directory").option("--verbose", "enable debug logging").option("--quiet", "only log errors");
5809
- const withContext = (action) => () => {
6062
+ const withContext = (action) => async () => {
5810
6063
  const context = contextFactory(program2.opts());
5811
- process.exitCode = action(context);
6064
+ try {
6065
+ process.exitCode = await action(context);
6066
+ } catch (error) {
6067
+ context.io.err(error instanceof Error ? error.message : String(error));
6068
+ process.exitCode = 1;
6069
+ }
5812
6070
  };
5813
- const syncCommand = program2.command("sync").description("read, merge and write back browser bookmarks/history").option("--bookmarks", "sync bookmarks only").option("--history", "sync history only").option("--all", "sync bookmarks and history (default)").option("--browser <name>", "chrome, edge or all", "all").option("--profile <name>", 'profile name or "all"').option("--strategy <name>", "merge (write back) or export (read only)").option("--dry-run", "show what would happen without touching any file").option("--force", "write bookmarks back even while the browser is running").option("--json", "print the report as JSON");
6071
+ const syncCommand = program2.command("sync").description("read, merge and write back browser bookmarks/history").option("--bookmarks", "sync bookmarks only").option("--history", "sync history only").option("--all", "sync bookmarks and history (default)").option("--browser <name>", "chrome, edge or all", "all").option("--profile <names>", 'profile name(s), comma-separated, or "all"').option("--strategy <name>", "merge (write back) or export (read only)").option("--dry-run", "show what would happen without touching any file").option("--force", "write bookmarks back even while the browser is running").option("--json", "print the report as JSON");
5814
6072
  syncCommand.action(withContext((context) => runSyncCommand(context, syncCommand.opts())));
5815
6073
  const backupCommand = program2.command("backup").description("back up browser bookmark and history files").option("--list", "list existing backups").option("--prune", "delete old backups").option("--keep <count>", "how many backups to keep when pruning");
5816
6074
  backupCommand.action(
@@ -5823,10 +6081,14 @@ function buildProgram(contextFactory = createCliContext) {
5823
6081
  });
5824
6082
  })
5825
6083
  );
5826
- const exportCommand = program2.command("export").description("export merged bookmarks/history as JSON").option("--format <format>", "output format (json)", "json").option("--out <dir>", "directory to write into").option("--browser <name>", "chrome, edge or all", "all").option("--profile <name>", 'profile name or "all"').option("--stdout", "print the export instead of writing a file");
6084
+ const exportCommand = program2.command("export").description("export merged bookmarks/history as JSON").option("--format <format>", "output format (json)", "json").option("--out <dir>", "directory to write into").option("--browser <name>", "chrome, edge or all", "all").option("--profile <names>", 'profile name(s), comma-separated, or "all"').option("--stdout", "print the export instead of writing a file");
5827
6085
  exportCommand.action(withContext((context) => runExportCommand(context, exportCommand.opts())));
5828
6086
  const statusCommand = program2.command("status").description("show browsers, profiles, backups and schedule state").option("--json", "print the status as JSON");
5829
6087
  statusCommand.action(withContext((context) => runStatusCommand(context, statusCommand.opts())));
6088
+ const profilesCommand = program2.command("profiles").description("list available Chromium profiles or change the synced selection").option("--list", "list profiles and the current selection (default)").option("--set <names>", 'replace the selection, e.g. "Default,Profile 11" or "all"').option("--add <names>", "add profiles to the selection").option("--remove <names>", "remove profiles from the selection").option("--all", "select every available profile").option("--reset", 'reset the selection to "Default"').option("--browser <name>", "limit listing to chrome, edge or all", "all");
6089
+ profilesCommand.action(
6090
+ withContext((context) => runProfilesCommand(context, profilesCommand.opts()))
6091
+ );
5830
6092
  const logsCommand = program2.command("logs").description("print CrossSync log entries").option("--limit <count>", "number of entries to show", "50").option("--level <level>", "debug, info, warn or error").option("--clear", "delete the log file").option("--json", "print the entries as JSON");
5831
6093
  logsCommand.action(
5832
6094
  withContext((context) => {
@@ -5851,13 +6113,13 @@ function buildProgram(contextFactory = createCliContext) {
5851
6113
  configCommand.action(withContext((context) => runConfigCommand(context, configCommand.opts())));
5852
6114
  return program2;
5853
6115
  }
5854
- function run(argv = process.argv) {
5855
- buildProgram().parse(argv);
6116
+ async function run(argv = process.argv) {
6117
+ await buildProgram().parseAsync(argv);
5856
6118
  }
5857
6119
  var PACKAGE = "crosssync";
5858
6120
  var VERSION = CLI_VERSION;
5859
6121
  if (require.main === module) {
5860
- run();
6122
+ void run();
5861
6123
  }
5862
6124
  // Annotate the CommonJS export names for ESM import in node:
5863
6125
  0 && (module.exports = {