@ncukondo/reference-manager 0.1.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.
Files changed (117) hide show
  1. package/README.md +167 -0
  2. package/bin/reference-manager.js +5 -0
  3. package/dist/chunks/detector-BF8Mcc72.js +1415 -0
  4. package/dist/chunks/detector-BF8Mcc72.js.map +1 -0
  5. package/dist/cli/commands/add.d.ts +22 -0
  6. package/dist/cli/commands/add.d.ts.map +1 -0
  7. package/dist/cli/commands/index.d.ts +16 -0
  8. package/dist/cli/commands/index.d.ts.map +1 -0
  9. package/dist/cli/commands/list.d.ts +15 -0
  10. package/dist/cli/commands/list.d.ts.map +1 -0
  11. package/dist/cli/commands/remove.d.ts +19 -0
  12. package/dist/cli/commands/remove.d.ts.map +1 -0
  13. package/dist/cli/commands/search.d.ts +16 -0
  14. package/dist/cli/commands/search.d.ts.map +1 -0
  15. package/dist/cli/commands/server.d.ts +32 -0
  16. package/dist/cli/commands/server.d.ts.map +1 -0
  17. package/dist/cli/commands/update.d.ts +20 -0
  18. package/dist/cli/commands/update.d.ts.map +1 -0
  19. package/dist/cli/helpers.d.ts +61 -0
  20. package/dist/cli/helpers.d.ts.map +1 -0
  21. package/dist/cli/index.d.ts +13 -0
  22. package/dist/cli/index.d.ts.map +1 -0
  23. package/dist/cli/output/bibtex.d.ts +6 -0
  24. package/dist/cli/output/bibtex.d.ts.map +1 -0
  25. package/dist/cli/output/index.d.ts +7 -0
  26. package/dist/cli/output/index.d.ts.map +1 -0
  27. package/dist/cli/output/json.d.ts +6 -0
  28. package/dist/cli/output/json.d.ts.map +1 -0
  29. package/dist/cli/output/pretty.d.ts +6 -0
  30. package/dist/cli/output/pretty.d.ts.map +1 -0
  31. package/dist/cli/server-client.d.ts +38 -0
  32. package/dist/cli/server-client.d.ts.map +1 -0
  33. package/dist/cli/server-detection.d.ts +27 -0
  34. package/dist/cli/server-detection.d.ts.map +1 -0
  35. package/dist/cli.js +981 -0
  36. package/dist/cli.js.map +1 -0
  37. package/dist/config/defaults.d.ts +29 -0
  38. package/dist/config/defaults.d.ts.map +1 -0
  39. package/dist/config/index.d.ts +10 -0
  40. package/dist/config/index.d.ts.map +1 -0
  41. package/dist/config/loader.d.ts +27 -0
  42. package/dist/config/loader.d.ts.map +1 -0
  43. package/dist/config/schema.d.ts +129 -0
  44. package/dist/config/schema.d.ts.map +1 -0
  45. package/dist/core/csl-json/parser.d.ts +9 -0
  46. package/dist/core/csl-json/parser.d.ts.map +1 -0
  47. package/dist/core/csl-json/serializer.d.ts +15 -0
  48. package/dist/core/csl-json/serializer.d.ts.map +1 -0
  49. package/dist/core/csl-json/types.d.ts +124 -0
  50. package/dist/core/csl-json/types.d.ts.map +1 -0
  51. package/dist/core/csl-json/validator.d.ts +19 -0
  52. package/dist/core/csl-json/validator.d.ts.map +1 -0
  53. package/dist/core/identifier/generator.d.ts +17 -0
  54. package/dist/core/identifier/generator.d.ts.map +1 -0
  55. package/dist/core/identifier/normalize.d.ts +20 -0
  56. package/dist/core/identifier/normalize.d.ts.map +1 -0
  57. package/dist/core/identifier/uuid.d.ts +24 -0
  58. package/dist/core/identifier/uuid.d.ts.map +1 -0
  59. package/dist/core/index.d.ts +15 -0
  60. package/dist/core/index.d.ts.map +1 -0
  61. package/dist/core/library.d.ts +73 -0
  62. package/dist/core/library.d.ts.map +1 -0
  63. package/dist/core/reference.d.ts +86 -0
  64. package/dist/core/reference.d.ts.map +1 -0
  65. package/dist/features/duplicate/detector.d.ts +19 -0
  66. package/dist/features/duplicate/detector.d.ts.map +1 -0
  67. package/dist/features/duplicate/index.d.ts +6 -0
  68. package/dist/features/duplicate/index.d.ts.map +1 -0
  69. package/dist/features/duplicate/types.d.ts +45 -0
  70. package/dist/features/duplicate/types.d.ts.map +1 -0
  71. package/dist/features/file-watcher/file-watcher.d.ts +83 -0
  72. package/dist/features/file-watcher/file-watcher.d.ts.map +1 -0
  73. package/dist/features/file-watcher/index.d.ts +2 -0
  74. package/dist/features/file-watcher/index.d.ts.map +1 -0
  75. package/dist/features/merge/index.d.ts +8 -0
  76. package/dist/features/merge/index.d.ts.map +1 -0
  77. package/dist/features/merge/three-way.d.ts +16 -0
  78. package/dist/features/merge/three-way.d.ts.map +1 -0
  79. package/dist/features/merge/types.d.ts +74 -0
  80. package/dist/features/merge/types.d.ts.map +1 -0
  81. package/dist/features/search/index.d.ts +9 -0
  82. package/dist/features/search/index.d.ts.map +1 -0
  83. package/dist/features/search/matcher.d.ts +18 -0
  84. package/dist/features/search/matcher.d.ts.map +1 -0
  85. package/dist/features/search/normalizer.d.ts +12 -0
  86. package/dist/features/search/normalizer.d.ts.map +1 -0
  87. package/dist/features/search/sorter.d.ts +11 -0
  88. package/dist/features/search/sorter.d.ts.map +1 -0
  89. package/dist/features/search/tokenizer.d.ts +6 -0
  90. package/dist/features/search/tokenizer.d.ts.map +1 -0
  91. package/dist/features/search/types.d.ts +77 -0
  92. package/dist/features/search/types.d.ts.map +1 -0
  93. package/dist/index.d.ts +13 -0
  94. package/dist/index.d.ts.map +1 -0
  95. package/dist/index.js +559 -0
  96. package/dist/index.js.map +1 -0
  97. package/dist/server/index.d.ts +9 -0
  98. package/dist/server/index.d.ts.map +1 -0
  99. package/dist/server/portfile.d.ts +43 -0
  100. package/dist/server/portfile.d.ts.map +1 -0
  101. package/dist/server/routes/health.d.ts +7 -0
  102. package/dist/server/routes/health.d.ts.map +1 -0
  103. package/dist/server/routes/references.d.ts +9 -0
  104. package/dist/server/routes/references.d.ts.map +1 -0
  105. package/dist/server.js +91 -0
  106. package/dist/server.js.map +1 -0
  107. package/dist/utils/backup.d.ts +21 -0
  108. package/dist/utils/backup.d.ts.map +1 -0
  109. package/dist/utils/file.d.ts +9 -0
  110. package/dist/utils/file.d.ts.map +1 -0
  111. package/dist/utils/hash.d.ts +9 -0
  112. package/dist/utils/hash.d.ts.map +1 -0
  113. package/dist/utils/index.d.ts +5 -0
  114. package/dist/utils/index.d.ts.map +1 -0
  115. package/dist/utils/logger.d.ts +8 -0
  116. package/dist/utils/logger.d.ts.map +1 -0
  117. package/package.json +72 -0
