@ncukondo/reference-manager 0.5.3 → 0.6.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/README.md +57 -0
- package/dist/chunks/{file-watcher-CBAbblss.js → file-watcher-Cwfnnw92.js} +42 -10
- package/dist/chunks/file-watcher-Cwfnnw92.js.map +1 -0
- package/dist/chunks/{index-Bl_mOQRe.js → index-CQO8hLYm.js} +263 -132
- package/dist/chunks/index-CQO8hLYm.js.map +1 -0
- package/dist/chunks/{loader-DuzyKV70.js → loader-B_ZLxCQW.js} +97 -26
- package/dist/chunks/loader-B_ZLxCQW.js.map +1 -0
- package/dist/cli/commands/list.d.ts +7 -1
- package/dist/cli/commands/list.d.ts.map +1 -1
- package/dist/cli/commands/search.d.ts +7 -1
- package/dist/cli/commands/search.d.ts.map +1 -1
- package/dist/cli/completion.d.ts +65 -0
- package/dist/cli/completion.d.ts.map +1 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli.js +480 -118
- package/dist/cli.js.map +1 -1
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/schema.d.ts +74 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/features/operations/list.d.ts +12 -3
- package/dist/features/operations/list.d.ts.map +1 -1
- package/dist/features/operations/search.d.ts +19 -3
- package/dist/features/operations/search.d.ts.map +1 -1
- package/dist/features/pagination/aliases.d.ts +14 -0
- package/dist/features/pagination/aliases.d.ts.map +1 -0
- package/dist/features/pagination/index.d.ts +8 -0
- package/dist/features/pagination/index.d.ts.map +1 -0
- package/dist/features/pagination/paginate.d.ts +20 -0
- package/dist/features/pagination/paginate.d.ts.map +1 -0
- package/dist/features/pagination/sorter.d.ts +16 -0
- package/dist/features/pagination/sorter.d.ts.map +1 -0
- package/dist/features/pagination/types.d.ts +74 -0
- package/dist/features/pagination/types.d.ts.map +1 -0
- package/dist/index.js +13 -12
- package/dist/index.js.map +1 -1
- package/dist/mcp/context.d.ts +4 -4
- package/dist/mcp/context.d.ts.map +1 -1
- package/dist/mcp/resources/index.d.ts +3 -3
- package/dist/mcp/resources/index.d.ts.map +1 -1
- package/dist/mcp/resources/library.d.ts +5 -5
- package/dist/mcp/resources/library.d.ts.map +1 -1
- package/dist/mcp/tools/add.d.ts +3 -3
- package/dist/mcp/tools/add.d.ts.map +1 -1
- package/dist/mcp/tools/cite.d.ts +3 -3
- package/dist/mcp/tools/cite.d.ts.map +1 -1
- package/dist/mcp/tools/fulltext.d.ts +7 -7
- package/dist/mcp/tools/fulltext.d.ts.map +1 -1
- package/dist/mcp/tools/index.d.ts +3 -3
- package/dist/mcp/tools/index.d.ts.map +1 -1
- package/dist/mcp/tools/list.d.ts +10 -3
- package/dist/mcp/tools/list.d.ts.map +1 -1
- package/dist/mcp/tools/remove.d.ts +3 -3
- package/dist/mcp/tools/remove.d.ts.map +1 -1
- package/dist/mcp/tools/search.d.ts +10 -3
- package/dist/mcp/tools/search.d.ts.map +1 -1
- package/dist/server/routes/list.d.ts +13 -0
- package/dist/server/routes/list.d.ts.map +1 -1
- package/dist/server/routes/search.d.ts +14 -0
- package/dist/server/routes/search.d.ts.map +1 -1
- package/dist/server.js +4 -4
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/object.d.ts +16 -0
- package/dist/utils/object.d.ts.map +1 -0
- package/package.json +3 -1
- package/dist/chunks/file-watcher-CBAbblss.js.map +0 -1
- package/dist/chunks/index-Bl_mOQRe.js.map +0 -1
- package/dist/chunks/loader-DuzyKV70.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAEjD;AAED;;;GAGG;AACH,wBAAgB,kCAAkC,IAAI,MAAM,CAE3D;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,IAAI,MAAM,CAEpD;AAED;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAEjD;AAED;;;GAGG;AACH,wBAAgB,kCAAkC,IAAI,MAAM,CAE3D;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,IAAI,MAAM,CAEpD;AAED;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,MAuC3B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAWH,OAAO,EACL,KAAK,MAAM,EAMZ,MAAM,aAAa,CAAC;AAErB;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,yDAAyD;IACzD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;CAC7B;
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAWH,OAAO,EACL,KAAK,MAAM,EAMZ,MAAM,aAAa,CAAC;AAErB;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,yDAAyD;IACzD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;CAC7B;AAwLD;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,OAAO,GAAE,iBAAsB,GAAG,MAAM,CAwClE"}
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -10,6 +10,29 @@ export declare const logLevelSchema: z.ZodEnum<{
|
|
|
10
10
|
info: "info";
|
|
11
11
|
debug: "debug";
|
|
12
12
|
}>;
|
|
13
|
+
/**
|
|
14
|
+
* CLI configuration schema
|
|
15
|
+
*/
|
|
16
|
+
export declare const cliConfigSchema: z.ZodObject<{
|
|
17
|
+
defaultLimit: z.ZodNumber;
|
|
18
|
+
defaultSort: z.ZodEnum<{
|
|
19
|
+
title: "title";
|
|
20
|
+
author: "author";
|
|
21
|
+
updated: "updated";
|
|
22
|
+
created: "created";
|
|
23
|
+
published: "published";
|
|
24
|
+
}>;
|
|
25
|
+
defaultOrder: z.ZodEnum<{
|
|
26
|
+
asc: "asc";
|
|
27
|
+
desc: "desc";
|
|
28
|
+
}>;
|
|
29
|
+
}, z.core.$strip>;
|
|
30
|
+
/**
|
|
31
|
+
* MCP configuration schema
|
|
32
|
+
*/
|
|
33
|
+
export declare const mcpConfigSchema: z.ZodObject<{
|
|
34
|
+
defaultLimit: z.ZodNumber;
|
|
35
|
+
}, z.core.$strip>;
|
|
13
36
|
/**
|
|
14
37
|
* Backup configuration schema
|
|
15
38
|
*/
|
|
@@ -112,6 +135,23 @@ export declare const configSchema: z.ZodObject<{
|
|
|
112
135
|
fulltext: z.ZodObject<{
|
|
113
136
|
directory: z.ZodString;
|
|
114
137
|
}, z.core.$strip>;
|
|
138
|
+
cli: z.ZodObject<{
|
|
139
|
+
defaultLimit: z.ZodNumber;
|
|
140
|
+
defaultSort: z.ZodEnum<{
|
|
141
|
+
title: "title";
|
|
142
|
+
author: "author";
|
|
143
|
+
updated: "updated";
|
|
144
|
+
created: "created";
|
|
145
|
+
published: "published";
|
|
146
|
+
}>;
|
|
147
|
+
defaultOrder: z.ZodEnum<{
|
|
148
|
+
asc: "asc";
|
|
149
|
+
desc: "desc";
|
|
150
|
+
}>;
|
|
151
|
+
}, z.core.$strip>;
|
|
152
|
+
mcp: z.ZodObject<{
|
|
153
|
+
defaultLimit: z.ZodNumber;
|
|
154
|
+
}, z.core.$strip>;
|
|
115
155
|
}, z.core.$strip>;
|
|
116
156
|
/**
|
|
117
157
|
* Partial configuration schema (for TOML files)
|
|
@@ -178,6 +218,36 @@ export declare const partialConfigSchema: z.ZodObject<{
|
|
|
178
218
|
fulltext: z.ZodOptional<z.ZodObject<{
|
|
179
219
|
directory: z.ZodOptional<z.ZodString>;
|
|
180
220
|
}, z.core.$strip>>;
|
|
221
|
+
cli: z.ZodOptional<z.ZodObject<{
|
|
222
|
+
defaultLimit: z.ZodOptional<z.ZodNumber>;
|
|
223
|
+
default_limit: z.ZodOptional<z.ZodNumber>;
|
|
224
|
+
defaultSort: z.ZodOptional<z.ZodEnum<{
|
|
225
|
+
title: "title";
|
|
226
|
+
author: "author";
|
|
227
|
+
updated: "updated";
|
|
228
|
+
created: "created";
|
|
229
|
+
published: "published";
|
|
230
|
+
}>>;
|
|
231
|
+
default_sort: z.ZodOptional<z.ZodEnum<{
|
|
232
|
+
title: "title";
|
|
233
|
+
author: "author";
|
|
234
|
+
updated: "updated";
|
|
235
|
+
created: "created";
|
|
236
|
+
published: "published";
|
|
237
|
+
}>>;
|
|
238
|
+
defaultOrder: z.ZodOptional<z.ZodEnum<{
|
|
239
|
+
asc: "asc";
|
|
240
|
+
desc: "desc";
|
|
241
|
+
}>>;
|
|
242
|
+
default_order: z.ZodOptional<z.ZodEnum<{
|
|
243
|
+
asc: "asc";
|
|
244
|
+
desc: "desc";
|
|
245
|
+
}>>;
|
|
246
|
+
}, z.core.$strip>>;
|
|
247
|
+
mcp: z.ZodOptional<z.ZodObject<{
|
|
248
|
+
defaultLimit: z.ZodOptional<z.ZodNumber>;
|
|
249
|
+
default_limit: z.ZodOptional<z.ZodNumber>;
|
|
250
|
+
}, z.core.$strip>>;
|
|
181
251
|
}, z.core.$loose>;
|
|
182
252
|
/**
|
|
183
253
|
* Inferred types from schemas
|
|
@@ -190,6 +260,8 @@ export type CitationFormat = z.infer<typeof citationFormatSchema>;
|
|
|
190
260
|
export type CitationConfig = z.infer<typeof citationConfigSchema>;
|
|
191
261
|
export type PubmedConfig = z.infer<typeof pubmedConfigSchema>;
|
|
192
262
|
export type FulltextConfig = z.infer<typeof fulltextConfigSchema>;
|
|
263
|
+
export type CliConfig = z.infer<typeof cliConfigSchema>;
|
|
264
|
+
export type McpConfig = z.infer<typeof mcpConfigSchema>;
|
|
193
265
|
export type Config = z.infer<typeof configSchema>;
|
|
194
266
|
export type PartialConfig = z.infer<typeof partialConfigSchema>;
|
|
195
267
|
/**
|
|
@@ -204,6 +276,8 @@ export type DeepPartialConfig = {
|
|
|
204
276
|
citation?: Partial<CitationConfig>;
|
|
205
277
|
pubmed?: Partial<PubmedConfig>;
|
|
206
278
|
fulltext?: Partial<FulltextConfig>;
|
|
279
|
+
cli?: Partial<CliConfig>;
|
|
280
|
+
mcp?: Partial<McpConfig>;
|
|
207
281
|
};
|
|
208
282
|
/**
|
|
209
283
|
* Normalize snake_case fields to camelCase
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ILibrary } from "../../core/library-interface.js";
|
|
2
|
+
import { type PaginationOptions, type SortOptions } from "../pagination/index.js";
|
|
2
3
|
/**
|
|
3
4
|
* Output format options for list operation
|
|
4
5
|
*/
|
|
@@ -6,7 +7,7 @@ export type ListFormat = "pretty" | "json" | "bibtex" | "ids-only" | "uuid";
|
|
|
6
7
|
/**
|
|
7
8
|
* Options for listReferences operation
|
|
8
9
|
*/
|
|
9
|
-
export interface ListOptions {
|
|
10
|
+
export interface ListOptions extends PaginationOptions, SortOptions {
|
|
10
11
|
/** Output format (default: "pretty") */
|
|
11
12
|
format?: ListFormat;
|
|
12
13
|
}
|
|
@@ -16,13 +17,21 @@ export interface ListOptions {
|
|
|
16
17
|
export interface ListResult {
|
|
17
18
|
/** Formatted strings for each reference */
|
|
18
19
|
items: string[];
|
|
20
|
+
/** Total count before pagination */
|
|
21
|
+
total: number;
|
|
22
|
+
/** Applied limit (0 if unlimited) */
|
|
23
|
+
limit: number;
|
|
24
|
+
/** Applied offset */
|
|
25
|
+
offset: number;
|
|
26
|
+
/** Next page offset, null if no more results */
|
|
27
|
+
nextOffset: number | null;
|
|
19
28
|
}
|
|
20
29
|
/**
|
|
21
30
|
* List all references from the library with specified format.
|
|
22
31
|
*
|
|
23
32
|
* @param library - The library to list references from
|
|
24
|
-
* @param options - Formatting options
|
|
25
|
-
* @returns Formatted strings for each reference
|
|
33
|
+
* @param options - Formatting and pagination options
|
|
34
|
+
* @returns Formatted strings for each reference with pagination metadata
|
|
26
35
|
*/
|
|
27
36
|
export declare function listReferences(library: ILibrary, options: ListOptions): Promise<ListResult>;
|
|
28
37
|
//# sourceMappingURL=list.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/features/operations/list.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/features/operations/list.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAEhE,OAAO,EACL,KAAK,iBAAiB,EAEtB,KAAK,WAAW,EAIjB,MAAM,wBAAwB,CAAC;AAEhC;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAC;AAE5E;;GAEG;AACH,MAAM,WAAW,WAAY,SAAQ,iBAAiB,EAAE,WAAW;IACjE,wCAAwC;IACxC,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AA4BD;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CA2BjG"}
|
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
import type { ILibrary } from "../../core/library-interface.js";
|
|
2
|
+
import { type PaginationOptions, type SearchSortField, type SortOrder } from "../pagination/index.js";
|
|
2
3
|
/**
|
|
3
4
|
* Output format options for search operation
|
|
4
5
|
*/
|
|
5
6
|
export type SearchFormat = "pretty" | "json" | "bibtex" | "ids-only" | "uuid";
|
|
7
|
+
/**
|
|
8
|
+
* Sort options for search (includes relevance)
|
|
9
|
+
*/
|
|
10
|
+
export interface SearchSortOptions {
|
|
11
|
+
sort?: SearchSortField;
|
|
12
|
+
order?: SortOrder;
|
|
13
|
+
}
|
|
6
14
|
/**
|
|
7
15
|
* Options for searchReferences operation
|
|
8
16
|
*/
|
|
9
|
-
export interface SearchOperationOptions {
|
|
17
|
+
export interface SearchOperationOptions extends PaginationOptions, SearchSortOptions {
|
|
10
18
|
/** Search query string */
|
|
11
19
|
query: string;
|
|
12
20
|
/** Output format (default: "pretty") */
|
|
@@ -18,13 +26,21 @@ export interface SearchOperationOptions {
|
|
|
18
26
|
export interface SearchResult {
|
|
19
27
|
/** Formatted strings for each matching reference */
|
|
20
28
|
items: string[];
|
|
29
|
+
/** Total count before pagination */
|
|
30
|
+
total: number;
|
|
31
|
+
/** Applied limit (0 if unlimited) */
|
|
32
|
+
limit: number;
|
|
33
|
+
/** Applied offset */
|
|
34
|
+
offset: number;
|
|
35
|
+
/** Next page offset, null if no more results */
|
|
36
|
+
nextOffset: number | null;
|
|
21
37
|
}
|
|
22
38
|
/**
|
|
23
39
|
* Search references in the library and return formatted results.
|
|
24
40
|
*
|
|
25
41
|
* @param library - The library to search in
|
|
26
|
-
* @param options - Search query and
|
|
27
|
-
* @returns Formatted strings for each matching reference
|
|
42
|
+
* @param options - Search query, formatting, and pagination options
|
|
43
|
+
* @returns Formatted strings for each matching reference with pagination metadata
|
|
28
44
|
*/
|
|
29
45
|
export declare function searchReferences(library: ILibrary, options: SearchOperationOptions): Promise<SearchResult>;
|
|
30
46
|
//# sourceMappingURL=search.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/features/operations/search.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/features/operations/search.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAEhE,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,eAAe,EAEpB,KAAK,SAAS,EAGf,MAAM,wBAAwB,CAAC;AAKhC;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAC;AAE9E;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAuB,SAAQ,iBAAiB,EAAE,iBAAiB;IAClF,0BAA0B;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,oDAAoD;IACpD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AA4BD;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,QAAQ,EACjB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,YAAY,CAAC,CAuDvB"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sort field alias resolver
|
|
3
|
+
*/
|
|
4
|
+
import type { SearchSortField } from "./types.js";
|
|
5
|
+
/**
|
|
6
|
+
* Resolves a sort field alias to its full name.
|
|
7
|
+
* Passes through valid sort fields unchanged.
|
|
8
|
+
*
|
|
9
|
+
* @param alias - The alias or sort field name
|
|
10
|
+
* @returns The resolved sort field
|
|
11
|
+
* @throws Error if the alias is unknown
|
|
12
|
+
*/
|
|
13
|
+
export declare function resolveSortAlias(alias: string): SearchSortField;
|
|
14
|
+
//# sourceMappingURL=aliases.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aliases.d.ts","sourceRoot":"","sources":["../../../src/features/pagination/aliases.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAkBlD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAW/D"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pagination feature exports
|
|
3
|
+
*/
|
|
4
|
+
export * from "./types.js";
|
|
5
|
+
export { resolveSortAlias } from "./aliases.js";
|
|
6
|
+
export { sortReferences } from "./sorter.js";
|
|
7
|
+
export { paginate, type PaginateOptions, type PaginateResult } from "./paginate.js";
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/features/pagination/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pagination applier
|
|
3
|
+
*/
|
|
4
|
+
export interface PaginateOptions {
|
|
5
|
+
limit?: number;
|
|
6
|
+
offset?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface PaginateResult<T> {
|
|
9
|
+
items: T[];
|
|
10
|
+
nextOffset: number | null;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Apply pagination to an array of items.
|
|
14
|
+
*
|
|
15
|
+
* @param items - Items to paginate
|
|
16
|
+
* @param options - Pagination options (limit=0 or undefined means unlimited)
|
|
17
|
+
* @returns Paginated items with nextOffset (null if no more items)
|
|
18
|
+
*/
|
|
19
|
+
export declare function paginate<T>(items: T[], options: PaginateOptions): PaginateResult<T>;
|
|
20
|
+
//# sourceMappingURL=paginate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paginate.d.ts","sourceRoot":"","sources":["../../../src/features/pagination/paginate.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,eAAe,GAAG,cAAc,CAAC,CAAC,CAAC,CAiCnF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reference sorter
|
|
3
|
+
*/
|
|
4
|
+
import type { CslItem } from "../../core/csl-json/types.js";
|
|
5
|
+
import type { SortField, SortOrder } from "./types.js";
|
|
6
|
+
/**
|
|
7
|
+
* Sort references by the specified field and order.
|
|
8
|
+
* Uses secondary sort: created (desc), then id (asc) for stability.
|
|
9
|
+
*
|
|
10
|
+
* @param items - References to sort
|
|
11
|
+
* @param sort - Sort field
|
|
12
|
+
* @param order - Sort order
|
|
13
|
+
* @returns Sorted references (new array, does not mutate input)
|
|
14
|
+
*/
|
|
15
|
+
export declare function sortReferences(items: CslItem[], sort: SortField, order: SortOrder): CslItem[];
|
|
16
|
+
//# sourceMappingURL=sorter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sorter.d.ts","sourceRoot":"","sources":["../../../src/features/pagination/sorter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAsFvD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,EAAE,CAmB7F"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pagination and sorting type definitions
|
|
3
|
+
*/
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
/**
|
|
6
|
+
* Sort field for list/search commands
|
|
7
|
+
*/
|
|
8
|
+
export declare const sortFieldSchema: z.ZodEnum<{
|
|
9
|
+
title: "title";
|
|
10
|
+
author: "author";
|
|
11
|
+
updated: "updated";
|
|
12
|
+
created: "created";
|
|
13
|
+
published: "published";
|
|
14
|
+
}>;
|
|
15
|
+
export type SortField = z.infer<typeof sortFieldSchema>;
|
|
16
|
+
/**
|
|
17
|
+
* Sort field for search command (includes relevance)
|
|
18
|
+
*/
|
|
19
|
+
export declare const searchSortFieldSchema: z.ZodEnum<{
|
|
20
|
+
title: "title";
|
|
21
|
+
author: "author";
|
|
22
|
+
updated: "updated";
|
|
23
|
+
created: "created";
|
|
24
|
+
published: "published";
|
|
25
|
+
relevance: "relevance";
|
|
26
|
+
}>;
|
|
27
|
+
export type SearchSortField = z.infer<typeof searchSortFieldSchema>;
|
|
28
|
+
/**
|
|
29
|
+
* Sort order
|
|
30
|
+
*/
|
|
31
|
+
export declare const sortOrderSchema: z.ZodEnum<{
|
|
32
|
+
asc: "asc";
|
|
33
|
+
desc: "desc";
|
|
34
|
+
}>;
|
|
35
|
+
export type SortOrder = z.infer<typeof sortOrderSchema>;
|
|
36
|
+
/**
|
|
37
|
+
* Pagination options
|
|
38
|
+
*/
|
|
39
|
+
export declare const paginationOptionsSchema: z.ZodObject<{
|
|
40
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
41
|
+
offset: z.ZodOptional<z.ZodNumber>;
|
|
42
|
+
}, z.core.$strip>;
|
|
43
|
+
export type PaginationOptions = z.infer<typeof paginationOptionsSchema>;
|
|
44
|
+
/**
|
|
45
|
+
* Sort options
|
|
46
|
+
*/
|
|
47
|
+
export declare const sortOptionsSchema: z.ZodObject<{
|
|
48
|
+
sort: z.ZodOptional<z.ZodEnum<{
|
|
49
|
+
title: "title";
|
|
50
|
+
author: "author";
|
|
51
|
+
updated: "updated";
|
|
52
|
+
created: "created";
|
|
53
|
+
published: "published";
|
|
54
|
+
}>>;
|
|
55
|
+
order: z.ZodOptional<z.ZodEnum<{
|
|
56
|
+
asc: "asc";
|
|
57
|
+
desc: "desc";
|
|
58
|
+
}>>;
|
|
59
|
+
}, z.core.$strip>;
|
|
60
|
+
export type SortOptions<T extends string = SortField> = {
|
|
61
|
+
sort?: T;
|
|
62
|
+
order?: SortOrder;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Paginated result
|
|
66
|
+
*/
|
|
67
|
+
export interface PaginatedResult<T> {
|
|
68
|
+
items: T[];
|
|
69
|
+
total: number;
|
|
70
|
+
limit: number;
|
|
71
|
+
offset: number;
|
|
72
|
+
nextOffset: number | null;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/features/pagination/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,eAAO,MAAM,eAAe;;;;;;EAAiE,CAAC;AAC9F,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;;;;;EAOhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;GAEG;AACH,eAAO,MAAM,eAAe;;;EAA0B,CAAC;AACvD,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;iBAGlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;iBAG5B,CAAC;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,MAAM,GAAG,SAAS,IAAI;IACtD,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B"}
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { C as CslLibrarySchema, c as computeFileHash, a as computeHash, n as normalize, s as search, b as sortResults, t as tokenize, d as detectDuplicate } from "./chunks/file-watcher-
|
|
2
|
-
import { e, F, L, R,
|
|
1
|
+
import { C as CslLibrarySchema, c as computeFileHash, a as computeHash, p as pickDefined, n as normalize, s as search, b as sortResults, t as tokenize, d as detectDuplicate } from "./chunks/file-watcher-Cwfnnw92.js";
|
|
2
|
+
import { e, F, L, R, m, o, h, i, k, l, j, f, g, w } from "./chunks/file-watcher-Cwfnnw92.js";
|
|
3
3
|
import { mkdir, readFile, copyFile, stat, unlink, readdir } from "node:fs/promises";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
import writeFileAtomicLib from "write-file-atomic";
|
|
6
6
|
import { existsSync } from "node:fs";
|
|
7
7
|
import { tmpdir } from "node:os";
|
|
8
8
|
import { fileURLToPath } from "node:url";
|
|
9
|
-
import { b as backupConfigSchema, c as configSchema, d as defaultConfig, g as getDefaultBackupDirectory, a as getDefaultCurrentDirConfigFilename, e as getDefaultLibraryPath, f as getDefaultUserConfigPath, l as loadConfig, h as logLevelSchema, n as normalizePartialConfig, p as partialConfigSchema, w as watchConfigSchema } from "./chunks/loader-
|
|
9
|
+
import { b as backupConfigSchema, c as configSchema, d as defaultConfig, g as getDefaultBackupDirectory, a as getDefaultCurrentDirConfigFilename, e as getDefaultLibraryPath, f as getDefaultUserConfigPath, l as loadConfig, h as logLevelSchema, n as normalizePartialConfig, p as partialConfigSchema, w as watchConfigSchema } from "./chunks/loader-B_ZLxCQW.js";
|
|
10
10
|
function validateCslJson(data) {
|
|
11
11
|
const parseResult = CslLibrarySchema.safeParse(data);
|
|
12
12
|
if (!parseResult.success) {
|
|
@@ -120,6 +120,7 @@ const index$4 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
120
120
|
ensureDirectoryExists,
|
|
121
121
|
getBackupDirectory,
|
|
122
122
|
listBackups,
|
|
123
|
+
pickDefined,
|
|
123
124
|
writeFileAtomic
|
|
124
125
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
125
126
|
const index$3 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
@@ -378,15 +379,15 @@ export {
|
|
|
378
379
|
R as Reference,
|
|
379
380
|
index$2 as Search,
|
|
380
381
|
index$4 as Utils,
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
382
|
+
m as ensureCustomMetadata,
|
|
383
|
+
o as extractUuidFromCustom,
|
|
384
|
+
h as generateId,
|
|
385
|
+
i as generateIdWithCollisionCheck,
|
|
386
|
+
k as generateUuid,
|
|
387
|
+
l as isValidUuid,
|
|
388
|
+
j as normalizeText,
|
|
389
|
+
f as parseCslJson,
|
|
390
|
+
g as serializeCslJson,
|
|
390
391
|
validateCslJson,
|
|
391
392
|
w as writeCslJson
|
|
392
393
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/core/csl-json/validator.ts","../src/utils/logger.ts","../src/utils/file.ts","../src/utils/backup.ts","../src/features/merge/three-way.ts"],"sourcesContent":["import { CslItemSchema, CslLibrarySchema } from \"./types\";\nimport type { CslItem, CslLibrary } from \"./types\";\n\n/**\n * Validate CSL-JSON library structure\n * @param data - Data to validate (can be any type)\n * @returns Validated CSL-JSON library\n * @throws Error if validation fails\n */\nexport function validateCslJson(data: unknown): CslLibrary {\n const parseResult = CslLibrarySchema.safeParse(data);\n\n if (!parseResult.success) {\n throw new Error(`Invalid CSL-JSON structure: ${parseResult.error.message}`);\n }\n\n return parseResult.data;\n}\n\n/**\n * Validate a single CSL-JSON item\n * @param data - Data to validate (can be any type)\n * @returns Validation result with valid flag and errors\n */\nexport function validateCslItem(data: unknown): {\n valid: boolean;\n data?: CslItem;\n errors?: string[];\n} {\n const parseResult = CslItemSchema.safeParse(data);\n\n if (!parseResult.success) {\n return {\n valid: false,\n errors: parseResult.error.issues.map((issue) => issue.message),\n };\n }\n\n return {\n valid: true,\n data: parseResult.data,\n };\n}\n","export type LogLevel = \"silent\" | \"info\" | \"debug\";\n\nexport interface Logger {\n info(...args: unknown[]): void;\n debug(...args: unknown[]): void;\n error(...args: unknown[]): void;\n}\n\nexport function createLogger(level: LogLevel = \"info\"): Logger {\n const shouldLogInfo = level === \"info\" || level === \"debug\";\n const shouldLogDebug = level === \"debug\";\n\n function formatMessage(...args: unknown[]): string {\n return `${args.map((arg) => String(arg)).join(\" \")}\\n`;\n }\n\n return {\n info(...args: unknown[]): void {\n if (shouldLogInfo) {\n process.stderr.write(formatMessage(...args));\n }\n },\n\n debug(...args: unknown[]): void {\n if (shouldLogDebug) {\n process.stderr.write(formatMessage(...args));\n }\n },\n\n error(...args: unknown[]): void {\n process.stderr.write(formatMessage(...args));\n },\n };\n}\n","import { mkdir } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport writeFileAtomicLib from \"write-file-atomic\";\n\n/**\n * Write file atomically with parent directory creation\n */\nexport async function writeFileAtomic(filePath: string, content: string): Promise<void> {\n await ensureDirectoryExists(dirname(filePath));\n await writeFileAtomicLib(filePath, content, { encoding: \"utf-8\" });\n}\n\n/**\n * Ensure directory exists, creating it recursively if necessary\n */\nexport async function ensureDirectoryExists(dirPath: string): Promise<void> {\n await mkdir(dirPath, { recursive: true });\n}\n","import { existsSync } from \"node:fs\";\nimport { copyFile, readFile, readdir, stat, unlink } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { ensureDirectoryExists } from \"./file\";\n\nexport interface BackupOptions {\n maxGenerations?: number;\n maxAgeMs?: number;\n}\n\nconst DEFAULT_MAX_GENERATIONS = 50;\nconst DEFAULT_MAX_AGE_MS = 365 * 24 * 60 * 60 * 1000; // 1 year\n\n/**\n * Get package name from package.json\n */\nasync function resolvePackageName(): Promise<string> {\n try {\n const currentFile = fileURLToPath(import.meta.url);\n let currentDir = dirname(currentFile);\n\n for (let i = 0; i < 10; i++) {\n const packageJsonPath = join(currentDir, \"package.json\");\n if (existsSync(packageJsonPath)) {\n const content = await readFile(packageJsonPath, \"utf-8\");\n const pkg = JSON.parse(content);\n return pkg.name;\n }\n currentDir = dirname(currentDir);\n }\n } catch {\n // Fall back to hardcoded name if package.json is not found\n }\n\n return \"reference-manager\";\n}\n\nconst packageName = await resolvePackageName();\n\n/**\n * Get backup directory path for a library\n */\nexport function getBackupDirectory(libraryName: string): string {\n const pkgName = packageName ?? \"reference-manager\";\n return join(tmpdir(), pkgName, \"backups\", libraryName);\n}\n\n/**\n * Create a backup of the given file\n */\nexport async function createBackup(sourceFile: string, libraryName: string): Promise<string> {\n const backupDir = getBackupDirectory(libraryName);\n await ensureDirectoryExists(backupDir);\n\n const timestamp = Date.now();\n const backupFileName = `${timestamp}.backup`;\n const backupPath = join(backupDir, backupFileName);\n\n await copyFile(sourceFile, backupPath);\n\n return backupPath;\n}\n\n/**\n * List all backups for a library (sorted by modification time, newest first)\n */\nexport async function listBackups(libraryName: string): Promise<string[]> {\n const backupDir = getBackupDirectory(libraryName);\n\n if (!existsSync(backupDir)) {\n return [];\n }\n\n const files = await readdir(backupDir);\n const backupFiles = files.filter((f) => f.endsWith(\".backup\")).map((f) => join(backupDir, f));\n\n const filesWithStats = await Promise.all(\n backupFiles.map(async (file) => {\n const stats = await stat(file);\n return { file, mtime: stats.mtimeMs };\n })\n );\n\n filesWithStats.sort((a, b) => b.mtime - a.mtime);\n\n return filesWithStats.map((f) => f.file);\n}\n\n/**\n * Clean up old backups based on generation count and age\n */\nexport async function cleanupOldBackups(\n libraryName: string,\n options?: BackupOptions\n): Promise<void> {\n const maxGenerations = options?.maxGenerations ?? DEFAULT_MAX_GENERATIONS;\n const maxAgeMs = options?.maxAgeMs ?? DEFAULT_MAX_AGE_MS;\n\n const backups = await listBackups(libraryName);\n const now = Date.now();\n\n const backupsToDelete: string[] = [];\n\n for (let i = 0; i < backups.length; i++) {\n const backupPath = backups[i];\n if (!backupPath) continue;\n\n const stats = await stat(backupPath);\n const age = now - stats.mtimeMs;\n\n if (i >= maxGenerations || age > maxAgeMs) {\n backupsToDelete.push(backupPath);\n }\n }\n\n await Promise.all(backupsToDelete.map((backup) => unlink(backup)));\n}\n","/**\n * 3-way merge implementation with Last-Write-Wins (LWW) strategy\n */\n\nimport type { CslItem } from \"../../core/csl-json/types.js\";\nimport type {\n FieldConflict,\n ItemConflict,\n MergeOptions,\n MergeResult,\n MergeStatus,\n} from \"./types.js\";\n\n/**\n * Get UUID from item, with fallback to id if uuid is missing\n */\nfunction getItemUuid(item: CslItem): string {\n return item.custom?.uuid || item.id || \"unknown\";\n}\n\n/**\n * Get timestamp from item, with fallback to created_at\n */\nfunction getTimestamp(item: CslItem): string {\n return item.custom?.timestamp || item.custom?.created_at || \"1970-01-01T00:00:00.000Z\";\n}\n\n/**\n * Deep equality check for field values\n */\nfunction deepEqual(a: unknown, b: unknown): boolean {\n return JSON.stringify(a) === JSON.stringify(b);\n}\n\n/**\n * Resolve a field conflict using LWW or prefer option\n */\nfunction resolveFieldConflict(\n localValue: unknown,\n remoteValue: unknown,\n localTimestamp: string,\n remoteTimestamp: string,\n options?: MergeOptions\n): unknown {\n if (localTimestamp > remoteTimestamp) {\n return localValue;\n }\n if (remoteTimestamp > localTimestamp) {\n return remoteValue;\n }\n // Timestamps equal: use prefer option or default to local\n if (options?.prefer === \"remote\") {\n return remoteValue;\n }\n return localValue;\n}\n\n/**\n * Determine conflict resolution type\n */\nfunction determineResolution(\n fieldConflicts: FieldConflict[],\n localTimestamp: string,\n remoteTimestamp: string,\n options?: MergeOptions\n): ItemConflict[\"resolution\"] {\n const hasRealConflicts = fieldConflicts.every((fc) => fc.resolved !== undefined);\n const localIsNewer = fieldConflicts.some(\n (fc) => fc.local !== fc.remote && localTimestamp > remoteTimestamp\n );\n const remoteIsNewer = fieldConflicts.some(\n (fc) => fc.local !== fc.remote && remoteTimestamp > localTimestamp\n );\n\n if (hasRealConflicts && localIsNewer) return \"auto-lww\";\n if (hasRealConflicts && remoteIsNewer) return \"auto-lww\";\n if (options?.prefer === \"local\") return \"prefer-local\";\n if (options?.prefer === \"remote\") return \"prefer-remote\";\n return \"unresolved\";\n}\n\n/**\n * Merge a single field from base, local, and remote versions\n */\nfunction mergeField(\n key: string,\n baseValue: unknown,\n localValue: unknown,\n remoteValue: unknown,\n localTimestamp: string,\n remoteTimestamp: string,\n options?: MergeOptions\n): { value: unknown; conflict: FieldConflict | null } {\n const localChanged = !deepEqual(baseValue, localValue);\n const remoteChanged = !deepEqual(baseValue, remoteValue);\n\n if (!localChanged && !remoteChanged) {\n return { value: baseValue, conflict: null };\n }\n\n if (localChanged && !remoteChanged) {\n return { value: localValue, conflict: null };\n }\n\n if (!localChanged && remoteChanged) {\n return { value: remoteValue, conflict: null };\n }\n\n // Both changed\n if (deepEqual(localValue, remoteValue)) {\n return { value: localValue, conflict: null };\n }\n\n // Both changed to different values\n const resolved = resolveFieldConflict(\n localValue,\n remoteValue,\n localTimestamp,\n remoteTimestamp,\n options\n );\n\n // Don't record conflicts for 'custom' metadata field\n if (key === \"custom\") {\n return { value: resolved, conflict: null };\n }\n\n return {\n value: resolved,\n conflict: {\n field: key,\n base: baseValue,\n local: localValue,\n remote: remoteValue,\n resolved,\n },\n };\n}\n\n/**\n * Merge a single item from base, local, and remote versions\n */\nfunction mergeItem(\n base: CslItem,\n local: CslItem,\n remote: CslItem,\n options?: MergeOptions\n): { merged: CslItem; conflict: ItemConflict | null } {\n const uuid = getItemUuid(base);\n const localTimestamp = getTimestamp(local);\n const remoteTimestamp = getTimestamp(remote);\n\n const merged: CslItem = { ...base };\n const fieldConflicts: FieldConflict[] = [];\n\n // Get all unique keys from all three versions\n const allKeys = new Set<string>([\n ...Object.keys(base),\n ...Object.keys(local),\n ...Object.keys(remote),\n ]);\n\n for (const key of allKeys) {\n const baseValue = (base as Record<string, unknown>)[key];\n const localValue = (local as Record<string, unknown>)[key];\n const remoteValue = (remote as Record<string, unknown>)[key];\n\n const { value, conflict } = mergeField(\n key,\n baseValue,\n localValue,\n remoteValue,\n localTimestamp,\n remoteTimestamp,\n options\n );\n\n (merged as Record<string, unknown>)[key] = value;\n\n if (conflict) {\n fieldConflicts.push(conflict);\n }\n }\n\n // If there are field conflicts, create ItemConflict\n if (fieldConflicts.length > 0) {\n const resolution = determineResolution(\n fieldConflicts,\n localTimestamp,\n remoteTimestamp,\n options\n );\n\n return {\n merged,\n conflict: {\n uuid,\n id: base.id || \"unknown\",\n fields: fieldConflicts,\n localTimestamp,\n remoteTimestamp,\n resolution,\n },\n };\n }\n\n return { merged, conflict: null };\n}\n\n/**\n * Build UUID-indexed maps from item arrays\n */\nfunction buildItemMaps(base: CslItem[], local: CslItem[], remote: CslItem[]) {\n const baseMap = new Map<string, CslItem>();\n const localMap = new Map<string, CslItem>();\n const remoteMap = new Map<string, CslItem>();\n\n for (const item of base) {\n baseMap.set(getItemUuid(item), item);\n }\n for (const item of local) {\n localMap.set(getItemUuid(item), item);\n }\n for (const item of remote) {\n remoteMap.set(getItemUuid(item), item);\n }\n\n return { baseMap, localMap, remoteMap };\n}\n\n/**\n * Handle items that exist in all three versions\n */\nfunction mergeExistingItem(\n baseItem: CslItem,\n localItem: CslItem,\n remoteItem: CslItem,\n options: MergeOptions | undefined,\n merged: CslItem[],\n conflicts: ItemConflict[]\n): void {\n const { merged: mergedItem, conflict } = mergeItem(baseItem, localItem, remoteItem, options);\n merged.push(mergedItem);\n if (conflict) {\n conflicts.push(conflict);\n }\n}\n\n/**\n * Handle items added in both local and remote\n */\nfunction handleDualAddition(\n uuid: string,\n localItem: CslItem,\n remoteItem: CslItem,\n options: MergeOptions | undefined,\n merged: CslItem[],\n conflicts: ItemConflict[]\n): void {\n if (deepEqual(localItem, remoteItem)) {\n merged.push(localItem);\n } else {\n const syntheticBase: CslItem = {\n id: uuid,\n type: \"article\",\n custom: {\n uuid,\n created_at: \"1970-01-01T00:00:00.000Z\",\n timestamp: \"1970-01-01T00:00:00.000Z\",\n },\n };\n const { merged: mergedItem, conflict } = mergeItem(\n syntheticBase,\n localItem,\n remoteItem,\n options\n );\n merged.push(mergedItem);\n if (conflict) {\n conflicts.push(conflict);\n }\n }\n}\n\n/**\n * Process a single UUID across all three versions\n */\nfunction processItem(\n uuid: string,\n baseMap: Map<string, CslItem>,\n localMap: Map<string, CslItem>,\n remoteMap: Map<string, CslItem>,\n options: MergeOptions | undefined,\n result: {\n merged: CslItem[];\n conflicts: ItemConflict[];\n localOnly: CslItem[];\n remoteOnly: CslItem[];\n deletedInLocal: CslItem[];\n deletedInRemote: CslItem[];\n }\n): void {\n const baseItem = baseMap.get(uuid);\n const localItem = localMap.get(uuid);\n const remoteItem = remoteMap.get(uuid);\n\n if (baseItem && localItem && remoteItem) {\n mergeExistingItem(baseItem, localItem, remoteItem, options, result.merged, result.conflicts);\n } else if (!baseItem && localItem && remoteItem) {\n handleDualAddition(uuid, localItem, remoteItem, options, result.merged, result.conflicts);\n } else if (!baseItem && localItem && !remoteItem) {\n result.merged.push(localItem);\n result.localOnly.push(localItem);\n } else if (!baseItem && !localItem && remoteItem) {\n result.merged.push(remoteItem);\n result.remoteOnly.push(remoteItem);\n } else if (baseItem && !localItem && remoteItem) {\n result.deletedInLocal.push(baseItem);\n } else if (baseItem && localItem && !remoteItem) {\n result.deletedInRemote.push(baseItem);\n } else if (baseItem && !localItem && !remoteItem) {\n result.deletedInLocal.push(baseItem);\n result.deletedInRemote.push(baseItem);\n }\n}\n\n/**\n * Performs a 3-way merge of CSL-JSON items\n *\n * @param base - Base version (common ancestor)\n * @param local - Local version (current working copy)\n * @param remote - Remote version (incoming changes)\n * @param options - Merge options (e.g., prefer local/remote for tie-breaking)\n * @returns Merge result with merged items and conflict information\n */\nexport function threeWayMerge(\n base: CslItem[],\n local: CslItem[],\n remote: CslItem[],\n options?: MergeOptions\n): MergeResult {\n const { baseMap, localMap, remoteMap } = buildItemMaps(base, local, remote);\n\n const result = {\n merged: [] as CslItem[],\n conflicts: [] as ItemConflict[],\n localOnly: [] as CslItem[],\n remoteOnly: [] as CslItem[],\n deletedInLocal: [] as CslItem[],\n deletedInRemote: [] as CslItem[],\n };\n\n const allUuids = new Set<string>([...baseMap.keys(), ...localMap.keys(), ...remoteMap.keys()]);\n\n for (const uuid of allUuids) {\n processItem(uuid, baseMap, localMap, remoteMap, options, result);\n }\n\n // Determine overall status\n let status: MergeStatus = \"success\";\n if (result.conflicts.length > 0) {\n const hasUnresolved = result.conflicts.some((c) => c.resolution === \"unresolved\");\n status = hasUnresolved ? \"conflict\" : \"auto-resolved\";\n }\n\n return {\n status,\n ...result,\n };\n}\n"],"names":["i","f"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/core/csl-json/validator.ts","../src/utils/logger.ts","../src/utils/file.ts","../src/utils/backup.ts","../src/features/merge/three-way.ts"],"sourcesContent":["import { CslItemSchema, CslLibrarySchema } from \"./types\";\nimport type { CslItem, CslLibrary } from \"./types\";\n\n/**\n * Validate CSL-JSON library structure\n * @param data - Data to validate (can be any type)\n * @returns Validated CSL-JSON library\n * @throws Error if validation fails\n */\nexport function validateCslJson(data: unknown): CslLibrary {\n const parseResult = CslLibrarySchema.safeParse(data);\n\n if (!parseResult.success) {\n throw new Error(`Invalid CSL-JSON structure: ${parseResult.error.message}`);\n }\n\n return parseResult.data;\n}\n\n/**\n * Validate a single CSL-JSON item\n * @param data - Data to validate (can be any type)\n * @returns Validation result with valid flag and errors\n */\nexport function validateCslItem(data: unknown): {\n valid: boolean;\n data?: CslItem;\n errors?: string[];\n} {\n const parseResult = CslItemSchema.safeParse(data);\n\n if (!parseResult.success) {\n return {\n valid: false,\n errors: parseResult.error.issues.map((issue) => issue.message),\n };\n }\n\n return {\n valid: true,\n data: parseResult.data,\n };\n}\n","export type LogLevel = \"silent\" | \"info\" | \"debug\";\n\nexport interface Logger {\n info(...args: unknown[]): void;\n debug(...args: unknown[]): void;\n error(...args: unknown[]): void;\n}\n\nexport function createLogger(level: LogLevel = \"info\"): Logger {\n const shouldLogInfo = level === \"info\" || level === \"debug\";\n const shouldLogDebug = level === \"debug\";\n\n function formatMessage(...args: unknown[]): string {\n return `${args.map((arg) => String(arg)).join(\" \")}\\n`;\n }\n\n return {\n info(...args: unknown[]): void {\n if (shouldLogInfo) {\n process.stderr.write(formatMessage(...args));\n }\n },\n\n debug(...args: unknown[]): void {\n if (shouldLogDebug) {\n process.stderr.write(formatMessage(...args));\n }\n },\n\n error(...args: unknown[]): void {\n process.stderr.write(formatMessage(...args));\n },\n };\n}\n","import { mkdir } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport writeFileAtomicLib from \"write-file-atomic\";\n\n/**\n * Write file atomically with parent directory creation\n */\nexport async function writeFileAtomic(filePath: string, content: string): Promise<void> {\n await ensureDirectoryExists(dirname(filePath));\n await writeFileAtomicLib(filePath, content, { encoding: \"utf-8\" });\n}\n\n/**\n * Ensure directory exists, creating it recursively if necessary\n */\nexport async function ensureDirectoryExists(dirPath: string): Promise<void> {\n await mkdir(dirPath, { recursive: true });\n}\n","import { existsSync } from \"node:fs\";\nimport { copyFile, readFile, readdir, stat, unlink } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { ensureDirectoryExists } from \"./file\";\n\nexport interface BackupOptions {\n maxGenerations?: number;\n maxAgeMs?: number;\n}\n\nconst DEFAULT_MAX_GENERATIONS = 50;\nconst DEFAULT_MAX_AGE_MS = 365 * 24 * 60 * 60 * 1000; // 1 year\n\n/**\n * Get package name from package.json\n */\nasync function resolvePackageName(): Promise<string> {\n try {\n const currentFile = fileURLToPath(import.meta.url);\n let currentDir = dirname(currentFile);\n\n for (let i = 0; i < 10; i++) {\n const packageJsonPath = join(currentDir, \"package.json\");\n if (existsSync(packageJsonPath)) {\n const content = await readFile(packageJsonPath, \"utf-8\");\n const pkg = JSON.parse(content);\n return pkg.name;\n }\n currentDir = dirname(currentDir);\n }\n } catch {\n // Fall back to hardcoded name if package.json is not found\n }\n\n return \"reference-manager\";\n}\n\nconst packageName = await resolvePackageName();\n\n/**\n * Get backup directory path for a library\n */\nexport function getBackupDirectory(libraryName: string): string {\n const pkgName = packageName ?? \"reference-manager\";\n return join(tmpdir(), pkgName, \"backups\", libraryName);\n}\n\n/**\n * Create a backup of the given file\n */\nexport async function createBackup(sourceFile: string, libraryName: string): Promise<string> {\n const backupDir = getBackupDirectory(libraryName);\n await ensureDirectoryExists(backupDir);\n\n const timestamp = Date.now();\n const backupFileName = `${timestamp}.backup`;\n const backupPath = join(backupDir, backupFileName);\n\n await copyFile(sourceFile, backupPath);\n\n return backupPath;\n}\n\n/**\n * List all backups for a library (sorted by modification time, newest first)\n */\nexport async function listBackups(libraryName: string): Promise<string[]> {\n const backupDir = getBackupDirectory(libraryName);\n\n if (!existsSync(backupDir)) {\n return [];\n }\n\n const files = await readdir(backupDir);\n const backupFiles = files.filter((f) => f.endsWith(\".backup\")).map((f) => join(backupDir, f));\n\n const filesWithStats = await Promise.all(\n backupFiles.map(async (file) => {\n const stats = await stat(file);\n return { file, mtime: stats.mtimeMs };\n })\n );\n\n filesWithStats.sort((a, b) => b.mtime - a.mtime);\n\n return filesWithStats.map((f) => f.file);\n}\n\n/**\n * Clean up old backups based on generation count and age\n */\nexport async function cleanupOldBackups(\n libraryName: string,\n options?: BackupOptions\n): Promise<void> {\n const maxGenerations = options?.maxGenerations ?? DEFAULT_MAX_GENERATIONS;\n const maxAgeMs = options?.maxAgeMs ?? DEFAULT_MAX_AGE_MS;\n\n const backups = await listBackups(libraryName);\n const now = Date.now();\n\n const backupsToDelete: string[] = [];\n\n for (let i = 0; i < backups.length; i++) {\n const backupPath = backups[i];\n if (!backupPath) continue;\n\n const stats = await stat(backupPath);\n const age = now - stats.mtimeMs;\n\n if (i >= maxGenerations || age > maxAgeMs) {\n backupsToDelete.push(backupPath);\n }\n }\n\n await Promise.all(backupsToDelete.map((backup) => unlink(backup)));\n}\n","/**\n * 3-way merge implementation with Last-Write-Wins (LWW) strategy\n */\n\nimport type { CslItem } from \"../../core/csl-json/types.js\";\nimport type {\n FieldConflict,\n ItemConflict,\n MergeOptions,\n MergeResult,\n MergeStatus,\n} from \"./types.js\";\n\n/**\n * Get UUID from item, with fallback to id if uuid is missing\n */\nfunction getItemUuid(item: CslItem): string {\n return item.custom?.uuid || item.id || \"unknown\";\n}\n\n/**\n * Get timestamp from item, with fallback to created_at\n */\nfunction getTimestamp(item: CslItem): string {\n return item.custom?.timestamp || item.custom?.created_at || \"1970-01-01T00:00:00.000Z\";\n}\n\n/**\n * Deep equality check for field values\n */\nfunction deepEqual(a: unknown, b: unknown): boolean {\n return JSON.stringify(a) === JSON.stringify(b);\n}\n\n/**\n * Resolve a field conflict using LWW or prefer option\n */\nfunction resolveFieldConflict(\n localValue: unknown,\n remoteValue: unknown,\n localTimestamp: string,\n remoteTimestamp: string,\n options?: MergeOptions\n): unknown {\n if (localTimestamp > remoteTimestamp) {\n return localValue;\n }\n if (remoteTimestamp > localTimestamp) {\n return remoteValue;\n }\n // Timestamps equal: use prefer option or default to local\n if (options?.prefer === \"remote\") {\n return remoteValue;\n }\n return localValue;\n}\n\n/**\n * Determine conflict resolution type\n */\nfunction determineResolution(\n fieldConflicts: FieldConflict[],\n localTimestamp: string,\n remoteTimestamp: string,\n options?: MergeOptions\n): ItemConflict[\"resolution\"] {\n const hasRealConflicts = fieldConflicts.every((fc) => fc.resolved !== undefined);\n const localIsNewer = fieldConflicts.some(\n (fc) => fc.local !== fc.remote && localTimestamp > remoteTimestamp\n );\n const remoteIsNewer = fieldConflicts.some(\n (fc) => fc.local !== fc.remote && remoteTimestamp > localTimestamp\n );\n\n if (hasRealConflicts && localIsNewer) return \"auto-lww\";\n if (hasRealConflicts && remoteIsNewer) return \"auto-lww\";\n if (options?.prefer === \"local\") return \"prefer-local\";\n if (options?.prefer === \"remote\") return \"prefer-remote\";\n return \"unresolved\";\n}\n\n/**\n * Merge a single field from base, local, and remote versions\n */\nfunction mergeField(\n key: string,\n baseValue: unknown,\n localValue: unknown,\n remoteValue: unknown,\n localTimestamp: string,\n remoteTimestamp: string,\n options?: MergeOptions\n): { value: unknown; conflict: FieldConflict | null } {\n const localChanged = !deepEqual(baseValue, localValue);\n const remoteChanged = !deepEqual(baseValue, remoteValue);\n\n if (!localChanged && !remoteChanged) {\n return { value: baseValue, conflict: null };\n }\n\n if (localChanged && !remoteChanged) {\n return { value: localValue, conflict: null };\n }\n\n if (!localChanged && remoteChanged) {\n return { value: remoteValue, conflict: null };\n }\n\n // Both changed\n if (deepEqual(localValue, remoteValue)) {\n return { value: localValue, conflict: null };\n }\n\n // Both changed to different values\n const resolved = resolveFieldConflict(\n localValue,\n remoteValue,\n localTimestamp,\n remoteTimestamp,\n options\n );\n\n // Don't record conflicts for 'custom' metadata field\n if (key === \"custom\") {\n return { value: resolved, conflict: null };\n }\n\n return {\n value: resolved,\n conflict: {\n field: key,\n base: baseValue,\n local: localValue,\n remote: remoteValue,\n resolved,\n },\n };\n}\n\n/**\n * Merge a single item from base, local, and remote versions\n */\nfunction mergeItem(\n base: CslItem,\n local: CslItem,\n remote: CslItem,\n options?: MergeOptions\n): { merged: CslItem; conflict: ItemConflict | null } {\n const uuid = getItemUuid(base);\n const localTimestamp = getTimestamp(local);\n const remoteTimestamp = getTimestamp(remote);\n\n const merged: CslItem = { ...base };\n const fieldConflicts: FieldConflict[] = [];\n\n // Get all unique keys from all three versions\n const allKeys = new Set<string>([\n ...Object.keys(base),\n ...Object.keys(local),\n ...Object.keys(remote),\n ]);\n\n for (const key of allKeys) {\n const baseValue = (base as Record<string, unknown>)[key];\n const localValue = (local as Record<string, unknown>)[key];\n const remoteValue = (remote as Record<string, unknown>)[key];\n\n const { value, conflict } = mergeField(\n key,\n baseValue,\n localValue,\n remoteValue,\n localTimestamp,\n remoteTimestamp,\n options\n );\n\n (merged as Record<string, unknown>)[key] = value;\n\n if (conflict) {\n fieldConflicts.push(conflict);\n }\n }\n\n // If there are field conflicts, create ItemConflict\n if (fieldConflicts.length > 0) {\n const resolution = determineResolution(\n fieldConflicts,\n localTimestamp,\n remoteTimestamp,\n options\n );\n\n return {\n merged,\n conflict: {\n uuid,\n id: base.id || \"unknown\",\n fields: fieldConflicts,\n localTimestamp,\n remoteTimestamp,\n resolution,\n },\n };\n }\n\n return { merged, conflict: null };\n}\n\n/**\n * Build UUID-indexed maps from item arrays\n */\nfunction buildItemMaps(base: CslItem[], local: CslItem[], remote: CslItem[]) {\n const baseMap = new Map<string, CslItem>();\n const localMap = new Map<string, CslItem>();\n const remoteMap = new Map<string, CslItem>();\n\n for (const item of base) {\n baseMap.set(getItemUuid(item), item);\n }\n for (const item of local) {\n localMap.set(getItemUuid(item), item);\n }\n for (const item of remote) {\n remoteMap.set(getItemUuid(item), item);\n }\n\n return { baseMap, localMap, remoteMap };\n}\n\n/**\n * Handle items that exist in all three versions\n */\nfunction mergeExistingItem(\n baseItem: CslItem,\n localItem: CslItem,\n remoteItem: CslItem,\n options: MergeOptions | undefined,\n merged: CslItem[],\n conflicts: ItemConflict[]\n): void {\n const { merged: mergedItem, conflict } = mergeItem(baseItem, localItem, remoteItem, options);\n merged.push(mergedItem);\n if (conflict) {\n conflicts.push(conflict);\n }\n}\n\n/**\n * Handle items added in both local and remote\n */\nfunction handleDualAddition(\n uuid: string,\n localItem: CslItem,\n remoteItem: CslItem,\n options: MergeOptions | undefined,\n merged: CslItem[],\n conflicts: ItemConflict[]\n): void {\n if (deepEqual(localItem, remoteItem)) {\n merged.push(localItem);\n } else {\n const syntheticBase: CslItem = {\n id: uuid,\n type: \"article\",\n custom: {\n uuid,\n created_at: \"1970-01-01T00:00:00.000Z\",\n timestamp: \"1970-01-01T00:00:00.000Z\",\n },\n };\n const { merged: mergedItem, conflict } = mergeItem(\n syntheticBase,\n localItem,\n remoteItem,\n options\n );\n merged.push(mergedItem);\n if (conflict) {\n conflicts.push(conflict);\n }\n }\n}\n\n/**\n * Process a single UUID across all three versions\n */\nfunction processItem(\n uuid: string,\n baseMap: Map<string, CslItem>,\n localMap: Map<string, CslItem>,\n remoteMap: Map<string, CslItem>,\n options: MergeOptions | undefined,\n result: {\n merged: CslItem[];\n conflicts: ItemConflict[];\n localOnly: CslItem[];\n remoteOnly: CslItem[];\n deletedInLocal: CslItem[];\n deletedInRemote: CslItem[];\n }\n): void {\n const baseItem = baseMap.get(uuid);\n const localItem = localMap.get(uuid);\n const remoteItem = remoteMap.get(uuid);\n\n if (baseItem && localItem && remoteItem) {\n mergeExistingItem(baseItem, localItem, remoteItem, options, result.merged, result.conflicts);\n } else if (!baseItem && localItem && remoteItem) {\n handleDualAddition(uuid, localItem, remoteItem, options, result.merged, result.conflicts);\n } else if (!baseItem && localItem && !remoteItem) {\n result.merged.push(localItem);\n result.localOnly.push(localItem);\n } else if (!baseItem && !localItem && remoteItem) {\n result.merged.push(remoteItem);\n result.remoteOnly.push(remoteItem);\n } else if (baseItem && !localItem && remoteItem) {\n result.deletedInLocal.push(baseItem);\n } else if (baseItem && localItem && !remoteItem) {\n result.deletedInRemote.push(baseItem);\n } else if (baseItem && !localItem && !remoteItem) {\n result.deletedInLocal.push(baseItem);\n result.deletedInRemote.push(baseItem);\n }\n}\n\n/**\n * Performs a 3-way merge of CSL-JSON items\n *\n * @param base - Base version (common ancestor)\n * @param local - Local version (current working copy)\n * @param remote - Remote version (incoming changes)\n * @param options - Merge options (e.g., prefer local/remote for tie-breaking)\n * @returns Merge result with merged items and conflict information\n */\nexport function threeWayMerge(\n base: CslItem[],\n local: CslItem[],\n remote: CslItem[],\n options?: MergeOptions\n): MergeResult {\n const { baseMap, localMap, remoteMap } = buildItemMaps(base, local, remote);\n\n const result = {\n merged: [] as CslItem[],\n conflicts: [] as ItemConflict[],\n localOnly: [] as CslItem[],\n remoteOnly: [] as CslItem[],\n deletedInLocal: [] as CslItem[],\n deletedInRemote: [] as CslItem[],\n };\n\n const allUuids = new Set<string>([...baseMap.keys(), ...localMap.keys(), ...remoteMap.keys()]);\n\n for (const uuid of allUuids) {\n processItem(uuid, baseMap, localMap, remoteMap, options, result);\n }\n\n // Determine overall status\n let status: MergeStatus = \"success\";\n if (result.conflicts.length > 0) {\n const hasUnresolved = result.conflicts.some((c) => c.resolution === \"unresolved\");\n status = hasUnresolved ? \"conflict\" : \"auto-resolved\";\n }\n\n return {\n status,\n ...result,\n };\n}\n"],"names":["i","f"],"mappings":";;;;;;;;;AASO,SAAS,gBAAgB,MAA2B;AACzD,QAAM,cAAc,iBAAiB,UAAU,IAAI;AAEnD,MAAI,CAAC,YAAY,SAAS;AACxB,UAAM,IAAI,MAAM,+BAA+B,YAAY,MAAM,OAAO,EAAE;AAAA,EAC5E;AAEA,SAAO,YAAY;AACrB;ACTO,SAAS,aAAa,QAAkB,QAAgB;AAC7D,QAAM,gBAAgB,UAAU,UAAU,UAAU;AACpD,QAAM,iBAAiB,UAAU;AAEjC,WAAS,iBAAiB,MAAyB;AACjD,WAAO,GAAG,KAAK,IAAI,CAAC,QAAQ,OAAO,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC;AAAA;AAAA,EACpD;AAEA,SAAO;AAAA,IACL,QAAQ,MAAuB;AAC7B,UAAI,eAAe;AACjB,gBAAQ,OAAO,MAAM,cAAc,GAAG,IAAI,CAAC;AAAA,MAC7C;AAAA,IACF;AAAA,IAEA,SAAS,MAAuB;AAC9B,UAAI,gBAAgB;AAClB,gBAAQ,OAAO,MAAM,cAAc,GAAG,IAAI,CAAC;AAAA,MAC7C;AAAA,IACF;AAAA,IAEA,SAAS,MAAuB;AAC9B,cAAQ,OAAO,MAAM,cAAc,GAAG,IAAI,CAAC;AAAA,IAC7C;AAAA,EAAA;AAEJ;AC1BA,eAAsB,gBAAgB,UAAkB,SAAgC;AACtF,QAAM,sBAAsB,QAAQ,QAAQ,CAAC;AAC7C,QAAM,mBAAmB,UAAU,SAAS,EAAE,UAAU,SAAS;AACnE;AAKA,eAAsB,sBAAsB,SAAgC;AAC1E,QAAM,MAAM,SAAS,EAAE,WAAW,MAAM;AAC1C;ACLA,MAAM,0BAA0B;AAChC,MAAM,qBAAqB,MAAM,KAAK,KAAK,KAAK;AAKhD,eAAe,qBAAsC;AACnD,MAAI;AACF,UAAM,cAAc,cAAc,YAAY,GAAG;AACjD,QAAI,aAAa,QAAQ,WAAW;AAEpC,aAASA,KAAI,GAAGA,KAAI,IAAIA,MAAK;AAC3B,YAAM,kBAAkB,KAAK,YAAY,cAAc;AACvD,UAAI,WAAW,eAAe,GAAG;AAC/B,cAAM,UAAU,MAAM,SAAS,iBAAiB,OAAO;AACvD,cAAM,MAAM,KAAK,MAAM,OAAO;AAC9B,eAAO,IAAI;AAAA,MACb;AACA,mBAAa,QAAQ,UAAU;AAAA,IACjC;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;AAEA,MAAM,cAAc,MAAM,mBAAA;AAKnB,SAAS,mBAAmB,aAA6B;AAC9D,QAAM,UAAU,eAAe;AAC/B,SAAO,KAAK,OAAA,GAAU,SAAS,WAAW,WAAW;AACvD;AAKA,eAAsB,aAAa,YAAoB,aAAsC;AAC3F,QAAM,YAAY,mBAAmB,WAAW;AAChD,QAAM,sBAAsB,SAAS;AAErC,QAAM,YAAY,KAAK,IAAA;AACvB,QAAM,iBAAiB,GAAG,SAAS;AACnC,QAAM,aAAa,KAAK,WAAW,cAAc;AAEjD,QAAM,SAAS,YAAY,UAAU;AAErC,SAAO;AACT;AAKA,eAAsB,YAAY,aAAwC;AACxE,QAAM,YAAY,mBAAmB,WAAW;AAEhD,MAAI,CAAC,WAAW,SAAS,GAAG;AAC1B,WAAO,CAAA;AAAA,EACT;AAEA,QAAM,QAAQ,MAAM,QAAQ,SAAS;AACrC,QAAM,cAAc,MAAM,OAAO,CAACC,OAAMA,GAAE,SAAS,SAAS,CAAC,EAAE,IAAI,CAACA,OAAM,KAAK,WAAWA,EAAC,CAAC;AAE5F,QAAM,iBAAiB,MAAM,QAAQ;AAAA,IACnC,YAAY,IAAI,OAAO,SAAS;AAC9B,YAAM,QAAQ,MAAM,KAAK,IAAI;AAC7B,aAAO,EAAE,MAAM,OAAO,MAAM,QAAA;AAAA,IAC9B,CAAC;AAAA,EAAA;AAGH,iBAAe,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAE/C,SAAO,eAAe,IAAI,CAACA,OAAMA,GAAE,IAAI;AACzC;AAKA,eAAsB,kBACpB,aACA,SACe;AACf,QAAM,iBAAiB,SAAS,kBAAkB;AAClD,QAAM,WAAW,SAAS,YAAY;AAEtC,QAAM,UAAU,MAAM,YAAY,WAAW;AAC7C,QAAM,MAAM,KAAK,IAAA;AAEjB,QAAM,kBAA4B,CAAA;AAElC,WAASD,KAAI,GAAGA,KAAI,QAAQ,QAAQA,MAAK;AACvC,UAAM,aAAa,QAAQA,EAAC;AAC5B,QAAI,CAAC,WAAY;AAEjB,UAAM,QAAQ,MAAM,KAAK,UAAU;AACnC,UAAM,MAAM,MAAM,MAAM;AAExB,QAAIA,MAAK,kBAAkB,MAAM,UAAU;AACzC,sBAAgB,KAAK,UAAU;AAAA,IACjC;AAAA,EACF;AAEA,QAAM,QAAQ,IAAI,gBAAgB,IAAI,CAAC,WAAW,OAAO,MAAM,CAAC,CAAC;AACnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACtGA,SAAS,YAAY,MAAuB;AAC1C,SAAO,KAAK,QAAQ,QAAQ,KAAK,MAAM;AACzC;AAKA,SAAS,aAAa,MAAuB;AAC3C,SAAO,KAAK,QAAQ,aAAa,KAAK,QAAQ,cAAc;AAC9D;AAKA,SAAS,UAAU,GAAY,GAAqB;AAClD,SAAO,KAAK,UAAU,CAAC,MAAM,KAAK,UAAU,CAAC;AAC/C;AAKA,SAAS,qBACP,YACA,aACA,gBACA,iBACA,SACS;AACT,MAAI,iBAAiB,iBAAiB;AACpC,WAAO;AAAA,EACT;AACA,MAAI,kBAAkB,gBAAgB;AACpC,WAAO;AAAA,EACT;AAEA,MAAI,SAAS,WAAW,UAAU;AAChC,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAKA,SAAS,oBACP,gBACA,gBACA,iBACA,SAC4B;AAC5B,QAAM,mBAAmB,eAAe,MAAM,CAAC,OAAO,GAAG,aAAa,MAAS;AAC/E,QAAM,eAAe,eAAe;AAAA,IAClC,CAAC,OAAO,GAAG,UAAU,GAAG,UAAU,iBAAiB;AAAA,EAAA;AAErD,QAAM,gBAAgB,eAAe;AAAA,IACnC,CAAC,OAAO,GAAG,UAAU,GAAG,UAAU,kBAAkB;AAAA,EAAA;AAGtD,MAAI,oBAAoB,aAAc,QAAO;AAC7C,MAAI,oBAAoB,cAAe,QAAO;AAC9C,MAAI,SAAS,WAAW,QAAS,QAAO;AACxC,MAAI,SAAS,WAAW,SAAU,QAAO;AACzC,SAAO;AACT;AAKA,SAAS,WACP,KACA,WACA,YACA,aACA,gBACA,iBACA,SACoD;AACpD,QAAM,eAAe,CAAC,UAAU,WAAW,UAAU;AACrD,QAAM,gBAAgB,CAAC,UAAU,WAAW,WAAW;AAEvD,MAAI,CAAC,gBAAgB,CAAC,eAAe;AACnC,WAAO,EAAE,OAAO,WAAW,UAAU,KAAA;AAAA,EACvC;AAEA,MAAI,gBAAgB,CAAC,eAAe;AAClC,WAAO,EAAE,OAAO,YAAY,UAAU,KAAA;AAAA,EACxC;AAEA,MAAI,CAAC,gBAAgB,eAAe;AAClC,WAAO,EAAE,OAAO,aAAa,UAAU,KAAA;AAAA,EACzC;AAGA,MAAI,UAAU,YAAY,WAAW,GAAG;AACtC,WAAO,EAAE,OAAO,YAAY,UAAU,KAAA;AAAA,EACxC;AAGA,QAAM,WAAW;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAIF,MAAI,QAAQ,UAAU;AACpB,WAAO,EAAE,OAAO,UAAU,UAAU,KAAA;AAAA,EACtC;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,IACP,UAAU;AAAA,MACR,OAAO;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ;AAAA,MACR;AAAA,IAAA;AAAA,EACF;AAEJ;AAKA,SAAS,UACP,MACA,OACA,QACA,SACoD;AACpD,QAAM,OAAO,YAAY,IAAI;AAC7B,QAAM,iBAAiB,aAAa,KAAK;AACzC,QAAM,kBAAkB,aAAa,MAAM;AAE3C,QAAM,SAAkB,EAAE,GAAG,KAAA;AAC7B,QAAM,iBAAkC,CAAA;AAGxC,QAAM,8BAAc,IAAY;AAAA,IAC9B,GAAG,OAAO,KAAK,IAAI;AAAA,IACnB,GAAG,OAAO,KAAK,KAAK;AAAA,IACpB,GAAG,OAAO,KAAK,MAAM;AAAA,EAAA,CACtB;AAED,aAAW,OAAO,SAAS;AACzB,UAAM,YAAa,KAAiC,GAAG;AACvD,UAAM,aAAc,MAAkC,GAAG;AACzD,UAAM,cAAe,OAAmC,GAAG;AAE3D,UAAM,EAAE,OAAO,SAAA,IAAa;AAAA,MAC1B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAGD,WAAmC,GAAG,IAAI;AAE3C,QAAI,UAAU;AACZ,qBAAe,KAAK,QAAQ;AAAA,IAC9B;AAAA,EACF;AAGA,MAAI,eAAe,SAAS,GAAG;AAC7B,UAAM,aAAa;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAGF,WAAO;AAAA,MACL;AAAA,MACA,UAAU;AAAA,QACR;AAAA,QACA,IAAI,KAAK,MAAM;AAAA,QACf,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,IACF;AAAA,EAEJ;AAEA,SAAO,EAAE,QAAQ,UAAU,KAAA;AAC7B;AAKA,SAAS,cAAc,MAAiB,OAAkB,QAAmB;AAC3E,QAAM,8BAAc,IAAA;AACpB,QAAM,+BAAe,IAAA;AACrB,QAAM,gCAAgB,IAAA;AAEtB,aAAW,QAAQ,MAAM;AACvB,YAAQ,IAAI,YAAY,IAAI,GAAG,IAAI;AAAA,EACrC;AACA,aAAW,QAAQ,OAAO;AACxB,aAAS,IAAI,YAAY,IAAI,GAAG,IAAI;AAAA,EACtC;AACA,aAAW,QAAQ,QAAQ;AACzB,cAAU,IAAI,YAAY,IAAI,GAAG,IAAI;AAAA,EACvC;AAEA,SAAO,EAAE,SAAS,UAAU,UAAA;AAC9B;AAKA,SAAS,kBACP,UACA,WACA,YACA,SACA,QACA,WACM;AACN,QAAM,EAAE,QAAQ,YAAY,SAAA,IAAa,UAAU,UAAU,WAAW,YAAY,OAAO;AAC3F,SAAO,KAAK,UAAU;AACtB,MAAI,UAAU;AACZ,cAAU,KAAK,QAAQ;AAAA,EACzB;AACF;AAKA,SAAS,mBACP,MACA,WACA,YACA,SACA,QACA,WACM;AACN,MAAI,UAAU,WAAW,UAAU,GAAG;AACpC,WAAO,KAAK,SAAS;AAAA,EACvB,OAAO;AACL,UAAM,gBAAyB;AAAA,MAC7B,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,QAAQ;AAAA,QACN;AAAA,QACA,YAAY;AAAA,QACZ,WAAW;AAAA,MAAA;AAAA,IACb;AAEF,UAAM,EAAE,QAAQ,YAAY,SAAA,IAAa;AAAA,MACvC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAEF,WAAO,KAAK,UAAU;AACtB,QAAI,UAAU;AACZ,gBAAU,KAAK,QAAQ;AAAA,IACzB;AAAA,EACF;AACF;AAKA,SAAS,YACP,MACA,SACA,UACA,WACA,SACA,QAQM;AACN,QAAM,WAAW,QAAQ,IAAI,IAAI;AACjC,QAAM,YAAY,SAAS,IAAI,IAAI;AACnC,QAAM,aAAa,UAAU,IAAI,IAAI;AAErC,MAAI,YAAY,aAAa,YAAY;AACvC,sBAAkB,UAAU,WAAW,YAAY,SAAS,OAAO,QAAQ,OAAO,SAAS;AAAA,EAC7F,WAAW,CAAC,YAAY,aAAa,YAAY;AAC/C,uBAAmB,MAAM,WAAW,YAAY,SAAS,OAAO,QAAQ,OAAO,SAAS;AAAA,EAC1F,WAAW,CAAC,YAAY,aAAa,CAAC,YAAY;AAChD,WAAO,OAAO,KAAK,SAAS;AAC5B,WAAO,UAAU,KAAK,SAAS;AAAA,EACjC,WAAW,CAAC,YAAY,CAAC,aAAa,YAAY;AAChD,WAAO,OAAO,KAAK,UAAU;AAC7B,WAAO,WAAW,KAAK,UAAU;AAAA,EACnC,WAAW,YAAY,CAAC,aAAa,YAAY;AAC/C,WAAO,eAAe,KAAK,QAAQ;AAAA,EACrC,WAAW,YAAY,aAAa,CAAC,YAAY;AAC/C,WAAO,gBAAgB,KAAK,QAAQ;AAAA,EACtC,WAAW,YAAY,CAAC,aAAa,CAAC,YAAY;AAChD,WAAO,eAAe,KAAK,QAAQ;AACnC,WAAO,gBAAgB,KAAK,QAAQ;AAAA,EACtC;AACF;AAWO,SAAS,cACd,MACA,OACA,QACA,SACa;AACb,QAAM,EAAE,SAAS,UAAU,UAAA,IAAc,cAAc,MAAM,OAAO,MAAM;AAE1E,QAAM,SAAS;AAAA,IACb,QAAQ,CAAA;AAAA,IACR,WAAW,CAAA;AAAA,IACX,WAAW,CAAA;AAAA,IACX,YAAY,CAAA;AAAA,IACZ,gBAAgB,CAAA;AAAA,IAChB,iBAAiB,CAAA;AAAA,EAAC;AAGpB,QAAM,WAAW,oBAAI,IAAY,CAAC,GAAG,QAAQ,KAAA,GAAQ,GAAG,SAAS,QAAQ,GAAG,UAAU,KAAA,CAAM,CAAC;AAE7F,aAAW,QAAQ,UAAU;AAC3B,gBAAY,MAAM,SAAS,UAAU,WAAW,SAAS,MAAM;AAAA,EACjE;AAGA,MAAI,SAAsB;AAC1B,MAAI,OAAO,UAAU,SAAS,GAAG;AAC/B,UAAM,gBAAgB,OAAO,UAAU,KAAK,CAAC,MAAM,EAAE,eAAe,YAAY;AAChF,aAAS,gBAAgB,aAAa;AAAA,EACxC;AAEA,SAAO;AAAA,IACL;AAAA,IACA,GAAG;AAAA,EAAA;AAEP;;;;;"}
|
package/dist/mcp/context.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { Config } from "../config/schema.js";
|
|
2
|
-
import { Library } from "../core/library.js";
|
|
3
2
|
import { FileWatcher } from "../features/file-watcher/file-watcher.js";
|
|
3
|
+
import type { ILibraryOperations } from "../features/operations/library-operations.js";
|
|
4
4
|
/**
|
|
5
|
-
* MCP context containing
|
|
6
|
-
*
|
|
5
|
+
* MCP context containing libraryOperations, config, and file watcher.
|
|
6
|
+
* Uses ILibraryOperations pattern for consistency with CLI (see ADR-009, ADR-010).
|
|
7
7
|
*/
|
|
8
8
|
export interface McpContext {
|
|
9
|
-
|
|
9
|
+
libraryOperations: ILibraryOperations;
|
|
10
10
|
config: Config;
|
|
11
11
|
fileWatcher: FileWatcher;
|
|
12
12
|
dispose: () => Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/mcp/context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/mcp/context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAC;AACvE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8CAA8C,CAAC;AAGvF;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,iBAAiB,EAAE,kBAAkB,CAAC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,WAAW,CAAC;IACzB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,UAAU,CAAC,CA6C5F"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { ILibraryOperations } from "../../features/operations/library-operations.js";
|
|
3
3
|
/**
|
|
4
4
|
* Register all resources with the MCP server.
|
|
5
5
|
*
|
|
6
6
|
* @param server - The MCP server instance
|
|
7
|
-
* @param
|
|
7
|
+
* @param getLibraryOperations - Function to get the current library operations instance
|
|
8
8
|
*/
|
|
9
|
-
export declare function registerAllResources(server: McpServer,
|
|
9
|
+
export declare function registerAllResources(server: McpServer, getLibraryOperations: () => ILibraryOperations): void;
|
|
10
10
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/mcp/resources/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/mcp/resources/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iDAAiD,CAAC;AAO1F;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,SAAS,EACjB,oBAAoB,EAAE,MAAM,kBAAkB,GAC7C,IAAI,CAIN"}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { ILibraryOperations } from "../../features/operations/library-operations.js";
|
|
3
3
|
/**
|
|
4
4
|
* Register the references resource with the MCP server.
|
|
5
5
|
* Returns all references as CSL-JSON.
|
|
6
6
|
*
|
|
7
7
|
* @param server - The MCP server instance
|
|
8
|
-
* @param
|
|
8
|
+
* @param getLibraryOperations - Function to get the current library operations instance
|
|
9
9
|
*/
|
|
10
|
-
export declare function registerReferencesResource(server: McpServer,
|
|
10
|
+
export declare function registerReferencesResource(server: McpServer, getLibraryOperations: () => ILibraryOperations): void;
|
|
11
11
|
/**
|
|
12
12
|
* Register the single reference resource with the MCP server.
|
|
13
13
|
* Returns a single reference by ID.
|
|
14
14
|
*
|
|
15
15
|
* @param server - The MCP server instance
|
|
16
|
-
* @param
|
|
16
|
+
* @param getLibraryOperations - Function to get the current library operations instance
|
|
17
17
|
*/
|
|
18
|
-
export declare function registerReferenceResource(server: McpServer,
|
|
18
|
+
export declare function registerReferenceResource(server: McpServer, getLibraryOperations: () => ILibraryOperations): void;
|
|
19
19
|
/**
|
|
20
20
|
* Register the styles resource with the MCP server.
|
|
21
21
|
* Returns available citation styles.
|