@anraktech/sync 0.6.0 → 0.8.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/cli.js +171 -65
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -6,7 +6,7 @@ import { createInterface as createInterface2 } from "readline/promises";
|
|
|
6
6
|
import { stdin as stdin2, stdout as stdout2 } from "process";
|
|
7
7
|
import { existsSync as existsSync4, statSync as statSync3 } from "fs";
|
|
8
8
|
import { resolve as resolve3 } from "path";
|
|
9
|
-
import
|
|
9
|
+
import chalk4 from "chalk";
|
|
10
10
|
|
|
11
11
|
// src/config.ts
|
|
12
12
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
@@ -15,17 +15,16 @@ import { join } from "path";
|
|
|
15
15
|
|
|
16
16
|
// src/logger.ts
|
|
17
17
|
import chalk from "chalk";
|
|
18
|
-
var PREFIX = chalk.bold.blue("[anrak-sync]");
|
|
19
18
|
var log = {
|
|
20
|
-
info: (msg) => console.log(
|
|
21
|
-
success: (msg) => console.log(
|
|
22
|
-
warn: (msg) => console.log(
|
|
23
|
-
error: (msg) => console.error(
|
|
19
|
+
info: (msg) => console.log(chalk.dim(` ${msg}`)),
|
|
20
|
+
success: (msg) => console.log(` ${chalk.green("\u2713")} ${msg}`),
|
|
21
|
+
warn: (msg) => console.log(` ${chalk.yellow("!")} ${msg}`),
|
|
22
|
+
error: (msg) => console.error(` ${chalk.red("\u2717")} ${msg}`),
|
|
24
23
|
debug: (msg) => {
|
|
25
|
-
if (process.env.ANRAK_DEBUG) console.log(
|
|
24
|
+
if (process.env.ANRAK_DEBUG) console.log(chalk.dim(` ${msg}`));
|
|
26
25
|
},
|
|
27
|
-
dim: (msg) => console.log(
|
|
28
|
-
file: (action, path) => console.log(
|
|
26
|
+
dim: (msg) => console.log(chalk.dim(` ${msg}`)),
|
|
27
|
+
file: (action, path) => console.log(` ${chalk.dim("\u203A")} ${chalk.cyan(action)} ${chalk.dim(path)}`)
|
|
29
28
|
};
|
|
30
29
|
|
|
31
30
|
// src/config.ts
|
|
@@ -417,7 +416,7 @@ function resetCache() {
|
|
|
417
416
|
// src/watcher.ts
|
|
418
417
|
import { watch } from "chokidar";
|
|
419
418
|
import { readdirSync as readdirSync2, statSync as statSync2, existsSync as existsSync3 } from "fs";
|
|
420
|
-
import { join as join3, relative as relative2, basename as
|
|
419
|
+
import { join as join3, relative as relative2, basename as basename5, resolve as resolve2 } from "path";
|
|
421
420
|
|
|
422
421
|
// src/uploader.ts
|
|
423
422
|
import { stat as stat2 } from "fs/promises";
|
|
@@ -620,9 +619,20 @@ function sleep(ms) {
|
|
|
620
619
|
import { createInterface } from "readline/promises";
|
|
621
620
|
import { stdin, stdout } from "process";
|
|
622
621
|
import { homedir as homedir2, platform } from "os";
|
|
623
|
-
import { resolve, join as join2 } from "path";
|
|
624
|
-
import { existsSync as existsSync2, readdirSync, statSync } from "fs";
|
|
622
|
+
import { resolve, join as join2, dirname as dirname2 } from "path";
|
|
623
|
+
import { existsSync as existsSync2, readdirSync, statSync, readFileSync as readFileSync2 } from "fs";
|
|
624
|
+
import { fileURLToPath } from "url";
|
|
625
625
|
import chalk2 from "chalk";
|
|
626
|
+
var __filename2 = fileURLToPath(import.meta.url);
|
|
627
|
+
var __dirname2 = dirname2(__filename2);
|
|
628
|
+
var PKG_VERSION = (() => {
|
|
629
|
+
try {
|
|
630
|
+
const pkg2 = JSON.parse(readFileSync2(join2(__dirname2, "..", "package.json"), "utf-8"));
|
|
631
|
+
return pkg2.version;
|
|
632
|
+
} catch {
|
|
633
|
+
return "0.0.0";
|
|
634
|
+
}
|
|
635
|
+
})();
|
|
626
636
|
var HOME = homedir2();
|
|
627
637
|
var IS_MAC = platform() === "darwin";
|
|
628
638
|
var FOLDER_SHORTCUTS = {
|
|
@@ -952,7 +962,8 @@ async function agentTurn(messages, ctx) {
|
|
|
952
962
|
};
|
|
953
963
|
messages.push(assistantMsg);
|
|
954
964
|
for (const tc of toolCalls.values()) {
|
|
955
|
-
|
|
965
|
+
const toolLabel = tc.name.replace(/_/g, " ");
|
|
966
|
+
process.stdout.write(chalk2.dim(` \u25CF ${toolLabel}
|
|
956
967
|
`));
|
|
957
968
|
let args = {};
|
|
958
969
|
try {
|
|
@@ -969,15 +980,29 @@ function startAIAgent(ctx) {
|
|
|
969
980
|
{ role: "system", content: buildSystemPrompt(ctx.config) }
|
|
970
981
|
];
|
|
971
982
|
const rl = createInterface({ input: stdin, output: stdout });
|
|
983
|
+
const cols = Math.min(process.stdout.columns || 70, 70);
|
|
984
|
+
const line = chalk2.dim("\u2500".repeat(cols));
|
|
985
|
+
const watchDisplay = ctx.config.watchFolder.startsWith(HOME) ? "~" + ctx.config.watchFolder.slice(HOME.length) : ctx.config.watchFolder;
|
|
986
|
+
const stats = ctx.bootStats;
|
|
972
987
|
console.log("");
|
|
973
|
-
console.log(
|
|
974
|
-
console.log(
|
|
975
|
-
console.log(chalk2.
|
|
988
|
+
console.log(line);
|
|
989
|
+
console.log("");
|
|
990
|
+
console.log(` ${chalk2.bold("AnrakLegal Sync")} ${chalk2.dim(`v${PKG_VERSION}`)}`);
|
|
991
|
+
console.log("");
|
|
992
|
+
console.log(` ${chalk2.dim("Folder")} ${watchDisplay}`);
|
|
993
|
+
console.log(` ${chalk2.dim("Server")} ${ctx.config.apiUrl}`);
|
|
994
|
+
if (stats) {
|
|
995
|
+
console.log(` ${chalk2.dim("Cases")} ${stats.cases} on server`);
|
|
996
|
+
if (stats.scanned > 0) {
|
|
997
|
+
console.log(` ${chalk2.dim("Files")} ${stats.scanned} scanned${stats.queued > 0 ? `, ${chalk2.yellow(String(stats.queued))} synced` : chalk2.green(" \xB7 up to date")}`);
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
console.log("");
|
|
1001
|
+
console.log(line);
|
|
1002
|
+
console.log("");
|
|
1003
|
+
console.log(chalk2.dim(" Type a message to get started. Examples:"));
|
|
1004
|
+
console.log(chalk2.dim(' "show my cases" "look at downloads" "sync my desktop"'));
|
|
976
1005
|
console.log("");
|
|
977
|
-
console.log(
|
|
978
|
-
chalk2.dim(" Ask me anything \u2014 scan folders, check cases, show status.")
|
|
979
|
-
);
|
|
980
|
-
console.log(chalk2.dim(' Type "quit" to exit.\n'));
|
|
981
1006
|
const PROMPT = `${chalk2.bold.blue("\u276F")} `;
|
|
982
1007
|
async function promptLoop() {
|
|
983
1008
|
while (true) {
|
|
@@ -1114,16 +1139,13 @@ async function scanExternalFolder(config, folderPath, cases) {
|
|
|
1114
1139
|
}
|
|
1115
1140
|
async function startWatching(config) {
|
|
1116
1141
|
const folder = config.watchFolder;
|
|
1117
|
-
log.info(`Scanning ${folder}...`);
|
|
1118
1142
|
let cases = await listCases(config);
|
|
1119
|
-
log.info(`Found ${cases.length} case(s) on server`);
|
|
1120
1143
|
const { scanned, queued } = await scanFolder(config);
|
|
1121
|
-
log.info(`Scanned ${scanned} files, ${queued} need syncing`);
|
|
1122
1144
|
if (queued > 0) {
|
|
1123
1145
|
const result = await processQueue(config, cases);
|
|
1124
|
-
|
|
1125
|
-
`Initial sync: ${result.uploaded} uploaded, ${result.failed} failed`
|
|
1126
|
-
|
|
1146
|
+
if (result.failed > 0) {
|
|
1147
|
+
log.warn(`Initial sync: ${result.uploaded} uploaded, ${result.failed} failed`);
|
|
1148
|
+
}
|
|
1127
1149
|
}
|
|
1128
1150
|
const refreshInterval = setInterval(async () => {
|
|
1129
1151
|
try {
|
|
@@ -1131,7 +1153,6 @@ async function startWatching(config) {
|
|
|
1131
1153
|
} catch {
|
|
1132
1154
|
}
|
|
1133
1155
|
}, 5 * 60 * 1e3);
|
|
1134
|
-
log.info(`Watching for changes...`);
|
|
1135
1156
|
const watcher = watch(folder, {
|
|
1136
1157
|
ignored: /(^|[\/\\])(\.|~\$|Thumbs\.db|desktop\.ini)/,
|
|
1137
1158
|
persistent: true,
|
|
@@ -1160,14 +1181,14 @@ async function startWatching(config) {
|
|
|
1160
1181
|
}, 3e3);
|
|
1161
1182
|
}
|
|
1162
1183
|
watcher.on("add", async (path) => {
|
|
1163
|
-
const filename =
|
|
1184
|
+
const filename = basename5(path);
|
|
1164
1185
|
if (!isSupportedFile(filename) || isIgnoredFile(filename)) return;
|
|
1165
1186
|
log.file("detected", relative2(folder, path));
|
|
1166
1187
|
await enqueue(path, folder);
|
|
1167
1188
|
scheduleProcess();
|
|
1168
1189
|
});
|
|
1169
1190
|
watcher.on("change", async (path) => {
|
|
1170
|
-
const filename =
|
|
1191
|
+
const filename = basename5(path);
|
|
1171
1192
|
if (!isSupportedFile(filename) || isIgnoredFile(filename)) return;
|
|
1172
1193
|
log.file("changed", relative2(folder, path));
|
|
1173
1194
|
await enqueue(path, folder);
|
|
@@ -1181,6 +1202,7 @@ async function startWatching(config) {
|
|
|
1181
1202
|
});
|
|
1182
1203
|
startAIAgent({
|
|
1183
1204
|
config,
|
|
1205
|
+
bootStats: { cases: cases.length, scanned, queued },
|
|
1184
1206
|
getCases: () => cases,
|
|
1185
1207
|
refreshCases: async () => {
|
|
1186
1208
|
cases = await listCases(config);
|
|
@@ -1211,21 +1233,100 @@ async function startWatching(config) {
|
|
|
1211
1233
|
process.on("SIGTERM", shutdown);
|
|
1212
1234
|
}
|
|
1213
1235
|
|
|
1236
|
+
// src/updater.ts
|
|
1237
|
+
import { execFileSync } from "child_process";
|
|
1238
|
+
import chalk3 from "chalk";
|
|
1239
|
+
var PACKAGE_NAME = "@anraktech/sync";
|
|
1240
|
+
var CHECK_INTERVAL_MS = 4 * 60 * 60 * 1e3;
|
|
1241
|
+
var updateCache = { lastCheck: 0, latestVersion: null };
|
|
1242
|
+
function compareVersions(current, latest) {
|
|
1243
|
+
const a = current.split(".").map(Number);
|
|
1244
|
+
const b = latest.split(".").map(Number);
|
|
1245
|
+
for (let i = 0; i < 3; i++) {
|
|
1246
|
+
if ((b[i] ?? 0) > (a[i] ?? 0)) return 1;
|
|
1247
|
+
if ((b[i] ?? 0) < (a[i] ?? 0)) return -1;
|
|
1248
|
+
}
|
|
1249
|
+
return 0;
|
|
1250
|
+
}
|
|
1251
|
+
async function fetchLatestVersion() {
|
|
1252
|
+
try {
|
|
1253
|
+
const res = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`, {
|
|
1254
|
+
signal: AbortSignal.timeout(5e3)
|
|
1255
|
+
});
|
|
1256
|
+
if (!res.ok) return null;
|
|
1257
|
+
const data = await res.json();
|
|
1258
|
+
return data.version ?? null;
|
|
1259
|
+
} catch {
|
|
1260
|
+
return null;
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
function performUpdate(currentVersion, latestVersion) {
|
|
1264
|
+
console.log(
|
|
1265
|
+
chalk3.dim(`
|
|
1266
|
+
Update available: ${currentVersion} \u2192 `) + chalk3.green(latestVersion) + chalk3.dim(" \xB7 installing...")
|
|
1267
|
+
);
|
|
1268
|
+
try {
|
|
1269
|
+
execFileSync("npm", ["install", "-g", `${PACKAGE_NAME}@${latestVersion}`], {
|
|
1270
|
+
stdio: "pipe",
|
|
1271
|
+
timeout: 6e4
|
|
1272
|
+
});
|
|
1273
|
+
console.log(chalk3.green(" \u2713 Updated. Restart to use the new version.\n"));
|
|
1274
|
+
return true;
|
|
1275
|
+
} catch {
|
|
1276
|
+
try {
|
|
1277
|
+
execFileSync("npm", ["install", "-g", `${PACKAGE_NAME}@${latestVersion}`, "--prefix", process.env.HOME + "/.npm-global"], {
|
|
1278
|
+
stdio: "pipe",
|
|
1279
|
+
timeout: 6e4
|
|
1280
|
+
});
|
|
1281
|
+
console.log(chalk3.green(" Updated successfully. Restart to use the new version."));
|
|
1282
|
+
console.log("");
|
|
1283
|
+
return true;
|
|
1284
|
+
} catch {
|
|
1285
|
+
console.log(
|
|
1286
|
+
chalk3.dim(" Update failed. Run: ") + chalk3.cyan(`npm i -g ${PACKAGE_NAME}
|
|
1287
|
+
`)
|
|
1288
|
+
);
|
|
1289
|
+
return false;
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
async function checkForUpdates(currentVersion) {
|
|
1294
|
+
try {
|
|
1295
|
+
const now = Date.now();
|
|
1296
|
+
if (now - updateCache.lastCheck < CHECK_INTERVAL_MS && updateCache.latestVersion) {
|
|
1297
|
+
if (compareVersions(currentVersion, updateCache.latestVersion) > 0) {
|
|
1298
|
+
performUpdate(currentVersion, updateCache.latestVersion);
|
|
1299
|
+
}
|
|
1300
|
+
return;
|
|
1301
|
+
}
|
|
1302
|
+
const latestVersion = await fetchLatestVersion();
|
|
1303
|
+
updateCache = { lastCheck: now, latestVersion };
|
|
1304
|
+
if (!latestVersion) return;
|
|
1305
|
+
if (compareVersions(currentVersion, latestVersion) > 0) {
|
|
1306
|
+
performUpdate(currentVersion, latestVersion);
|
|
1307
|
+
}
|
|
1308
|
+
} catch {
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1214
1312
|
// src/cli.ts
|
|
1215
|
-
import { readFileSync as
|
|
1216
|
-
import { fileURLToPath } from "url";
|
|
1217
|
-
import { dirname as
|
|
1218
|
-
var
|
|
1219
|
-
var
|
|
1220
|
-
var pkg = JSON.parse(
|
|
1313
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
1314
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1315
|
+
import { dirname as dirname3, join as join4 } from "path";
|
|
1316
|
+
var __filename3 = fileURLToPath2(import.meta.url);
|
|
1317
|
+
var __dirname3 = dirname3(__filename3);
|
|
1318
|
+
var pkg = JSON.parse(readFileSync3(join4(__dirname3, "..", "package.json"), "utf-8"));
|
|
1319
|
+
await checkForUpdates(pkg.version);
|
|
1221
1320
|
var program = new Command();
|
|
1222
1321
|
program.name("anrak-sync").description("AnrakLegal desktop file sync \u2014 watches local folders, syncs to case management").version(pkg.version);
|
|
1223
1322
|
program.command("init").description("Set up AnrakLegal Sync (first-time configuration)").option("--password", "Use email/password login instead of browser").action(async (opts) => {
|
|
1224
1323
|
const rl = createInterface2({ input: stdin2, output: stdout2 });
|
|
1225
1324
|
try {
|
|
1226
|
-
console.log(
|
|
1325
|
+
console.log(`
|
|
1326
|
+
${chalk4.bold("AnrakLegal Sync")} ${chalk4.dim("\u2014 Setup")}
|
|
1327
|
+
`);
|
|
1227
1328
|
const apiUrl = await rl.question(
|
|
1228
|
-
` AnrakLegal URL ${
|
|
1329
|
+
` AnrakLegal URL ${chalk4.dim("(https://anrak.legal)")}: `
|
|
1229
1330
|
) || "https://anrak.legal";
|
|
1230
1331
|
log.info("Connecting to server...");
|
|
1231
1332
|
const serverConfig = await fetchServerConfig(apiUrl);
|
|
@@ -1256,7 +1357,7 @@ program.command("init").description("Set up AnrakLegal Sync (first-time configur
|
|
|
1256
1357
|
const rl2 = createInterface2({ input: stdin2, output: stdout2 });
|
|
1257
1358
|
const defaultFolder = process.platform === "win32" ? "C:\\Cases" : `${process.env.HOME}/Cases`;
|
|
1258
1359
|
const watchInput = await rl2.question(
|
|
1259
|
-
` Watch folder ${
|
|
1360
|
+
` Watch folder ${chalk4.dim(`(${defaultFolder})`)}: `
|
|
1260
1361
|
);
|
|
1261
1362
|
const watchFolder = resolve3(watchInput || defaultFolder);
|
|
1262
1363
|
rl2.close();
|
|
@@ -1282,7 +1383,7 @@ program.command("init").description("Set up AnrakLegal Sync (first-time configur
|
|
|
1282
1383
|
log.info(`Config saved to ${getConfigDir()}`);
|
|
1283
1384
|
log.info(`Watching: ${watchFolder}`);
|
|
1284
1385
|
console.log(
|
|
1285
|
-
|
|
1386
|
+
chalk4.dim("\n Run `anrak-sync start` to begin syncing\n")
|
|
1286
1387
|
);
|
|
1287
1388
|
} catch (err) {
|
|
1288
1389
|
log.error(err instanceof Error ? err.message : String(err));
|
|
@@ -1317,10 +1418,6 @@ program.command("login").description("Re-authenticate with AnrakLegal").option("
|
|
|
1317
1418
|
});
|
|
1318
1419
|
program.command("start").description("Start watching for file changes and syncing").action(async () => {
|
|
1319
1420
|
const config = requireConfig();
|
|
1320
|
-
console.log(chalk3.bold.blue("\n AnrakLegal Sync\n"));
|
|
1321
|
-
log.info(`Watching: ${config.watchFolder}`);
|
|
1322
|
-
log.info(`Server: ${config.apiUrl}`);
|
|
1323
|
-
console.log("");
|
|
1324
1421
|
try {
|
|
1325
1422
|
await startWatching(config);
|
|
1326
1423
|
} catch (err) {
|
|
@@ -1330,10 +1427,9 @@ program.command("start").description("Start watching for file changes and syncin
|
|
|
1330
1427
|
});
|
|
1331
1428
|
program.command("push").description("One-time sync \u2014 upload all new/changed files, then exit").action(async () => {
|
|
1332
1429
|
const config = requireConfig();
|
|
1333
|
-
console.log(
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
console.log("");
|
|
1430
|
+
console.log(`
|
|
1431
|
+
${chalk4.bold("AnrakLegal Sync")} ${chalk4.dim("\u2014 Push")}
|
|
1432
|
+
`);
|
|
1337
1433
|
try {
|
|
1338
1434
|
await pushSync(config);
|
|
1339
1435
|
} catch (err) {
|
|
@@ -1344,38 +1440,48 @@ program.command("push").description("One-time sync \u2014 upload all new/changed
|
|
|
1344
1440
|
program.command("status").description("Show sync status").action(async () => {
|
|
1345
1441
|
const config = requireConfig();
|
|
1346
1442
|
const stats = getStats();
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
console.log(` Watch folder: ${config.watchFolder}`);
|
|
1350
|
-
console.log(` Config: ${getConfigDir()}`);
|
|
1443
|
+
const cols = Math.min(process.stdout.columns || 60, 60);
|
|
1444
|
+
const line = chalk4.dim("\u2500".repeat(cols));
|
|
1351
1445
|
console.log("");
|
|
1352
|
-
console.log(
|
|
1353
|
-
console.log(`
|
|
1354
|
-
console.log(
|
|
1355
|
-
console.log(
|
|
1356
|
-
console.log(`
|
|
1446
|
+
console.log(line);
|
|
1447
|
+
console.log(` ${chalk4.bold("AnrakLegal Sync")} ${chalk4.dim(`v${pkg.version}`)}`);
|
|
1448
|
+
console.log(line);
|
|
1449
|
+
console.log("");
|
|
1450
|
+
console.log(` ${chalk4.dim("Server")} ${config.apiUrl}`);
|
|
1451
|
+
console.log(` ${chalk4.dim("Watch folder")} ${config.watchFolder}`);
|
|
1452
|
+
console.log(` ${chalk4.dim("Config")} ${getConfigDir()}`);
|
|
1453
|
+
console.log("");
|
|
1454
|
+
console.log(` ${chalk4.dim("Files tracked")} ${stats.totalFiles}`);
|
|
1455
|
+
console.log(` ${chalk4.dim("Synced")} ${chalk4.green(stats.synced)}`);
|
|
1456
|
+
console.log(` ${chalk4.dim("Pending")} ${chalk4.yellow(stats.pending)}`);
|
|
1457
|
+
console.log(` ${chalk4.dim("Errors")} ${stats.errors > 0 ? chalk4.red(stats.errors) : stats.errors}`);
|
|
1458
|
+
console.log(` ${chalk4.dim("Mapped folders")} ${stats.mappedFolders}`);
|
|
1357
1459
|
try {
|
|
1358
1460
|
const cases = await listCases(config);
|
|
1359
|
-
console.log(
|
|
1360
|
-
Server cases
|
|
1361
|
-
console.log(` Auth
|
|
1461
|
+
console.log("");
|
|
1462
|
+
console.log(` ${chalk4.dim("Server cases")} ${cases.length}`);
|
|
1463
|
+
console.log(` ${chalk4.dim("Auth")} ${chalk4.green("valid")}`);
|
|
1362
1464
|
} catch {
|
|
1363
|
-
console.log(
|
|
1364
|
-
Auth
|
|
1465
|
+
console.log("");
|
|
1466
|
+
console.log(` ${chalk4.dim("Auth")} ${chalk4.red("expired")} ${chalk4.dim("\u2014 run")} anrak-sync login`);
|
|
1365
1467
|
}
|
|
1366
1468
|
console.log("");
|
|
1469
|
+
console.log(line);
|
|
1470
|
+
console.log("");
|
|
1367
1471
|
});
|
|
1368
1472
|
program.command("map").description("Show folder-to-case mappings").action(async () => {
|
|
1369
1473
|
const config = requireConfig();
|
|
1370
1474
|
const mappings = getAllMappings();
|
|
1371
1475
|
const entries = Object.entries(mappings);
|
|
1372
|
-
console.log(
|
|
1476
|
+
console.log(`
|
|
1477
|
+
${chalk4.bold("AnrakLegal Sync")} ${chalk4.dim("\u2014 Mappings")}
|
|
1478
|
+
`);
|
|
1373
1479
|
if (entries.length === 0) {
|
|
1374
1480
|
log.info("No mappings yet. Run `anrak-sync push` or `anrak-sync start` to create them.");
|
|
1375
1481
|
} else {
|
|
1376
1482
|
for (const [folder, mapping] of entries) {
|
|
1377
1483
|
console.log(
|
|
1378
|
-
` ${
|
|
1484
|
+
` ${chalk4.cyan(folder)} -> ${mapping.caseNumber} (${chalk4.dim(mapping.caseName)})`
|
|
1379
1485
|
);
|
|
1380
1486
|
}
|
|
1381
1487
|
}
|
|
@@ -1384,9 +1490,9 @@ program.command("map").description("Show folder-to-case mappings").action(async
|
|
|
1384
1490
|
const mappedIds = new Set(entries.map(([, m]) => m.caseId));
|
|
1385
1491
|
const unmapped = cases.filter((c) => !mappedIds.has(c.id));
|
|
1386
1492
|
if (unmapped.length > 0) {
|
|
1387
|
-
console.log(
|
|
1493
|
+
console.log(chalk4.dim("\n Unmapped server cases:"));
|
|
1388
1494
|
for (const c of unmapped) {
|
|
1389
|
-
console.log(` ${
|
|
1495
|
+
console.log(` ${chalk4.dim(c.caseNumber)} ${chalk4.dim(c.caseName)}`);
|
|
1390
1496
|
}
|
|
1391
1497
|
}
|
|
1392
1498
|
} catch {
|