@@ -0,0 +1,24 @@
1
+ import type { CslCustom } from "../csl-json/types";
2
+ /**
3
+ * Validate if a string is a valid UUID v4
4
+ */
5
+ export declare function isValidUuid(uuid: string): boolean;
6
+ /**
7
+ * Generate a new UUID v4
8
+ */
9
+ export declare function generateUuid(): string;
10
+ /**
11
+ * Generate a new ISO 8601 timestamp
12
+ */
13
+ export declare function generateTimestamp(): string;
14
+ /**
15
+ * Extract UUID from custom field
16
+ */
17
+ export declare function extractUuidFromCustom(custom: CslCustom | undefined): string | null;
18
+ /**
19
+ * Ensure custom metadata has valid UUID, created_at, and timestamp
20
+ * Handles legacy migration from old timestamp-only format
21
+ * Generates new values if missing or invalid
22
+ */
23
+ export declare function ensureCustomMetadata(custom: CslCustom | undefined): CslCustom;
24
+ //# sourceMappingURL=uuid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uuid.d.ts","sourceRoot":"","sources":["../../../src/core/identifier/uuid.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAInD;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAMlF;AAoED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAK7E"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Core module exports
3
+ */
4
+ export { Reference } from "./reference";
5
+ export type { ReferenceCreateOptions } from "./reference";
6
+ export { Library } from "./library";
7
+ export type { CslItem, CslLibrary, CslCustom } from "./csl-json/types";
8
+ export { CslItemSchema, CslLibrarySchema } from "./csl-json/types";
9
+ export { parseCslJson } from "./csl-json/parser";
10
+ export { serializeCslJson, writeCslJson } from "./csl-json/serializer";
11
+ export { validateCslJson } from "./csl-json/validator";
12
+ export { generateId, generateIdWithCollisionCheck } from "./identifier/generator";
13
+ export { normalizeText } from "./identifier/normalize";
14
+ export { generateUuid, isValidUuid, ensureCustomMetadata, extractUuidFromCustom, } from "./identifier/uuid";
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGvD,OAAO,EAAE,UAAU,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EACL,YAAY,EACZ,WAAW,EACX,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,73 @@
1
+ import type { CslItem } from "./csl-json/types";
2
+ import { Reference } from "./reference";
3
+ /**
4
+ * Library manager for CSL-JSON references
5
+ */
6
+ export declare class Library {
7
+ private filePath;
8
+ private references;
9
+ private currentHash;
10
+ private uuidIndex;
11
+ private idIndex;
12
+ private doiIndex;
13
+ private pmidIndex;
14
+ private constructor();
15
+ /**
16
+ * Load library from file
17
+ */
18
+ static load(filePath: string): Promise<Library>;
19
+ /**
20
+ * Save library to file
21
+ */
22
+ save(): Promise<void>;
23
+ /**
24
+ * Add a reference to the library
25
+ */
26
+ add(item: CslItem): void;
27
+ /**
28
+ * Remove a reference by UUID
29
+ */
30
+ removeByUuid(uuid: string): boolean;
31
+ /**
32
+ * Remove a reference by ID
33
+ */
34
+ removeById(id: string): boolean;
35
+ /**
36
+ * Find a reference by UUID
37
+ */
38
+ findByUuid(uuid: string): Reference | undefined;
39
+ /**
40
+ * Find a reference by ID
41
+ */
42
+ findById(id: string): Reference | undefined;
43
+ /**
44
+ * Find a reference by DOI
45
+ */
46
+ findByDoi(doi: string): Reference | undefined;
47
+ /**
48
+ * Find a reference by PMID
49
+ */
50
+ findByPmid(pmid: string): Reference | undefined;
51
+ /**
52
+ * Get all references
53
+ */
54
+ getAll(): Reference[];
55
+ /**
56
+ * Get the file path
57
+ */
58
+ getFilePath(): string;
59
+ /**
60
+ * Get the current file hash
61
+ * Returns null if the library has not been loaded or saved yet
62
+ */
63
+ getCurrentHash(): string | null;
64
+ /**
65
+ * Add reference to all indices
66
+ */
67
+ private addToIndices;
68
+ /**
69
+ * Remove reference from all indices and array
70
+ */
71
+ private removeReference;
72
+ }
73
+ //# sourceMappingURL=library.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"library.d.ts","sourceRoot":"","sources":["../../src/core/library.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC;;GAEG;AACH,qBAAa,OAAO;IAClB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAmB;IACrC,OAAO,CAAC,WAAW,CAAuB;IAG1C,OAAO,CAAC,SAAS,CAAqC;IACtD,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,QAAQ,CAAqC;IACrD,OAAO,CAAC,SAAS,CAAqC;IAEtD,OAAO;IAWP;;OAEG;WACU,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQrD;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAYxB;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IASnC;;OAEG;IACH,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAS/B;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAI/C;;OAEG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAI3C;;OAEG;IACH,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAI7C;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAI/C;;OAEG;IACH,MAAM,IAAI,SAAS,EAAE;IAIrB;;OAEG;IACH,WAAW,IAAI,MAAM;IAIrB;;;OAGG;IACH,cAAc,IAAI,MAAM,GAAG,IAAI;IAI/B;;OAEG;IACH,OAAO,CAAC,YAAY;IAoBpB;;OAEG;IACH,OAAO,CAAC,eAAe;CAwBxB"}
@@ -0,0 +1,86 @@
1
+ import type { CslItem } from "./csl-json/types";
2
+ /**
3
+ * Options for creating a Reference
4
+ */
5
+ export interface ReferenceCreateOptions {
6
+ /** Existing IDs to check for collision */
7
+ existingIds?: Set<string>;
8
+ }
9
+ /**
10
+ * Reference entity wrapping a CSL-JSON item
11
+ */
12
+ export declare class Reference {
13
+ private item;
14
+ private uuid;
15
+ constructor(item: CslItem);
16
+ /**
17
+ * Factory method to create a Reference with UUID and ID generation
18
+ */
19
+ static create(item: CslItem, options?: ReferenceCreateOptions): Reference;
20
+ /**
21
+ * Get the underlying CSL-JSON item
22
+ */
23
+ getItem(): CslItem;
24
+ /**
25
+ * Get the UUID (internal stable identifier)
26
+ */
27
+ getUuid(): string;
28
+ /**
29
+ * Get the ID (Pandoc citation key / BibTeX-key)
30
+ */
31
+ getId(): string;
32
+ /**
33
+ * Get the title
34
+ */
35
+ getTitle(): string | undefined;
36
+ /**
37
+ * Get the authors
38
+ */
39
+ getAuthors(): CslItem["author"];
40
+ /**
41
+ * Get the year from issued date
42
+ */
43
+ getYear(): number | undefined;
44
+ /**
45
+ * Get the DOI
46
+ */
47
+ getDoi(): string | undefined;
48
+ /**
49
+ * Get the PMID
50
+ */
51
+ getPmid(): string | undefined;
52
+ /**
53
+ * Get the PMCID
54
+ */
55
+ getPmcid(): string | undefined;
56
+ /**
57
+ * Get the URL
58
+ */
59
+ getUrl(): string | undefined;
60
+ /**
61
+ * Get the keyword
62
+ */
63
+ getKeyword(): string[] | undefined;
64
+ /**
65
+ * Get additional URLs from custom metadata
66
+ */
67
+ getAdditionalUrls(): string[] | undefined;
68
+ /**
69
+ * Get the creation timestamp from custom metadata (immutable)
70
+ */
71
+ getCreatedAt(): string;
72
+ /**
73
+ * Get the last modification timestamp from custom metadata
74
+ */
75
+ getTimestamp(): string;
76
+ /**
77
+ * Update the timestamp to current time
78
+ * Call this whenever the reference is modified
79
+ */
80
+ touch(): void;
81
+ /**
82
+ * Get the type
83
+ */
84
+ getType(): string;
85
+ }
86
+ //# sourceMappingURL=reference.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reference.d.ts","sourceRoot":"","sources":["../../src/core/reference.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAIhD;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,0CAA0C;IAC1C,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC3B;AAED;;GAEG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,IAAI,CAAU;IACtB,OAAO,CAAC,IAAI,CAAS;gBAET,IAAI,EAAE,OAAO;IAazB;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,SAAS;IAazE;;OAEG;IACH,OAAO,IAAI,OAAO;IAIlB;;OAEG;IACH,OAAO,IAAI,MAAM;IAIjB;;OAEG;IACH,KAAK,IAAI,MAAM;IAIf;;OAEG;IACH,QAAQ,IAAI,MAAM,GAAG,SAAS;IAI9B;;OAEG;IACH,UAAU,IAAI,OAAO,CAAC,QAAQ,CAAC;IAI/B;;OAEG;IACH,OAAO,IAAI,MAAM,GAAG,SAAS;IAS7B;;OAEG;IACH,MAAM,IAAI,MAAM,GAAG,SAAS;IAI5B;;OAEG;IACH,OAAO,IAAI,MAAM,GAAG,SAAS;IAI7B;;OAEG;IACH,QAAQ,IAAI,MAAM,GAAG,SAAS;IAI9B;;OAEG;IACH,MAAM,IAAI,MAAM,GAAG,SAAS;IAI5B;;OAEG;IACH,UAAU,IAAI,MAAM,EAAE,GAAG,SAAS;IAIlC;;OAEG;IACH,iBAAiB,IAAI,MAAM,EAAE,GAAG,SAAS;IAIzC;;OAEG;IACH,YAAY,IAAI,MAAM;IAOtB;;OAEG;IACH,YAAY,IAAI,MAAM;IAOtB;;;OAGG;IACH,KAAK,IAAI,IAAI;IAOb;;OAEG;IACH,OAAO,IAAI,MAAM;CAGlB"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Duplicate detection logic
3
+ */
4
+ import type { CslItem } from "../../core/csl-json/types.js";
5
+ import type { DuplicateResult } from "./types.js";
6
+ /**
7
+ * Detects if a reference is a duplicate of any existing references
8
+ *
9
+ * Priority order:
10
+ * 1. DOI (highest priority)
11
+ * 2. PMID
12
+ * 3. Title + Author + Year (lowest priority)
13
+ *
14
+ * @param item - The reference to check for duplicates
15
+ * @param existingReferences - Array of existing references to check against
16
+ * @returns DuplicateResult indicating if duplicate found and match details
17
+ */
18
+ export declare function detectDuplicate(item: CslItem, existingReferences: CslItem[]): DuplicateResult;
19
+ //# sourceMappingURL=detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../../../src/features/duplicate/detector.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAE5D,OAAO,KAAK,EAAkB,eAAe,EAAE,MAAM,YAAY,CAAC;AAwJlE;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAE,GAAG,eAAe,CAoB7F"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Duplicate detection exports
3
+ */
4
+ export * from "./types.js";
5
+ export { detectDuplicate } from "./detector.js";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/features/duplicate/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Duplicate detection types
3
+ */
4
+ import type { CslItem } from "../../core/csl-json/types.js";
5
+ /**
6
+ * Type of duplicate match
7
+ */
8
+ export type DuplicateType = "doi" | "pmid" | "title-author-year";
9
+ /**
10
+ * A single duplicate match result
11
+ */
12
+ export interface DuplicateMatch {
13
+ /**
14
+ * The type of duplicate detected
15
+ */
16
+ type: DuplicateType;
17
+ /**
18
+ * The existing reference that matches
19
+ */
20
+ existing: CslItem;
21
+ /**
22
+ * Optional match details (e.g., normalized values used for comparison)
23
+ */
24
+ details?: {
25
+ doi?: string;
26
+ pmid?: string;
27
+ normalizedTitle?: string;
28
+ normalizedAuthors?: string;
29
+ year?: string;
30
+ };
31
+ }
32
+ /**
33
+ * Result of duplicate detection
34
+ */
35
+ export interface DuplicateResult {
36
+ /**
37
+ * Whether a duplicate was found
38
+ */
39
+ isDuplicate: boolean;
40
+ /**
41
+ * Array of duplicate matches (can have multiple matches)
42
+ */
43
+ matches: DuplicateMatch[];
44
+ }
45
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/features/duplicate/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAE5D;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,MAAM,GAAG,mBAAmB,CAAC;AAEjE;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,IAAI,EAAE,aAAa,CAAC;IAEpB;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;IAElB;;OAEG;IACH,OAAO,CAAC,EAAE;QACR,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,WAAW,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,OAAO,EAAE,cAAc,EAAE,CAAC;CAC3B"}
@@ -0,0 +1,83 @@
1
+ import { EventEmitter } from "node:events";
2
+ /**
3
+ * Options for FileWatcher
4
+ */
5
+ export interface FileWatcherOptions {
6
+ /** Debounce time in milliseconds (default: 500) */
7
+ debounceMs?: number;
8
+ /** Poll interval in milliseconds for polling mode (default: 5000) */
9
+ pollIntervalMs?: number;
10
+ /** Use polling instead of native file system events */
11
+ usePolling?: boolean;
12
+ /** Retry delay in milliseconds for JSON parse (default: 200) */
13
+ retryDelayMs?: number;
14
+ /** Maximum number of retries for JSON parse (default: 10) */
15
+ maxRetries?: number;
16
+ }
17
+ /**
18
+ * FileWatcher watches a file or directory for changes and emits events.
19
+ *
20
+ * Events:
21
+ * - 'change': Emitted when a watched file changes (after debounce)
22
+ * - 'error': Emitted when a watch error occurs
23
+ * - 'ready': Emitted when watching has started
24
+ * - 'parsed': Emitted when JSON file is successfully parsed
25
+ * - 'parseError': Emitted when JSON parse fails after all retries
26
+ */
27
+ export declare class FileWatcher extends EventEmitter {
28
+ private readonly watchPath;
29
+ private readonly debounceMs;
30
+ private readonly pollIntervalMs;
31
+ private readonly usePolling;
32
+ private readonly retryDelayMs;
33
+ private readonly maxRetries;
34
+ private watcher;
35
+ private watching;
36
+ private debounceTimers;
37
+ constructor(watchPath: string, options?: FileWatcherOptions);
38
+ /**
39
+ * Start watching for file changes
40
+ */
41
+ start(): Promise<void>;
42
+ /**
43
+ * Handle file change with debouncing
44
+ */
45
+ private handleFileChange;
46
+ /**
47
+ * Try to parse JSON file with retries
48
+ */
49
+ private tryParseJsonFile;
50
+ /**
51
+ * Delay helper
52
+ */
53
+ private delay;
54
+ /**
55
+ * Stop watching for file changes
56
+ */
57
+ close(): void;
58
+ /**
59
+ * Get the watched path
60
+ */
61
+ getPath(): string;
62
+ /**
63
+ * Check if the watcher is currently active
64
+ */
65
+ isWatching(): boolean;
66
+ /**
67
+ * Get the debounce time in milliseconds
68
+ */
69
+ getDebounceMs(): number;
70
+ /**
71
+ * Get the poll interval in milliseconds
72
+ */
73
+ getPollIntervalMs(): number;
74
+ /**
75
+ * Get the retry delay in milliseconds
76
+ */
77
+ getRetryDelayMs(): number;
78
+ /**
79
+ * Get the maximum number of retries
80
+ */
81
+ getMaxRetries(): number;
82
+ }
83
+ //# sourceMappingURL=file-watcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-watcher.d.ts","sourceRoot":"","sources":["../../../src/features/file-watcher/file-watcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK3C;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,mDAAmD;IACnD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qEAAqE;IACrE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uDAAuD;IACvD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAyCD;;;;;;;;;GASG;AACH,qBAAa,WAAY,SAAQ,YAAY;IAC3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;IACrC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IAEpC,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,cAAc,CAA0C;gBAEpD,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB;IAU3D;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAsC5B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAiBxB;;OAEG;YACW,gBAAgB;IAyB9B;;OAEG;IACH,OAAO,CAAC,KAAK;IAIb;;OAEG;IACH,KAAK,IAAI,IAAI;IAeb;;OAEG;IACH,OAAO,IAAI,MAAM;IAIjB;;OAEG;IACH,UAAU,IAAI,OAAO;IAIrB;;OAEG;IACH,aAAa,IAAI,MAAM;IAIvB;;OAEG;IACH,iBAAiB,IAAI,MAAM;IAI3B;;OAEG;IACH,eAAe,IAAI,MAAM;IAIzB;;OAEG;IACH,aAAa,IAAI,MAAM;CAGxB"}
@@ -0,0 +1,2 @@
1
+ export { FileWatcher, type FileWatcherOptions } from "./file-watcher";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/features/file-watcher/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * 3-way merge module
3
+ *
4
+ * Provides Last-Write-Wins (LWW) merge strategy for CSL-JSON items
5
+ */
6
+ export type { FieldConflict, ItemConflict, MergeOptions, MergeResult, MergeStatus, PreferOption, } from "./types.js";
7
+ export { threeWayMerge } from "./three-way.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/features/merge/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EACV,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,WAAW,EACX,YAAY,GACb,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * 3-way merge implementation with Last-Write-Wins (LWW) strategy
3
+ */
4
+ import type { CslItem } from "../../core/csl-json/types.js";
5
+ import type { MergeOptions, MergeResult } from "./types.js";
6
+ /**
7
+ * Performs a 3-way merge of CSL-JSON items
8
+ *
9
+ * @param base - Base version (common ancestor)
10
+ * @param local - Local version (current working copy)
11
+ * @param remote - Remote version (incoming changes)
12
+ * @param options - Merge options (e.g., prefer local/remote for tie-breaking)
13
+ * @returns Merge result with merged items and conflict information
14
+ */
15
+ export declare function threeWayMerge(base: CslItem[], local: CslItem[], remote: CslItem[], options?: MergeOptions): MergeResult;
16
+ //# sourceMappingURL=three-way.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"three-way.d.ts","sourceRoot":"","sources":["../../../src/features/merge/three-way.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,KAAK,EAGV,YAAY,EACZ,WAAW,EAEZ,MAAM,YAAY,CAAC;AA2TpB;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,OAAO,EAAE,EACf,KAAK,EAAE,OAAO,EAAE,EAChB,MAAM,EAAE,OAAO,EAAE,EACjB,OAAO,CAAC,EAAE,YAAY,GACrB,WAAW,CA6Bb"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * 3-way merge types for Last-Write-Wins (LWW) conflict resolution
3
+ */
4
+ import type { CslItem } from "../../core/csl-json/types.js";
5
+ /**
6
+ * Preference option for tie-breaking when timestamps are equal
7
+ */
8
+ export type PreferOption = "local" | "remote";
9
+ /**
10
+ * Merge options
11
+ */
12
+ export interface MergeOptions {
13
+ /**
14
+ * Tie-breaker when custom.timestamp values are equal
15
+ * If not provided and timestamps are equal, conflict is reported
16
+ */
17
+ prefer?: PreferOption;
18
+ }
19
+ /**
20
+ * Information about a field conflict
21
+ */
22
+ export interface FieldConflict {
23
+ /** Field path (e.g., "title", "author[0].family") */
24
+ field: string;
25
+ /** Value in base version */
26
+ base: unknown;
27
+ /** Value in local version */
28
+ local: unknown;
29
+ /** Value in remote version */
30
+ remote: unknown;
31
+ /** Chosen value (based on LWW or prefer option) */
32
+ resolved?: unknown;
33
+ }
34
+ /**
35
+ * Information about a conflicted item
36
+ */
37
+ export interface ItemConflict {
38
+ /** UUID of the conflicted item */
39
+ uuid: string;
40
+ /** ID (citation key) of the item */
41
+ id: string;
42
+ /** List of conflicting fields */
43
+ fields: FieldConflict[];
44
+ /** Local timestamp */
45
+ localTimestamp: string;
46
+ /** Remote timestamp */
47
+ remoteTimestamp: string;
48
+ /** How the conflict was resolved */
49
+ resolution: "auto-lww" | "prefer-local" | "prefer-remote" | "unresolved";
50
+ }
51
+ /**
52
+ * Merge status
53
+ */
54
+ export type MergeStatus = "success" | "auto-resolved" | "conflict";
55
+ /**
56
+ * Result of a 3-way merge operation
57
+ */
58
+ export interface MergeResult {
59
+ /** Merge status */
60
+ status: MergeStatus;
61
+ /** Merged items (all items from both sides, with conflicts resolved) */
62
+ merged: CslItem[];
63
+ /** List of conflicts (empty if status is 'success') */
64
+ conflicts: ItemConflict[];
65
+ /** Items only in local (additions in local) */
66
+ localOnly: CslItem[];
67
+ /** Items only in remote (additions in remote) */
68
+ remoteOnly: CslItem[];
69
+ /** Items deleted in local (present in base, absent in local) */
70
+ deletedInLocal: CslItem[];
71
+ /** Items deleted in remote (present in base, absent in remote) */
72
+ deletedInRemote: CslItem[];
73
+ }
74
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/features/merge/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAE5D;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,4BAA4B;IAC5B,IAAI,EAAE,OAAO,CAAC;IACd,6BAA6B;IAC7B,KAAK,EAAE,OAAO,CAAC;IACf,8BAA8B;IAC9B,MAAM,EAAE,OAAO,CAAC;IAChB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,iCAAiC;IACjC,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,sBAAsB;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,uBAAuB;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,oCAAoC;IACpC,UAAU,EAAE,UAAU,GAAG,cAAc,GAAG,eAAe,GAAG,YAAY,CAAC;CAC1E;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GACnB,SAAS,GACT,eAAe,GACf,UAAU,CAAC;AAEf;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,mBAAmB;IACnB,MAAM,EAAE,WAAW,CAAC;IACpB,wEAAwE;IACxE,MAAM,EAAE,OAAO,EAAE,CAAC;IAClB,uDAAuD;IACvD,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,+CAA+C;IAC/C,SAAS,EAAE,OAAO,EAAE,CAAC;IACrB,iDAAiD;IACjD,UAAU,EAAE,OAAO,EAAE,CAAC;IACtB,gEAAgE;IAChE,cAAc,EAAE,OAAO,EAAE,CAAC;IAC1B,kEAAkE;IAClE,eAAe,EAAE,OAAO,EAAE,CAAC;CAC5B"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Search feature exports
3
+ */
4
+ export * from "./types.js";
5
+ export { tokenize } from "./tokenizer.js";
6
+ export { normalize } from "./normalizer.js";
7
+ export { search } from "./matcher.js";
8
+ export { sortResults } from "./sorter.js";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/features/search/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { CslItem } from "../../core/csl-json/types.js";
2
+ import type { FieldMatch, SearchResult, SearchToken } from "./types.js";
3
+ /**
4
+ * Match a single token against a reference
5
+ * Returns an array of field matches
6
+ */
7
+ export declare function matchToken(token: SearchToken, reference: CslItem): FieldMatch[];
8
+ /**
9
+ * Match a reference against all search tokens
10
+ * Returns a SearchResult if all tokens match (AND logic), null otherwise
11
+ */
12
+ export declare function matchReference(reference: CslItem, tokens: SearchToken[]): SearchResult | null;
13
+ /**
14
+ * Search references against search tokens
15
+ * Returns array of SearchResult for all matching references
16
+ */
17
+ export declare function search(references: CslItem[], tokens: SearchToken[]): SearchResult[];
18
+ //# sourceMappingURL=matcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matcher.d.ts","sourceRoot":"","sources":["../../../src/features/search/matcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAE5D,OAAO,KAAK,EAAE,UAAU,EAAiB,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAuRvF;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,GAAG,UAAU,EAAE,CAQ/E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,YAAY,GAAG,IAAI,CA4C7F;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,UAAU,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,YAAY,EAAE,CAWnF"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Normalize text for search matching
3
+ *
4
+ * Applies the following transformations:
5
+ * 1. Unicode NFKC normalization
6
+ * 2. Lowercase conversion
7
+ * 3. Remove diacritics (accents)
8
+ * 4. Punctuation removal
9
+ * 5. Whitespace normalization
10
+ */
11
+ export declare function normalize(text: string): string;
12
+ //# sourceMappingURL=normalizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizer.d.ts","sourceRoot":"","sources":["../../../src/features/search/normalizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAsB9C"}
@@ -0,0 +1,11 @@
1
+ import type { SearchResult } from "./types.js";
2
+ /**
3
+ * Sort search results according to the specification:
4
+ * 1. Match strength (exact > partial)
5
+ * 2. Year (descending)
6
+ * 3. Author (alphabetical)
7
+ * 4. Title (alphabetical)
8
+ * 5. Registration order (original array order)
9
+ */
10
+ export declare function sortResults(results: SearchResult[]): SearchResult[];
11
+ //# sourceMappingURL=sorter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sorter.d.ts","sourceRoot":"","sources":["../../../src/features/search/sorter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAiB,YAAY,EAAE,MAAM,YAAY,CAAC;AA6E9D;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,YAAY,EAAE,CA4BnE"}
@@ -0,0 +1,6 @@
1
+ import type { SearchQuery } from "./types.js";
2
+ /**
3
+ * Tokenize a search query string
4
+ */
5
+ export declare function tokenize(query: string): SearchQuery;
6
+ //# sourceMappingURL=tokenizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenizer.d.ts","sourceRoot":"","sources":["../../../src/features/search/tokenizer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,WAAW,EAAe,MAAM,YAAY,CAAC;AA2B3E;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAuBnD"}