@ncukondo/reference-manager 0.19.0 → 0.20.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/chunks/{action-menu-BoJkH1yr.js → action-menu-Brg5Lmz7.js} +3 -3
- package/dist/chunks/{action-menu-BoJkH1yr.js.map → action-menu-Brg5Lmz7.js.map} +1 -1
- package/dist/chunks/{format-QgF4pmp6.js → format-CYO99JV-.js} +2 -2
- package/dist/chunks/{format-QgF4pmp6.js.map → format-CYO99JV-.js.map} +1 -1
- package/dist/chunks/{index-BJf01yMW.js → index-BR5tlrNU.js} +2 -2
- package/dist/chunks/index-BR5tlrNU.js.map +1 -0
- package/dist/chunks/{index-Di6yhlFH.js → index-Cno7_aWr.js} +434 -96
- package/dist/chunks/index-Cno7_aWr.js.map +1 -0
- package/dist/chunks/{index-C49EfSAl.js → index-D--7n1SB.js} +4 -4
- package/dist/chunks/{index-C49EfSAl.js.map → index-D--7n1SB.js.map} +1 -1
- package/dist/chunks/{index-B4gr0P83.js → index-DrZawbND.js} +2 -1
- package/dist/chunks/{index-B4gr0P83.js.map → index-DrZawbND.js.map} +1 -1
- package/dist/chunks/{reference-select-D4iGJ4kA.js → reference-select-DrINWBuP.js} +3 -3
- package/dist/chunks/{reference-select-D4iGJ4kA.js.map → reference-select-DrINWBuP.js.map} +1 -1
- package/dist/chunks/{style-select-UWYScO8e.js → style-select-DxcSWBSF.js} +3 -3
- package/dist/chunks/{style-select-UWYScO8e.js.map → style-select-DxcSWBSF.js.map} +1 -1
- package/dist/cli/commands/attach.d.ts +44 -1
- package/dist/cli/commands/attach.d.ts.map +1 -1
- package/dist/cli/helpers.d.ts +18 -0
- package/dist/cli/helpers.d.ts.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/features/operations/attachments/sync.d.ts +14 -0
- package/dist/features/operations/attachments/sync.d.ts.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +1 -1
- package/dist/chunks/index-BJf01yMW.js.map +0 -1
- package/dist/chunks/index-Di6yhlFH.js.map +0 -1
|
@@ -6,8 +6,8 @@ import * as os from "node:os";
|
|
|
6
6
|
import { tmpdir } from "node:os";
|
|
7
7
|
import * as path from "node:path";
|
|
8
8
|
import path__default, { extname, join, basename, dirname } from "node:path";
|
|
9
|
+
import { g as getExtension, i as isValidFulltextFiles, a as isReservedRole, R as RESERVED_ROLES, F as FULLTEXT_ROLE, b as formatToExtension, c as findFulltextFiles, d as findFulltextFile, e as extensionToFormat, B as BUILTIN_STYLES, h as getFulltextAttachmentTypes, s as startServerWithFileWatcher } from "./index-DrZawbND.js";
|
|
9
10
|
import fs__default, { stat, rename, copyFile, readFile, unlink, readdir, mkdir, rm } from "node:fs/promises";
|
|
10
|
-
import { g as getExtension, i as isValidFulltextFiles, a as isReservedRole, F as FULLTEXT_ROLE, b as formatToExtension, c as findFulltextFiles, d as findFulltextFile, e as extensionToFormat, B as BUILTIN_STYLES, h as getFulltextAttachmentTypes, s as startServerWithFileWatcher } from "./index-B4gr0P83.js";
|
|
11
11
|
import { o as openWithSystemApp, l as loadConfig, e as getDefaultCurrentDirConfigFilename, h as getDefaultUserConfigPath } from "./loader-BtW20O32.js";
|
|
12
12
|
import { spawn, spawnSync } from "node:child_process";
|
|
13
13
|
import process$1, { stdin, stdout } from "node:process";
|
|
@@ -20,7 +20,7 @@ import "@citation-js/plugin-csl";
|
|
|
20
20
|
import { ZodOptional as ZodOptional$2, z } from "zod";
|
|
21
21
|
import { serve } from "@hono/node-server";
|
|
22
22
|
const name = "@ncukondo/reference-manager";
|
|
23
|
-
const version$1 = "0.
|
|
23
|
+
const version$1 = "0.20.0";
|
|
24
24
|
const description$1 = "A local reference management tool using CSL-JSON as the single source of truth";
|
|
25
25
|
const packageJson = {
|
|
26
26
|
name,
|
|
@@ -414,6 +414,44 @@ function getExitCode(result) {
|
|
|
414
414
|
}
|
|
415
415
|
return 0;
|
|
416
416
|
}
|
|
417
|
+
function slugifyLabel(label) {
|
|
418
|
+
return label.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
419
|
+
}
|
|
420
|
+
function generateFilename(role, ext, label) {
|
|
421
|
+
if (label) {
|
|
422
|
+
const slug = slugifyLabel(label);
|
|
423
|
+
return `${role}-${slug}.${ext}`;
|
|
424
|
+
}
|
|
425
|
+
return `${role}.${ext}`;
|
|
426
|
+
}
|
|
427
|
+
function parseFilename(filename) {
|
|
428
|
+
if (!filename) {
|
|
429
|
+
return null;
|
|
430
|
+
}
|
|
431
|
+
const ext = path__default.extname(filename);
|
|
432
|
+
const extWithoutDot = ext.startsWith(".") ? ext.slice(1) : ext;
|
|
433
|
+
const basename2 = ext ? filename.slice(0, -ext.length) : filename;
|
|
434
|
+
const firstHyphenIndex = basename2.indexOf("-");
|
|
435
|
+
if (firstHyphenIndex === -1) {
|
|
436
|
+
return {
|
|
437
|
+
role: basename2,
|
|
438
|
+
ext: extWithoutDot
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
const role = basename2.slice(0, firstHyphenIndex);
|
|
442
|
+
const label = basename2.slice(firstHyphenIndex + 1);
|
|
443
|
+
if (label) {
|
|
444
|
+
return {
|
|
445
|
+
role,
|
|
446
|
+
ext: extWithoutDot,
|
|
447
|
+
label
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
return {
|
|
451
|
+
role,
|
|
452
|
+
ext: extWithoutDot
|
|
453
|
+
};
|
|
454
|
+
}
|
|
417
455
|
function normalizePathForOutput(p) {
|
|
418
456
|
return p.replace(/\\/g, "/");
|
|
419
457
|
}
|
|
@@ -464,44 +502,6 @@ async function deleteDirectoryIfEmpty(dirPath) {
|
|
|
464
502
|
}
|
|
465
503
|
}
|
|
466
504
|
}
|
|
467
|
-
function slugifyLabel(label) {
|
|
468
|
-
return label.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
469
|
-
}
|
|
470
|
-
function generateFilename(role, ext, label) {
|
|
471
|
-
if (label) {
|
|
472
|
-
const slug = slugifyLabel(label);
|
|
473
|
-
return `${role}-${slug}.${ext}`;
|
|
474
|
-
}
|
|
475
|
-
return `${role}.${ext}`;
|
|
476
|
-
}
|
|
477
|
-
function parseFilename(filename) {
|
|
478
|
-
if (!filename) {
|
|
479
|
-
return null;
|
|
480
|
-
}
|
|
481
|
-
const ext = path__default.extname(filename);
|
|
482
|
-
const extWithoutDot = ext.startsWith(".") ? ext.slice(1) : ext;
|
|
483
|
-
const basename2 = ext ? filename.slice(0, -ext.length) : filename;
|
|
484
|
-
const firstHyphenIndex = basename2.indexOf("-");
|
|
485
|
-
if (firstHyphenIndex === -1) {
|
|
486
|
-
return {
|
|
487
|
-
role: basename2,
|
|
488
|
-
ext: extWithoutDot
|
|
489
|
-
};
|
|
490
|
-
}
|
|
491
|
-
const role = basename2.slice(0, firstHyphenIndex);
|
|
492
|
-
const label = basename2.slice(firstHyphenIndex + 1);
|
|
493
|
-
if (label) {
|
|
494
|
-
return {
|
|
495
|
-
role,
|
|
496
|
-
ext: extWithoutDot,
|
|
497
|
-
label
|
|
498
|
-
};
|
|
499
|
-
}
|
|
500
|
-
return {
|
|
501
|
-
role,
|
|
502
|
-
ext: extWithoutDot
|
|
503
|
-
};
|
|
504
|
-
}
|
|
505
505
|
async function checkSourceFile(filePath) {
|
|
506
506
|
try {
|
|
507
507
|
await stat(filePath);
|
|
@@ -794,6 +794,19 @@ async function detachAttachment(library, options) {
|
|
|
794
794
|
function errorResult(error) {
|
|
795
795
|
return { success: false, newFiles: [], missingFiles: [], applied: false, error };
|
|
796
796
|
}
|
|
797
|
+
function suggestRoleFromContext(filename, existingFiles) {
|
|
798
|
+
const ext = filename.toLowerCase();
|
|
799
|
+
const dataExtensions = [".xlsx", ".csv", ".tsv", ".zip"];
|
|
800
|
+
if (dataExtensions.some((de) => ext.endsWith(de)) || ext.endsWith(".tar.gz")) {
|
|
801
|
+
return "supplement";
|
|
802
|
+
}
|
|
803
|
+
const isDocumentLike = ext.endsWith(".pdf") || ext.endsWith(".md");
|
|
804
|
+
if (isDocumentLike) {
|
|
805
|
+
const hasFulltext = existingFiles.some((f) => f.role === "fulltext");
|
|
806
|
+
return hasFulltext ? "supplement" : "fulltext";
|
|
807
|
+
}
|
|
808
|
+
return null;
|
|
809
|
+
}
|
|
797
810
|
function inferFromFilename(filename) {
|
|
798
811
|
const parsed = parseFilename(filename);
|
|
799
812
|
if (!parsed) {
|
|
@@ -836,14 +849,17 @@ function findNewFiles(diskFiles, metadataFilenames) {
|
|
|
836
849
|
function findMissingFiles(metadataFiles, diskFilenames) {
|
|
837
850
|
return metadataFiles.filter((f) => !diskFilenames.has(f.filename)).map((f) => f.filename);
|
|
838
851
|
}
|
|
839
|
-
function buildUpdatedFiles(metadataFiles, newFiles, missingFiles, shouldApplyNew, shouldApplyFix) {
|
|
852
|
+
function buildUpdatedFiles(metadataFiles, newFiles, missingFiles, shouldApplyNew, shouldApplyFix, roleOverrides) {
|
|
840
853
|
let updatedFiles = [...metadataFiles];
|
|
841
854
|
if (shouldApplyNew) {
|
|
842
855
|
for (const newFile of newFiles) {
|
|
856
|
+
const override = roleOverrides?.[newFile.filename];
|
|
857
|
+
const role = override?.role ?? newFile.role;
|
|
858
|
+
const label = override ? override.label : newFile.label;
|
|
843
859
|
const attachmentFile = {
|
|
844
860
|
filename: newFile.filename,
|
|
845
|
-
role
|
|
846
|
-
...
|
|
861
|
+
role,
|
|
862
|
+
...label && { label }
|
|
847
863
|
};
|
|
848
864
|
updatedFiles.push(attachmentFile);
|
|
849
865
|
}
|
|
@@ -854,6 +870,36 @@ function buildUpdatedFiles(metadataFiles, newFiles, missingFiles, shouldApplyNew
|
|
|
854
870
|
}
|
|
855
871
|
return updatedFiles;
|
|
856
872
|
}
|
|
873
|
+
async function applyRenames(dirPath, renames) {
|
|
874
|
+
const applied = {};
|
|
875
|
+
for (const [oldName, newName] of Object.entries(renames)) {
|
|
876
|
+
const oldPath = join(dirPath, oldName);
|
|
877
|
+
const newPath = join(dirPath, newName);
|
|
878
|
+
try {
|
|
879
|
+
await stat(newPath);
|
|
880
|
+
process.stderr.write(
|
|
881
|
+
`Warning: Cannot rename ${oldName} → ${newName}: target already exists
|
|
882
|
+
`
|
|
883
|
+
);
|
|
884
|
+
} catch {
|
|
885
|
+
try {
|
|
886
|
+
await rename(oldPath, newPath);
|
|
887
|
+
applied[oldName] = newName;
|
|
888
|
+
} catch {
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
return applied;
|
|
893
|
+
}
|
|
894
|
+
function applyRenamesInMetadata(files, appliedRenames) {
|
|
895
|
+
return files.map((f) => {
|
|
896
|
+
const newName = appliedRenames[f.filename];
|
|
897
|
+
if (newName) {
|
|
898
|
+
return { ...f, filename: newName };
|
|
899
|
+
}
|
|
900
|
+
return f;
|
|
901
|
+
});
|
|
902
|
+
}
|
|
857
903
|
async function updateAttachmentMetadata(library, item, attachments, updatedFiles) {
|
|
858
904
|
await library.update(item.id, {
|
|
859
905
|
custom: {
|
|
@@ -866,7 +912,15 @@ async function updateAttachmentMetadata(library, item, attachments, updatedFiles
|
|
|
866
912
|
});
|
|
867
913
|
}
|
|
868
914
|
async function syncAttachments(library, options) {
|
|
869
|
-
const {
|
|
915
|
+
const {
|
|
916
|
+
identifier,
|
|
917
|
+
yes = false,
|
|
918
|
+
fix = false,
|
|
919
|
+
idType = "id",
|
|
920
|
+
attachmentsDirectory,
|
|
921
|
+
roleOverrides,
|
|
922
|
+
renames
|
|
923
|
+
} = options;
|
|
870
924
|
const item = await library.find(identifier, { idType });
|
|
871
925
|
if (!item) {
|
|
872
926
|
return errorResult(`Reference '${identifier}' not found`);
|
|
@@ -889,13 +943,20 @@ async function syncAttachments(library, options) {
|
|
|
889
943
|
const shouldApplyFix = fix && missingFiles.length > 0;
|
|
890
944
|
const shouldApply = shouldApplyNew || shouldApplyFix;
|
|
891
945
|
if (shouldApply) {
|
|
892
|
-
|
|
946
|
+
let updatedFiles = buildUpdatedFiles(
|
|
893
947
|
metadataFiles,
|
|
894
948
|
newFiles,
|
|
895
949
|
missingFiles,
|
|
896
950
|
shouldApplyNew,
|
|
897
|
-
shouldApplyFix
|
|
951
|
+
shouldApplyFix,
|
|
952
|
+
roleOverrides
|
|
898
953
|
);
|
|
954
|
+
if (shouldApplyNew && renames && Object.keys(renames).length > 0) {
|
|
955
|
+
const appliedRenames = await applyRenames(dirPath, renames);
|
|
956
|
+
if (Object.keys(appliedRenames).length > 0) {
|
|
957
|
+
updatedFiles = applyRenamesInMetadata(updatedFiles, appliedRenames);
|
|
958
|
+
}
|
|
959
|
+
}
|
|
899
960
|
await updateAttachmentMetadata(library, item, attachments, updatedFiles);
|
|
900
961
|
await library.save();
|
|
901
962
|
}
|
|
@@ -1032,15 +1093,15 @@ class OperationsLibrary {
|
|
|
1032
1093
|
}
|
|
1033
1094
|
// High-level operations
|
|
1034
1095
|
async search(options) {
|
|
1035
|
-
const { searchReferences } = await import("./index-
|
|
1096
|
+
const { searchReferences } = await import("./index-DrZawbND.js").then((n) => n.n);
|
|
1036
1097
|
return searchReferences(this.library, options);
|
|
1037
1098
|
}
|
|
1038
1099
|
async list(options) {
|
|
1039
|
-
const { listReferences } = await import("./index-
|
|
1100
|
+
const { listReferences } = await import("./index-DrZawbND.js").then((n) => n.m);
|
|
1040
1101
|
return listReferences(this.library, options ?? {});
|
|
1041
1102
|
}
|
|
1042
1103
|
async cite(options) {
|
|
1043
|
-
const { citeReferences } = await import("./index-
|
|
1104
|
+
const { citeReferences } = await import("./index-DrZawbND.js").then((n) => n.l);
|
|
1044
1105
|
const defaultStyle = options.defaultStyle ?? this.citationConfig?.defaultStyle;
|
|
1045
1106
|
const cslDirectory = options.cslDirectory ?? this.citationConfig?.cslDirectory;
|
|
1046
1107
|
const mergedOptions = {
|
|
@@ -1051,32 +1112,32 @@ class OperationsLibrary {
|
|
|
1051
1112
|
return citeReferences(this.library, mergedOptions);
|
|
1052
1113
|
}
|
|
1053
1114
|
async import(inputs, options) {
|
|
1054
|
-
const { addReferences } = await import("./index-
|
|
1115
|
+
const { addReferences } = await import("./index-DrZawbND.js").then((n) => n.k);
|
|
1055
1116
|
return addReferences(inputs, this.library, options ?? {});
|
|
1056
1117
|
}
|
|
1057
1118
|
// Attachment operations
|
|
1058
1119
|
async attachAdd(options) {
|
|
1059
|
-
const { addAttachment: addAttachment2 } = await import("./index-
|
|
1120
|
+
const { addAttachment: addAttachment2 } = await import("./index-BR5tlrNU.js");
|
|
1060
1121
|
return addAttachment2(this.library, options);
|
|
1061
1122
|
}
|
|
1062
1123
|
async attachList(options) {
|
|
1063
|
-
const { listAttachments: listAttachments2 } = await import("./index-
|
|
1124
|
+
const { listAttachments: listAttachments2 } = await import("./index-BR5tlrNU.js");
|
|
1064
1125
|
return listAttachments2(this.library, options);
|
|
1065
1126
|
}
|
|
1066
1127
|
async attachGet(options) {
|
|
1067
|
-
const { getAttachment: getAttachment2 } = await import("./index-
|
|
1128
|
+
const { getAttachment: getAttachment2 } = await import("./index-BR5tlrNU.js");
|
|
1068
1129
|
return getAttachment2(this.library, options);
|
|
1069
1130
|
}
|
|
1070
1131
|
async attachDetach(options) {
|
|
1071
|
-
const { detachAttachment: detachAttachment2 } = await import("./index-
|
|
1132
|
+
const { detachAttachment: detachAttachment2 } = await import("./index-BR5tlrNU.js");
|
|
1072
1133
|
return detachAttachment2(this.library, options);
|
|
1073
1134
|
}
|
|
1074
1135
|
async attachSync(options) {
|
|
1075
|
-
const { syncAttachments: syncAttachments2 } = await import("./index-
|
|
1136
|
+
const { syncAttachments: syncAttachments2 } = await import("./index-BR5tlrNU.js");
|
|
1076
1137
|
return syncAttachments2(this.library, options);
|
|
1077
1138
|
}
|
|
1078
1139
|
async attachOpen(options) {
|
|
1079
|
-
const { openAttachment: openAttachment2 } = await import("./index-
|
|
1140
|
+
const { openAttachment: openAttachment2 } = await import("./index-BR5tlrNU.js");
|
|
1080
1141
|
return openAttachment2(this.library, options);
|
|
1081
1142
|
}
|
|
1082
1143
|
}
|
|
@@ -1536,6 +1597,62 @@ async function readConfirmation(prompt) {
|
|
|
1536
1597
|
});
|
|
1537
1598
|
});
|
|
1538
1599
|
}
|
|
1600
|
+
async function readChoice(prompt, choices, defaultIndex) {
|
|
1601
|
+
if (choices.length === 0) {
|
|
1602
|
+
throw new Error("readChoice requires at least one choice");
|
|
1603
|
+
}
|
|
1604
|
+
const effectiveDefault = defaultIndex !== void 0 && defaultIndex >= 0 && defaultIndex < choices.length ? defaultIndex : 0;
|
|
1605
|
+
const getDefault = () => {
|
|
1606
|
+
const choice = choices[effectiveDefault];
|
|
1607
|
+
if (!choice) throw new Error("Invalid default index");
|
|
1608
|
+
return choice.value;
|
|
1609
|
+
};
|
|
1610
|
+
const parseAnswer = (answer) => {
|
|
1611
|
+
const trimmed = answer.trim();
|
|
1612
|
+
if (trimmed === "") return getDefault();
|
|
1613
|
+
const num = Number.parseInt(trimmed, 10);
|
|
1614
|
+
if (Number.isNaN(num) || num < 1 || num > choices.length) return getDefault();
|
|
1615
|
+
const selected = choices[num - 1];
|
|
1616
|
+
return selected ? selected.value : getDefault();
|
|
1617
|
+
};
|
|
1618
|
+
if (!isTTY()) {
|
|
1619
|
+
return getDefault();
|
|
1620
|
+
}
|
|
1621
|
+
if (process.stdin.isTTY && process.stdin.isRaw) {
|
|
1622
|
+
process.stdin.setRawMode(false);
|
|
1623
|
+
}
|
|
1624
|
+
process.stdin.resume();
|
|
1625
|
+
process.stdin.ref();
|
|
1626
|
+
const rl = readline.createInterface({
|
|
1627
|
+
input: process.stdin,
|
|
1628
|
+
output: process.stderr
|
|
1629
|
+
});
|
|
1630
|
+
process.stderr.write(`${prompt}
|
|
1631
|
+
`);
|
|
1632
|
+
for (let i = 0; i < choices.length; i++) {
|
|
1633
|
+
const choice = choices[i];
|
|
1634
|
+
if (!choice) continue;
|
|
1635
|
+
const marker = i === effectiveDefault ? " (default)" : "";
|
|
1636
|
+
process.stderr.write(` ${i + 1}) ${choice.label}${marker}
|
|
1637
|
+
`);
|
|
1638
|
+
}
|
|
1639
|
+
return new Promise((resolve2) => {
|
|
1640
|
+
let resolved = false;
|
|
1641
|
+
rl.question("Enter number: ", (answer) => {
|
|
1642
|
+
if (!resolved) {
|
|
1643
|
+
resolved = true;
|
|
1644
|
+
rl.close();
|
|
1645
|
+
resolve2(parseAnswer(answer));
|
|
1646
|
+
}
|
|
1647
|
+
});
|
|
1648
|
+
rl.on("close", () => {
|
|
1649
|
+
if (!resolved) {
|
|
1650
|
+
resolved = true;
|
|
1651
|
+
resolve2(getDefault());
|
|
1652
|
+
}
|
|
1653
|
+
});
|
|
1654
|
+
});
|
|
1655
|
+
}
|
|
1539
1656
|
async function readStdinContent() {
|
|
1540
1657
|
const chunks = [];
|
|
1541
1658
|
for await (const chunk of stdin) {
|
|
@@ -1658,7 +1775,9 @@ async function executeAttachSync(options, context) {
|
|
|
1658
1775
|
attachmentsDirectory: options.attachmentsDirectory,
|
|
1659
1776
|
...options.yes !== void 0 && { yes: options.yes },
|
|
1660
1777
|
...options.fix !== void 0 && { fix: options.fix },
|
|
1661
|
-
...options.idType !== void 0 && { idType: options.idType }
|
|
1778
|
+
...options.idType !== void 0 && { idType: options.idType },
|
|
1779
|
+
...options.roleOverrides !== void 0 && { roleOverrides: options.roleOverrides },
|
|
1780
|
+
...options.renames !== void 0 && { renames: options.renames }
|
|
1662
1781
|
};
|
|
1663
1782
|
return syncAttachments(context.library, operationOptions);
|
|
1664
1783
|
}
|
|
@@ -1755,6 +1874,73 @@ function formatMissingFilesSection(result, lines) {
|
|
|
1755
1874
|
}
|
|
1756
1875
|
lines.push("");
|
|
1757
1876
|
}
|
|
1877
|
+
function buildRoleOverridesFromSuggestions(newFiles) {
|
|
1878
|
+
const overrides = {};
|
|
1879
|
+
for (const file of newFiles) {
|
|
1880
|
+
if (file.role !== "other") continue;
|
|
1881
|
+
const suggested = suggestRoleFromContext(file.filename, newFiles);
|
|
1882
|
+
if (suggested) {
|
|
1883
|
+
overrides[file.filename] = { role: suggested };
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
return overrides;
|
|
1887
|
+
}
|
|
1888
|
+
function generateRenameMap(newFiles, overrides) {
|
|
1889
|
+
const renames = {};
|
|
1890
|
+
for (const file of newFiles) {
|
|
1891
|
+
const override = overrides[file.filename];
|
|
1892
|
+
if (!override) continue;
|
|
1893
|
+
const ext = path__default.extname(file.filename);
|
|
1894
|
+
const extWithoutDot = ext.startsWith(".") ? ext.slice(1) : ext;
|
|
1895
|
+
const baseName = ext ? file.filename.slice(0, -ext.length) : file.filename;
|
|
1896
|
+
const canonical = generateFilename(override.role, extWithoutDot, override.label);
|
|
1897
|
+
if (canonical !== file.filename) {
|
|
1898
|
+
const newName = override.label ? canonical : `${override.role}-${baseName}${ext}`;
|
|
1899
|
+
renames[file.filename] = newName;
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
return renames;
|
|
1903
|
+
}
|
|
1904
|
+
function formatSuggestedFileEntry(file, suggestions, renames, lines) {
|
|
1905
|
+
lines.push(` ${file.filename}`);
|
|
1906
|
+
const suggestion = suggestions[file.filename];
|
|
1907
|
+
if (suggestion) {
|
|
1908
|
+
lines.push(` role: ${suggestion.role} (suggested, inferred: ${file.role})`);
|
|
1909
|
+
} else {
|
|
1910
|
+
const labelPart = file.label ? `, label: "${file.label}"` : "";
|
|
1911
|
+
lines.push(` role: ${file.role}${labelPart}`);
|
|
1912
|
+
}
|
|
1913
|
+
const rename2 = renames[file.filename];
|
|
1914
|
+
if (rename2) {
|
|
1915
|
+
lines.push(` rename: ${rename2}`);
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
function formatSyncPreviewWithSuggestions(result, suggestions, renames, identifier) {
|
|
1919
|
+
if (!result.success) {
|
|
1920
|
+
return `Error: ${result.error}`;
|
|
1921
|
+
}
|
|
1922
|
+
const hasNewFiles = result.newFiles.length > 0;
|
|
1923
|
+
const hasMissingFiles = result.missingFiles.length > 0;
|
|
1924
|
+
const hasRenames = Object.keys(renames).length > 0;
|
|
1925
|
+
if (!hasNewFiles && !hasMissingFiles) {
|
|
1926
|
+
return "Already in sync.";
|
|
1927
|
+
}
|
|
1928
|
+
const lines = [];
|
|
1929
|
+
lines.push(`Sync preview for ${identifier}:`);
|
|
1930
|
+
if (hasNewFiles) {
|
|
1931
|
+
lines.push(" New files:");
|
|
1932
|
+
for (const file of result.newFiles) {
|
|
1933
|
+
formatSuggestedFileEntry(file, suggestions, renames, lines);
|
|
1934
|
+
}
|
|
1935
|
+
lines.push("");
|
|
1936
|
+
}
|
|
1937
|
+
formatMissingFilesSection(result, lines);
|
|
1938
|
+
lines.push(`To apply: ref attach sync ${identifier} --yes`);
|
|
1939
|
+
if (hasRenames) {
|
|
1940
|
+
lines.push(`To apply without renaming: ref attach sync ${identifier} --yes --no-rename`);
|
|
1941
|
+
}
|
|
1942
|
+
return lines.join("\n").trimEnd();
|
|
1943
|
+
}
|
|
1758
1944
|
function formatAttachSyncOutput(result) {
|
|
1759
1945
|
if (!result.success) {
|
|
1760
1946
|
return `Error: ${result.error}`;
|
|
@@ -1795,7 +1981,7 @@ function getAttachExitCode(result) {
|
|
|
1795
1981
|
}
|
|
1796
1982
|
async function executeInteractiveSelect$2(context, config2) {
|
|
1797
1983
|
const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
|
|
1798
|
-
const { selectReferencesOrExit } = await import("./reference-select-
|
|
1984
|
+
const { selectReferencesOrExit } = await import("./reference-select-DrINWBuP.js");
|
|
1799
1985
|
const allReferences = await context.library.getAll();
|
|
1800
1986
|
const identifiers = await withAlternateScreen2(
|
|
1801
1987
|
() => selectReferencesOrExit(allReferences, { multiSelect: false }, config2.cli.tui)
|
|
@@ -1853,44 +2039,95 @@ async function waitForEnter() {
|
|
|
1853
2039
|
});
|
|
1854
2040
|
});
|
|
1855
2041
|
}
|
|
1856
|
-
function
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
2042
|
+
async function promptForRenames(renameMap) {
|
|
2043
|
+
const accepted = {};
|
|
2044
|
+
for (const [oldName, newName] of Object.entries(renameMap)) {
|
|
2045
|
+
const shouldRename = await readConfirmation(`Rename ${oldName} → ${newName}?`);
|
|
2046
|
+
if (shouldRename) {
|
|
2047
|
+
accepted[oldName] = newName;
|
|
2048
|
+
}
|
|
1860
2049
|
}
|
|
1861
|
-
|
|
2050
|
+
return accepted;
|
|
2051
|
+
}
|
|
2052
|
+
function showFilePreview(previewFiles, acceptedRenames) {
|
|
2053
|
+
process.stderr.write("\nScanning directory...\n\n");
|
|
1862
2054
|
process.stderr.write(
|
|
1863
|
-
`Found ${
|
|
2055
|
+
`Found ${previewFiles.length} new file${previewFiles.length > 1 ? "s" : ""}:
|
|
1864
2056
|
`
|
|
1865
2057
|
);
|
|
1866
|
-
for (const file of
|
|
2058
|
+
for (const file of previewFiles) {
|
|
1867
2059
|
const labelPart = file.label ? `, label: "${file.label}"` : "";
|
|
1868
|
-
|
|
1869
|
-
|
|
2060
|
+
const renamePart = acceptedRenames[file.filename] ? ` (rename → ${acceptedRenames[file.filename]})` : "";
|
|
2061
|
+
process.stderr.write(
|
|
2062
|
+
` ✓ ${file.filename} → role: ${file.role}${labelPart}${renamePart}
|
|
2063
|
+
`
|
|
2064
|
+
);
|
|
1870
2065
|
}
|
|
1871
|
-
process.stderr.write(`
|
|
1872
|
-
Updated metadata for ${identifier}.
|
|
1873
|
-
`);
|
|
1874
2066
|
}
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
2067
|
+
function buildPreviewFiles(newFiles, roleOverrides) {
|
|
2068
|
+
return newFiles.map((file) => {
|
|
2069
|
+
const override = roleOverrides[file.filename];
|
|
2070
|
+
if (override) {
|
|
2071
|
+
return { ...file, role: override.role, ...override.label && { label: override.label } };
|
|
2072
|
+
}
|
|
2073
|
+
return file;
|
|
2074
|
+
});
|
|
2075
|
+
}
|
|
2076
|
+
async function syncNewFilesWithRolePrompt(identifier, attachmentsDirectory, idType, context) {
|
|
2077
|
+
const dryRunResult = await executeAttachSync(
|
|
1879
2078
|
{
|
|
1880
2079
|
identifier,
|
|
1881
2080
|
attachmentsDirectory,
|
|
1882
|
-
yes: true,
|
|
1883
2081
|
...idType && { idType }
|
|
1884
2082
|
},
|
|
1885
2083
|
context
|
|
1886
2084
|
);
|
|
1887
|
-
if (
|
|
1888
|
-
|
|
2085
|
+
if (!dryRunResult.success) {
|
|
2086
|
+
process.stderr.write(`Sync error: ${dryRunResult.error}
|
|
2087
|
+
`);
|
|
2088
|
+
return;
|
|
2089
|
+
}
|
|
2090
|
+
if (dryRunResult.newFiles.length === 0) {
|
|
2091
|
+
process.stderr.write("No new files detected.\n");
|
|
2092
|
+
return;
|
|
2093
|
+
}
|
|
2094
|
+
const roleOverrides = await promptForUnknownRoles(dryRunResult.newFiles);
|
|
2095
|
+
const renameMap = generateRenameMap(dryRunResult.newFiles, roleOverrides);
|
|
2096
|
+
const acceptedRenames = await promptForRenames(renameMap);
|
|
2097
|
+
const previewFiles = buildPreviewFiles(dryRunResult.newFiles, roleOverrides);
|
|
2098
|
+
showFilePreview(previewFiles, acceptedRenames);
|
|
2099
|
+
const shouldApply = await readConfirmation("\nAdd new files to metadata?");
|
|
2100
|
+
if (!shouldApply) {
|
|
2101
|
+
process.stderr.write("No changes applied.\n");
|
|
2102
|
+
return;
|
|
2103
|
+
}
|
|
2104
|
+
const hasOverrides = Object.keys(roleOverrides).length > 0;
|
|
2105
|
+
const hasRenames = Object.keys(acceptedRenames).length > 0;
|
|
2106
|
+
const applyResult = await executeAttachSync(
|
|
2107
|
+
{
|
|
2108
|
+
identifier,
|
|
2109
|
+
attachmentsDirectory,
|
|
2110
|
+
yes: true,
|
|
2111
|
+
...idType && { idType },
|
|
2112
|
+
...hasOverrides && { roleOverrides },
|
|
2113
|
+
...hasRenames && { renames: acceptedRenames }
|
|
2114
|
+
},
|
|
2115
|
+
context
|
|
2116
|
+
);
|
|
2117
|
+
if (applyResult.success) {
|
|
2118
|
+
process.stderr.write(`
|
|
2119
|
+
Updated metadata for ${identifier}.
|
|
2120
|
+
`);
|
|
1889
2121
|
} else {
|
|
1890
|
-
process.stderr.write(`Sync error: ${
|
|
2122
|
+
process.stderr.write(`Sync error: ${applyResult.error}
|
|
1891
2123
|
`);
|
|
1892
2124
|
}
|
|
1893
2125
|
}
|
|
2126
|
+
async function runInteractiveMode(identifier, dirPath, attachmentsDirectory, idType, context) {
|
|
2127
|
+
displayNamingConvention(identifier, dirPath);
|
|
2128
|
+
await waitForEnter();
|
|
2129
|
+
await syncNewFilesWithRolePrompt(identifier, attachmentsDirectory, idType, context);
|
|
2130
|
+
}
|
|
1894
2131
|
function buildOpenOptions(identifier, filenameArg, options, attachmentsDirectory) {
|
|
1895
2132
|
return {
|
|
1896
2133
|
identifier,
|
|
@@ -2049,6 +2286,30 @@ async function handleAttachDetachAction(identifierArg, filenameArg, options, glo
|
|
|
2049
2286
|
setExitCode(ExitCode.INTERNAL_ERROR);
|
|
2050
2287
|
}
|
|
2051
2288
|
}
|
|
2289
|
+
async function promptForUnknownRoles(newFiles) {
|
|
2290
|
+
const overrides = {};
|
|
2291
|
+
const unknownFiles = newFiles.filter((f) => f.role === "other");
|
|
2292
|
+
if (unknownFiles.length === 0) return overrides;
|
|
2293
|
+
process.stderr.write("\nSome files could not be classified by filename:\n");
|
|
2294
|
+
const roleChoices = [
|
|
2295
|
+
...RESERVED_ROLES.map((r) => ({ label: r, value: r })),
|
|
2296
|
+
{ label: "other (keep as-is)", value: "other" }
|
|
2297
|
+
];
|
|
2298
|
+
for (const file of unknownFiles) {
|
|
2299
|
+
const suggested = suggestRoleFromContext(file.filename, newFiles);
|
|
2300
|
+
const defaultIndex = suggested ? roleChoices.findIndex((c) => c.value === suggested) : void 0;
|
|
2301
|
+
const selectedRole = await readChoice(
|
|
2302
|
+
`
|
|
2303
|
+
Role for "${file.filename}"?`,
|
|
2304
|
+
roleChoices,
|
|
2305
|
+
defaultIndex !== void 0 && defaultIndex >= 0 ? defaultIndex : void 0
|
|
2306
|
+
);
|
|
2307
|
+
if (selectedRole !== "other") {
|
|
2308
|
+
overrides[file.filename] = { role: selectedRole };
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
return overrides;
|
|
2312
|
+
}
|
|
2052
2313
|
async function runInteractiveSyncMode(identifier, attachmentsDirectory, idType, context) {
|
|
2053
2314
|
const dryRunOptions = {
|
|
2054
2315
|
identifier,
|
|
@@ -2063,7 +2324,12 @@ async function runInteractiveSyncMode(identifier, attachmentsDirectory, idType,
|
|
|
2063
2324
|
`);
|
|
2064
2325
|
return;
|
|
2065
2326
|
}
|
|
2066
|
-
|
|
2327
|
+
const roleOverrides = await promptForUnknownRoles(dryRunResult.newFiles);
|
|
2328
|
+
const renameMap = generateRenameMap(dryRunResult.newFiles, roleOverrides);
|
|
2329
|
+
const acceptedRenames = await promptForRenames(renameMap);
|
|
2330
|
+
const previewFiles = buildPreviewFiles(dryRunResult.newFiles, roleOverrides);
|
|
2331
|
+
const previewResult = { ...dryRunResult, newFiles: previewFiles };
|
|
2332
|
+
process.stderr.write(`${formatSyncPreview(previewResult)}
|
|
2067
2333
|
`);
|
|
2068
2334
|
const shouldApplyNew = hasNewFiles && await readConfirmation("Add new files to metadata?");
|
|
2069
2335
|
const shouldApplyFix = hasMissingFiles && await readConfirmation("Remove missing files from metadata?");
|
|
@@ -2071,16 +2337,70 @@ async function runInteractiveSyncMode(identifier, attachmentsDirectory, idType,
|
|
|
2071
2337
|
process.stderr.write("No changes applied.\n");
|
|
2072
2338
|
return;
|
|
2073
2339
|
}
|
|
2340
|
+
const hasRenames = Object.keys(acceptedRenames).length > 0;
|
|
2074
2341
|
const applyOptions = {
|
|
2075
2342
|
identifier,
|
|
2076
2343
|
attachmentsDirectory,
|
|
2077
2344
|
...shouldApplyNew && { yes: true },
|
|
2078
2345
|
...shouldApplyFix && { fix: true },
|
|
2346
|
+
...idType && { idType },
|
|
2347
|
+
...shouldApplyNew && Object.keys(roleOverrides).length > 0 && { roleOverrides },
|
|
2348
|
+
...shouldApplyNew && hasRenames && { renames: acceptedRenames }
|
|
2349
|
+
};
|
|
2350
|
+
const result = await executeAttachSync(applyOptions, context);
|
|
2351
|
+
process.stderr.write(`${formatAttachSyncOutput(result)}
|
|
2352
|
+
`);
|
|
2353
|
+
}
|
|
2354
|
+
async function handleSyncApplyWithSuggestions(identifier, attachmentsDirectory, idType, context, fix, noRename) {
|
|
2355
|
+
const dryRunOptions = {
|
|
2356
|
+
identifier,
|
|
2357
|
+
attachmentsDirectory,
|
|
2079
2358
|
...idType && { idType }
|
|
2080
2359
|
};
|
|
2360
|
+
const dryRunResult = await executeAttachSync(dryRunOptions, context);
|
|
2361
|
+
if (!dryRunResult.success) {
|
|
2362
|
+
process.stderr.write(`${formatAttachSyncOutput(dryRunResult)}
|
|
2363
|
+
`);
|
|
2364
|
+
setExitCode(getAttachExitCode(dryRunResult));
|
|
2365
|
+
return;
|
|
2366
|
+
}
|
|
2367
|
+
const suggestions = buildRoleOverridesFromSuggestions(dryRunResult.newFiles);
|
|
2368
|
+
const renames = noRename ? {} : generateRenameMap(dryRunResult.newFiles, suggestions);
|
|
2369
|
+
const hasRenames = Object.keys(renames).length > 0;
|
|
2370
|
+
const applyOptions = {
|
|
2371
|
+
identifier,
|
|
2372
|
+
attachmentsDirectory,
|
|
2373
|
+
yes: true,
|
|
2374
|
+
...fix && { fix: true },
|
|
2375
|
+
...idType && { idType },
|
|
2376
|
+
...Object.keys(suggestions).length > 0 && { roleOverrides: suggestions },
|
|
2377
|
+
...hasRenames && { renames }
|
|
2378
|
+
};
|
|
2081
2379
|
const result = await executeAttachSync(applyOptions, context);
|
|
2082
2380
|
process.stderr.write(`${formatAttachSyncOutput(result)}
|
|
2083
2381
|
`);
|
|
2382
|
+
setExitCode(getAttachExitCode(result));
|
|
2383
|
+
}
|
|
2384
|
+
async function handleSyncDryRunPreview(identifier, attachmentsDirectory, idType, context) {
|
|
2385
|
+
const dryRunOptions = {
|
|
2386
|
+
identifier,
|
|
2387
|
+
attachmentsDirectory,
|
|
2388
|
+
...idType && { idType }
|
|
2389
|
+
};
|
|
2390
|
+
const dryRunResult = await executeAttachSync(dryRunOptions, context);
|
|
2391
|
+
if (!dryRunResult.success) {
|
|
2392
|
+
process.stderr.write(`${formatAttachSyncOutput(dryRunResult)}
|
|
2393
|
+
`);
|
|
2394
|
+
setExitCode(getAttachExitCode(dryRunResult));
|
|
2395
|
+
return;
|
|
2396
|
+
}
|
|
2397
|
+
const suggestions = buildRoleOverridesFromSuggestions(dryRunResult.newFiles);
|
|
2398
|
+
const renames = generateRenameMap(dryRunResult.newFiles, suggestions);
|
|
2399
|
+
process.stderr.write(
|
|
2400
|
+
`${formatSyncPreviewWithSuggestions(dryRunResult, suggestions, renames, identifier)}
|
|
2401
|
+
`
|
|
2402
|
+
);
|
|
2403
|
+
setExitCode(getAttachExitCode(dryRunResult));
|
|
2084
2404
|
}
|
|
2085
2405
|
async function handleAttachSyncAction(identifierArg, options, globalOpts) {
|
|
2086
2406
|
try {
|
|
@@ -2089,17 +2409,31 @@ async function handleAttachSyncAction(identifierArg, options, globalOpts) {
|
|
|
2089
2409
|
const identifier = await resolveIdentifier(identifierArg, context, config2);
|
|
2090
2410
|
const attachmentsDirectory = config2.attachments.directory;
|
|
2091
2411
|
const idType = options.uuid ? "uuid" : void 0;
|
|
2092
|
-
|
|
2093
|
-
if (shouldUseInteractive) {
|
|
2412
|
+
if (isTTY() && !options.yes && !options.fix) {
|
|
2094
2413
|
await runInteractiveSyncMode(identifier, attachmentsDirectory, idType, context);
|
|
2095
2414
|
setExitCode(ExitCode.SUCCESS);
|
|
2096
2415
|
return;
|
|
2097
2416
|
}
|
|
2417
|
+
const noRename = options.noRename || options.rename === false;
|
|
2418
|
+
if (options.yes) {
|
|
2419
|
+
await handleSyncApplyWithSuggestions(
|
|
2420
|
+
identifier,
|
|
2421
|
+
attachmentsDirectory,
|
|
2422
|
+
idType,
|
|
2423
|
+
context,
|
|
2424
|
+
options.fix,
|
|
2425
|
+
noRename
|
|
2426
|
+
);
|
|
2427
|
+
return;
|
|
2428
|
+
}
|
|
2429
|
+
if (!options.fix) {
|
|
2430
|
+
await handleSyncDryRunPreview(identifier, attachmentsDirectory, idType, context);
|
|
2431
|
+
return;
|
|
2432
|
+
}
|
|
2098
2433
|
const syncOptions = {
|
|
2099
2434
|
identifier,
|
|
2100
2435
|
attachmentsDirectory,
|
|
2101
|
-
|
|
2102
|
-
...options.fix && { fix: true },
|
|
2436
|
+
fix: true,
|
|
2103
2437
|
...idType && { idType }
|
|
2104
2438
|
};
|
|
2105
2439
|
const result = await executeAttachSync(syncOptions, context);
|
|
@@ -2114,6 +2448,7 @@ async function handleAttachSyncAction(identifierArg, options, globalOpts) {
|
|
|
2114
2448
|
}
|
|
2115
2449
|
const attach = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2116
2450
|
__proto__: null,
|
|
2451
|
+
buildRoleOverridesFromSuggestions,
|
|
2117
2452
|
executeAttachAdd,
|
|
2118
2453
|
executeAttachDetach,
|
|
2119
2454
|
executeAttachGet,
|
|
@@ -2125,6 +2460,8 @@ const attach = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
|
|
|
2125
2460
|
formatAttachListOutput,
|
|
2126
2461
|
formatAttachOpenOutput,
|
|
2127
2462
|
formatAttachSyncOutput,
|
|
2463
|
+
formatSyncPreviewWithSuggestions,
|
|
2464
|
+
generateRenameMap,
|
|
2128
2465
|
getAttachExitCode,
|
|
2129
2466
|
handleAttachAddAction,
|
|
2130
2467
|
handleAttachDetachAction,
|
|
@@ -2132,7 +2469,8 @@ const attach = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
|
|
|
2132
2469
|
handleAttachListAction,
|
|
2133
2470
|
handleAttachOpenAction,
|
|
2134
2471
|
handleAttachSyncAction,
|
|
2135
|
-
runInteractiveMode
|
|
2472
|
+
runInteractiveMode,
|
|
2473
|
+
syncNewFilesWithRolePrompt
|
|
2136
2474
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
2137
2475
|
async function validateOptions$2(options) {
|
|
2138
2476
|
if (options.output && !["text", "html", "rtf"].includes(options.output)) {
|
|
@@ -2191,8 +2529,8 @@ function getCiteExitCode(result) {
|
|
|
2191
2529
|
}
|
|
2192
2530
|
async function executeInteractiveCite(options, context, config2) {
|
|
2193
2531
|
const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
|
|
2194
|
-
const { runCiteFlow } = await import("./index-
|
|
2195
|
-
const { buildStyleChoices, listCustomStyles } = await import("./style-select-
|
|
2532
|
+
const { runCiteFlow } = await import("./index-D--7n1SB.js");
|
|
2533
|
+
const { buildStyleChoices, listCustomStyles } = await import("./style-select-DxcSWBSF.js");
|
|
2196
2534
|
const { search } = await import("./file-watcher-CrsNHUpz.js").then((n) => n.z);
|
|
2197
2535
|
const { tokenize } = await import("./file-watcher-CrsNHUpz.js").then((n) => n.y);
|
|
2198
2536
|
const { checkTTY } = await import("./tty-BMyaEOhX.js");
|
|
@@ -6749,7 +7087,7 @@ function formatEditOutput(result) {
|
|
|
6749
7087
|
}
|
|
6750
7088
|
async function executeInteractiveEdit(options, context, config2) {
|
|
6751
7089
|
const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
|
|
6752
|
-
const { selectReferencesOrExit } = await import("./reference-select-
|
|
7090
|
+
const { selectReferencesOrExit } = await import("./reference-select-DrINWBuP.js");
|
|
6753
7091
|
const allReferences = await context.library.getAll();
|
|
6754
7092
|
const identifiers = await withAlternateScreen2(
|
|
6755
7093
|
() => selectReferencesOrExit(allReferences, { multiSelect: true }, config2.cli.tui)
|
|
@@ -10403,7 +10741,7 @@ function getFulltextExitCode(result) {
|
|
|
10403
10741
|
}
|
|
10404
10742
|
async function executeInteractiveSelect$1(context, config2) {
|
|
10405
10743
|
const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
|
|
10406
|
-
const { selectReferencesOrExit } = await import("./reference-select-
|
|
10744
|
+
const { selectReferencesOrExit } = await import("./reference-select-DrINWBuP.js");
|
|
10407
10745
|
const allReferences = await context.library.getAll();
|
|
10408
10746
|
const identifiers = await withAlternateScreen2(
|
|
10409
10747
|
() => selectReferencesOrExit(allReferences, { multiSelect: false }, config2.cli.tui)
|
|
@@ -31436,7 +31774,7 @@ async function mcpStart(options) {
|
|
|
31436
31774
|
async function executeRemove(options, context) {
|
|
31437
31775
|
const { identifier, idType = "id", fulltextDirectory, deleteFulltext = false } = options;
|
|
31438
31776
|
if (context.mode === "local" && deleteFulltext && fulltextDirectory) {
|
|
31439
|
-
const { removeReference } = await import("./index-
|
|
31777
|
+
const { removeReference } = await import("./index-DrZawbND.js").then((n) => n.r);
|
|
31440
31778
|
return removeReference(context.library, {
|
|
31441
31779
|
identifier,
|
|
31442
31780
|
idType,
|
|
@@ -31491,7 +31829,7 @@ Continue?`;
|
|
|
31491
31829
|
}
|
|
31492
31830
|
async function executeInteractiveRemove(context, config2) {
|
|
31493
31831
|
const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
|
|
31494
|
-
const { selectReferenceItemsOrExit } = await import("./reference-select-
|
|
31832
|
+
const { selectReferenceItemsOrExit } = await import("./reference-select-DrINWBuP.js");
|
|
31495
31833
|
const allReferences = await context.library.getAll();
|
|
31496
31834
|
const selectedItems = await withAlternateScreen2(
|
|
31497
31835
|
() => selectReferenceItemsOrExit(allReferences, { multiSelect: false }, config2.cli.tui)
|
|
@@ -31716,7 +32054,7 @@ async function executeInteractiveSearch(options, context, config2) {
|
|
|
31716
32054
|
validateInteractiveOptions(options);
|
|
31717
32055
|
const { checkTTY } = await import("./tty-BMyaEOhX.js");
|
|
31718
32056
|
const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
|
|
31719
|
-
const { runSearchFlow } = await import("./index-
|
|
32057
|
+
const { runSearchFlow } = await import("./index-D--7n1SB.js");
|
|
31720
32058
|
const { search } = await import("./file-watcher-CrsNHUpz.js").then((n) => n.z);
|
|
31721
32059
|
const { tokenize } = await import("./file-watcher-CrsNHUpz.js").then((n) => n.y);
|
|
31722
32060
|
checkTTY();
|
|
@@ -31735,7 +32073,7 @@ async function executeInteractiveSearch(options, context, config2) {
|
|
|
31735
32073
|
})
|
|
31736
32074
|
);
|
|
31737
32075
|
if (result.selectedItems && !result.cancelled) {
|
|
31738
|
-
const { isSideEffectAction } = await import("./action-menu-
|
|
32076
|
+
const { isSideEffectAction } = await import("./action-menu-Brg5Lmz7.js");
|
|
31739
32077
|
if (isSideEffectAction(result.action)) {
|
|
31740
32078
|
await executeSideEffectAction(result.action, result.selectedItems, context, config2);
|
|
31741
32079
|
return { output: "", cancelled: false, action: result.action };
|
|
@@ -32138,7 +32476,7 @@ function formatUpdateOutput(result, identifier) {
|
|
|
32138
32476
|
}
|
|
32139
32477
|
async function executeInteractiveUpdate(context, config2) {
|
|
32140
32478
|
const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
|
|
32141
|
-
const { selectReferencesOrExit } = await import("./reference-select-
|
|
32479
|
+
const { selectReferencesOrExit } = await import("./reference-select-DrINWBuP.js");
|
|
32142
32480
|
const allReferences = await context.library.getAll();
|
|
32143
32481
|
const identifiers = await withAlternateScreen2(
|
|
32144
32482
|
() => selectReferencesOrExit(allReferences, { multiSelect: false }, config2.cli.tui)
|
|
@@ -32433,7 +32771,7 @@ function getUrlExitCode(result) {
|
|
|
32433
32771
|
}
|
|
32434
32772
|
async function executeInteractiveSelect(context, config2) {
|
|
32435
32773
|
const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
|
|
32436
|
-
const { selectReferencesOrExit } = await import("./reference-select-
|
|
32774
|
+
const { selectReferencesOrExit } = await import("./reference-select-DrINWBuP.js");
|
|
32437
32775
|
const allReferences = await context.library.getAll();
|
|
32438
32776
|
const identifiers = await withAlternateScreen2(
|
|
32439
32777
|
() => selectReferencesOrExit(allReferences, { multiSelect: false }, config2.cli.tui)
|
|
@@ -33116,7 +33454,7 @@ function registerAttachCommand(program) {
|
|
|
33116
33454
|
attachCmd.command("detach").description("Detach file from a reference").argument("[identifier]", "Citation key or UUID (interactive selection if omitted)").argument("[filename]", "Specific file to detach").option("--role <role>", "Detach files by role").option("--all", "Detach all files of specified role").option("--remove-files", "Also delete files from disk").option("--uuid", "Interpret identifier as UUID").action(async (identifier, filename, options) => {
|
|
33117
33455
|
await handleAttachDetachAction(identifier, filename, options, program.opts());
|
|
33118
33456
|
});
|
|
33119
|
-
attachCmd.command("sync").description("Synchronize metadata with files on disk").argument("[identifier]", "Citation key or UUID (interactive selection if omitted)").option("--yes", "Apply changes (add new files)").option("--fix", "Remove missing files from metadata").option("--uuid", "Interpret identifier as UUID").action(async (identifier, options) => {
|
|
33457
|
+
attachCmd.command("sync").description("Synchronize metadata with files on disk").argument("[identifier]", "Citation key or UUID (interactive selection if omitted)").option("--yes", "Apply changes (add new files)").option("--fix", "Remove missing files from metadata").option("--no-rename", "Skip file renaming (keep original filenames)").option("--uuid", "Interpret identifier as UUID").action(async (identifier, options) => {
|
|
33120
33458
|
await handleAttachSyncAction(identifier, options, program.opts());
|
|
33121
33459
|
});
|
|
33122
33460
|
}
|
|
@@ -33170,4 +33508,4 @@ export {
|
|
|
33170
33508
|
restoreStdinAfterInk as r,
|
|
33171
33509
|
syncAttachments as s
|
|
33172
33510
|
};
|
|
33173
|
-
//# sourceMappingURL=index-
|
|
33511
|
+
//# sourceMappingURL=index-Cno7_aWr.js.map
|