@ncukondo/search-hub 0.13.0 → 0.15.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 +39 -9
- package/dist/cli/commands/check.d.ts +34 -0
- package/dist/cli/commands/check.d.ts.map +1 -0
- package/dist/cli/commands/check.js +126 -0
- package/dist/cli/commands/check.js.map +1 -0
- package/dist/cli/commands/export.d.ts +5 -3
- package/dist/cli/commands/export.d.ts.map +1 -1
- package/dist/cli/commands/export.js +0 -4
- package/dist/cli/commands/export.js.map +1 -1
- package/dist/cli/commands/query/init.d.ts.map +1 -1
- package/dist/cli/commands/query/init.js +17 -7
- package/dist/cli/commands/query/init.js.map +1 -1
- package/dist/cli/commands/query/inspect.d.ts +36 -0
- package/dist/cli/commands/query/inspect.d.ts.map +1 -0
- package/dist/cli/commands/query/inspect.js +155 -0
- package/dist/cli/commands/query/inspect.js.map +1 -0
- package/dist/cli/commands/query/translate.d.ts.map +1 -1
- package/dist/cli/commands/query/translate.js +3 -1
- package/dist/cli/commands/query/translate.js.map +1 -1
- package/dist/cli/commands/query-filter.d.ts +13 -0
- package/dist/cli/commands/query-filter.d.ts.map +1 -0
- package/dist/cli/commands/query-filter.js +149 -0
- package/dist/cli/commands/query-filter.js.map +1 -0
- package/dist/cli/commands/results.d.ts +3 -3
- package/dist/cli/commands/results.d.ts.map +1 -1
- package/dist/cli/commands/results.js +12 -3
- package/dist/cli/commands/results.js.map +1 -1
- package/dist/cli/commands/search-executor.d.ts.map +1 -1
- package/dist/cli/commands/search-executor.js +12 -7
- package/dist/cli/commands/search-executor.js.map +1 -1
- package/dist/cli/e2e-helpers.d.ts +5 -2
- package/dist/cli/e2e-helpers.d.ts.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +228 -45
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/providers/arxiv/provider.d.ts +3 -3
- package/dist/providers/arxiv/provider.d.ts.map +1 -1
- package/dist/providers/arxiv/provider.js +3 -3
- package/dist/providers/arxiv/provider.js.map +1 -1
- package/dist/providers/arxiv/translator.d.ts +3 -3
- package/dist/providers/arxiv/translator.d.ts.map +1 -1
- package/dist/providers/arxiv/translator.js +6 -8
- package/dist/providers/arxiv/translator.js.map +1 -1
- package/dist/providers/base/index.d.ts +1 -1
- package/dist/providers/base/index.d.ts.map +1 -1
- package/dist/providers/base/mock-provider.d.ts +2 -2
- package/dist/providers/base/mock-provider.d.ts.map +1 -1
- package/dist/providers/base/mock-provider.js +2 -9
- package/dist/providers/base/mock-provider.js.map +1 -1
- package/dist/providers/base/provider.d.ts +3 -3
- package/dist/providers/base/provider.d.ts.map +1 -1
- package/dist/providers/base/provider.js.map +1 -1
- package/dist/providers/base/types.d.ts +4 -6
- package/dist/providers/base/types.d.ts.map +1 -1
- package/dist/providers/base/types.js.map +1 -1
- package/dist/providers/eric/provider.d.ts +3 -3
- package/dist/providers/eric/provider.d.ts.map +1 -1
- package/dist/providers/eric/provider.js +3 -3
- package/dist/providers/eric/provider.js.map +1 -1
- package/dist/providers/eric/translator.d.ts +5 -5
- package/dist/providers/eric/translator.d.ts.map +1 -1
- package/dist/providers/eric/translator.js +6 -7
- package/dist/providers/eric/translator.js.map +1 -1
- package/dist/providers/pubmed/provider.d.ts +3 -3
- package/dist/providers/pubmed/provider.d.ts.map +1 -1
- package/dist/providers/pubmed/provider.js +3 -3
- package/dist/providers/pubmed/provider.js.map +1 -1
- package/dist/providers/pubmed/translator.d.ts +3 -3
- package/dist/providers/pubmed/translator.d.ts.map +1 -1
- package/dist/providers/pubmed/translator.js +4 -23
- package/dist/providers/pubmed/translator.js.map +1 -1
- package/dist/providers/scopus/provider.d.ts +3 -3
- package/dist/providers/scopus/provider.d.ts.map +1 -1
- package/dist/providers/scopus/provider.js +3 -3
- package/dist/providers/scopus/provider.js.map +1 -1
- package/dist/providers/scopus/translator.d.ts +3 -3
- package/dist/providers/scopus/translator.d.ts.map +1 -1
- package/dist/providers/scopus/translator.js +7 -9
- package/dist/providers/scopus/translator.js.map +1 -1
- package/dist/query/index.d.ts +3 -2
- package/dist/query/index.d.ts.map +1 -1
- package/dist/query/json-schema.d.ts.map +1 -1
- package/dist/query/json-schema.js +20 -11
- package/dist/query/json-schema.js.map +1 -1
- package/dist/query/mesh-lookup.d.ts.map +1 -1
- package/dist/query/mesh-lookup.js +66 -3
- package/dist/query/mesh-lookup.js.map +1 -1
- package/dist/query/resolver.d.ts +14 -0
- package/dist/query/resolver.d.ts.map +1 -0
- package/dist/query/resolver.js +61 -0
- package/dist/query/resolver.js.map +1 -0
- package/dist/query/types.d.ts +31 -11
- package/dist/query/types.d.ts.map +1 -1
- package/dist/query/validator.d.ts +659 -348
- package/dist/query/validator.d.ts.map +1 -1
- package/dist/query/validator.js +70 -30
- package/dist/query/validator.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { parseQueryFile, parseQueryString } from "./query/parser.js";
|
|
2
|
-
import {
|
|
2
|
+
import { resolveForProvider } from "./query/resolver.js";
|
|
3
|
+
import { ValidationError, fieldTypeSchema, filtersSchema, formatValidationErrors, providerSectionSchema, queryBlockSchema, queryFileSchema, termBlockSchema, validateQueryFile } from "./query/validator.js";
|
|
3
4
|
import { MeSHLookupClient } from "./query/mesh-lookup.js";
|
|
4
5
|
import { extractControlledVocabTerms, validateControlledVocab } from "./query/vocab-validator.js";
|
|
5
6
|
import { loadConfig, saveConfig } from "./config/loader.js";
|
|
@@ -40,11 +41,12 @@ export {
|
|
|
40
41
|
listSessions,
|
|
41
42
|
loadConfig,
|
|
42
43
|
loadSession,
|
|
43
|
-
overrideBlockSchema,
|
|
44
44
|
parseQueryFile,
|
|
45
45
|
parseQueryString,
|
|
46
|
+
providerSectionSchema,
|
|
46
47
|
queryBlockSchema,
|
|
47
48
|
queryFileSchema,
|
|
49
|
+
resolveForProvider,
|
|
48
50
|
sanitizeName,
|
|
49
51
|
saveConfig,
|
|
50
52
|
saveSession,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BaseProvider } from '../base/provider.js';
|
|
2
|
-
import { Article, TranslatedQuery, SearchOptions, SearchState, SearchResumeResult,
|
|
2
|
+
import { Article, TranslatedQuery, SearchOptions, SearchState, SearchResumeResult, ResolvedAST, ConnectionTestResult } from '../base/types.js';
|
|
3
3
|
import { ArxivConfig } from './types.js';
|
|
4
4
|
/**
|
|
5
5
|
* arXiv provider for searching preprints.
|
|
@@ -11,9 +11,9 @@ export declare class ArxivProvider extends BaseProvider {
|
|
|
11
11
|
private currentState;
|
|
12
12
|
constructor(config?: ArxivConfig);
|
|
13
13
|
/**
|
|
14
|
-
* Translate
|
|
14
|
+
* Translate ResolvedAST to arXiv-native query syntax.
|
|
15
15
|
*/
|
|
16
|
-
translateQuery(
|
|
16
|
+
translateQuery(resolved: ResolvedAST): TranslatedQuery;
|
|
17
17
|
/**
|
|
18
18
|
* Get total hit count for a query without downloading results.
|
|
19
19
|
* Uses a minimal search with maxResults=1 to get the total count from response metadata.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/providers/arxiv/provider.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EACV,OAAO,EACP,eAAe,EACf,aAAa,EACb,WAAW,EACX,kBAAkB,EAClB,
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/providers/arxiv/provider.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EACV,OAAO,EACP,eAAe,EACf,aAAa,EACb,WAAW,EACX,kBAAkB,EAClB,WAAW,EACX,oBAAoB,EACrB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,KAAK,EAAE,WAAW,EAAsB,MAAM,YAAY,CAAC;AAKlE;;GAEG;AACH,qBAAa,aAAc,SAAQ,YAAY;IAC7C,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAU;IAEjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAwB;IAGpD,OAAO,CAAC,YAAY,CAA4B;gBAEpC,MAAM,GAAE,WAAgB;IAqBpC;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,WAAW,GAAG,eAAe;IAItD;;;OAGG;IACG,KAAK,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;IAOpD;;OAEG;IACI,MAAM,CAAC,KAAK,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,aAAa,CAAC,OAAO,CAAC;IA0DtF;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,oBAAoB,CAAC;IAWrD;;OAEG;IACH,cAAc,IAAI,WAAW,GAAG,IAAI;IAIpC;;OAEG;IACI,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,aAAa,CAAC,OAAO,CAAC;IAsD/D;;;OAGG;IACG,aAAa,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,kBAAkB,CAAC;CAItE"}
|
|
@@ -29,10 +29,10 @@ class ArxivProvider extends BaseProvider {
|
|
|
29
29
|
});
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
|
-
* Translate
|
|
32
|
+
* Translate ResolvedAST to arXiv-native query syntax.
|
|
33
33
|
*/
|
|
34
|
-
translateQuery(
|
|
35
|
-
return translateQuery(
|
|
34
|
+
translateQuery(resolved) {
|
|
35
|
+
return translateQuery(resolved);
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
38
38
|
* Get total hit count for a query without downloading results.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.js","sources":["../../../src/providers/arxiv/provider.ts"],"sourcesContent":["/**\n * arXiv Provider\n *\n * Provider implementation for searching the arXiv preprint server.\n * Supports physics, mathematics, computer science, quantitative biology,\n * and related fields.\n */\n\nimport { BaseProvider } from '../base/provider.js';\nimport type {\n Article,\n TranslatedQuery,\n SearchOptions,\n SearchState,\n SearchResumeResult,\n
|
|
1
|
+
{"version":3,"file":"provider.js","sources":["../../../src/providers/arxiv/provider.ts"],"sourcesContent":["/**\n * arXiv Provider\n *\n * Provider implementation for searching the arXiv preprint server.\n * Supports physics, mathematics, computer science, quantitative biology,\n * and related fields.\n */\n\nimport { BaseProvider } from '../base/provider.js';\nimport type {\n Article,\n TranslatedQuery,\n SearchOptions,\n SearchState,\n SearchResumeResult,\n ResolvedAST,\n ConnectionTestResult,\n} from '../base/types.js';\nimport { ArxivClient } from './client.js';\nimport { translateQuery } from './translator.js';\nimport type { ArxivConfig, ArxivProviderState } from './types.js';\nimport { DEFAULT_ARXIV_CONFIG } from './types.js';\n\nconst DEFAULT_PAGE_SIZE = 100;\n\n/**\n * arXiv provider for searching preprints.\n */\nexport class ArxivProvider extends BaseProvider {\n readonly name = 'arxiv' as const;\n\n private readonly client: ArxivClient;\n private readonly arxivConfig: Required<ArxivConfig>;\n\n // State tracking for session resume\n private currentState: SearchState | null = null;\n\n constructor(config: ArxivConfig = {}) {\n super({\n rateLimit: config.rateLimit ?? DEFAULT_ARXIV_CONFIG.rateLimit,\n timeout: config.timeout ?? DEFAULT_ARXIV_CONFIG.timeout,\n retries: config.retries ?? DEFAULT_ARXIV_CONFIG.retries,\n initialBackoff: config.initialBackoff ?? DEFAULT_ARXIV_CONFIG.initialBackoff,\n maxBackoff: config.maxBackoff ?? DEFAULT_ARXIV_CONFIG.maxBackoff,\n });\n\n this.arxivConfig = {\n ...DEFAULT_ARXIV_CONFIG,\n ...config,\n };\n\n this.client = new ArxivClient({\n baseUrl: this.arxivConfig.baseUrl,\n minRequestInterval: Math.ceil(1000 / this.arxivConfig.rateLimit), // Convert rate to interval\n timeout: this.arxivConfig.timeout,\n });\n }\n\n /**\n * Translate ResolvedAST to arXiv-native query syntax.\n */\n translateQuery(resolved: ResolvedAST): TranslatedQuery {\n return translateQuery(resolved);\n }\n\n /**\n * Get total hit count for a query without downloading results.\n * Uses a minimal search with maxResults=1 to get the total count from response metadata.\n */\n async count(query: TranslatedQuery): Promise<number> {\n const response = await this.withRetry(() =>\n this.client.search(query.native, { start: 0, maxResults: 1 })\n );\n return response.totalResults;\n }\n\n /**\n * Search arXiv and yield articles as async iterable.\n */\n async *search(query: TranslatedQuery, options?: SearchOptions): AsyncIterable<Article> {\n const maxResults = options?.maxResults ?? this.arxivConfig.maxResults;\n const pageSize = options?.pageSize ?? DEFAULT_PAGE_SIZE;\n\n let offset = 0;\n let retrievedCount = 0;\n let totalResults = 0;\n\n while (retrievedCount < maxResults) {\n const searchOptions: { start: number; maxResults: number; signal?: AbortSignal } = {\n start: offset,\n maxResults: Math.min(pageSize, maxResults - retrievedCount),\n };\n if (options?.signal) {\n searchOptions.signal = options.signal;\n }\n\n const response = await this.withRetry(() =>\n this.client.search(query.native, searchOptions)\n );\n\n totalResults = response.totalResults;\n\n // Update state for session resume\n this.currentState = {\n ...this.createBaseState(query, totalResults, retrievedCount),\n providerState: { offset } as ArxivProviderState,\n };\n\n // Yield articles from this page\n for (const entry of response.entries) {\n if (retrievedCount >= maxResults) {\n break;\n }\n yield entry;\n retrievedCount++;\n }\n\n // Update state after yielding\n if (this.currentState) {\n this.currentState.retrievedCount = retrievedCount;\n this.currentState.providerState = {\n offset: offset + response.entries.length,\n } as ArxivProviderState;\n }\n\n // Check if we've retrieved all available results\n if (response.entries.length === 0 || offset + response.entries.length >= totalResults) {\n break;\n }\n\n offset += response.entries.length;\n }\n\n // Clear state when search completes\n this.currentState = null;\n }\n\n /**\n * Test connection to arXiv API.\n */\n async testConnection(): Promise<ConnectionTestResult> {\n try {\n // Make a minimal search request\n await this.client.search('ti:test', { start: 0, maxResults: 1 });\n return { ok: true };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return { ok: false, error: message };\n }\n }\n\n /**\n * Get current search state for session persistence.\n */\n getSearchState(): SearchState | null {\n return this.currentState;\n }\n\n /**\n * Resume search from saved state.\n */\n async *resumeSearch(state: SearchState): AsyncIterable<Article> {\n const providerState = state.providerState as ArxivProviderState | undefined;\n const startOffset = providerState?.offset ?? 0;\n\n const maxResults = state.totalResults - state.retrievedCount;\n const pageSize = DEFAULT_PAGE_SIZE;\n\n let offset = startOffset;\n let retrievedCount = 0;\n\n while (retrievedCount < maxResults) {\n const response = await this.withRetry(() =>\n this.client.search(state.query.native, {\n start: offset,\n maxResults: Math.min(pageSize, maxResults - retrievedCount),\n })\n );\n\n // Update state\n this.currentState = {\n ...state,\n retrievedCount: state.retrievedCount + retrievedCount,\n lastUpdated: new Date(),\n providerState: { offset },\n };\n\n // Yield articles\n for (const entry of response.entries) {\n if (retrievedCount >= maxResults) {\n break;\n }\n yield entry;\n retrievedCount++;\n }\n\n // Update state after yielding\n if (this.currentState) {\n this.currentState.retrievedCount = state.retrievedCount + retrievedCount;\n this.currentState.providerState = {\n offset: offset + response.entries.length,\n } as ArxivProviderState;\n }\n\n // Check if done\n if (response.entries.length === 0 || offset + response.entries.length >= state.totalResults) {\n break;\n }\n\n offset += response.entries.length;\n }\n\n this.currentState = null;\n }\n\n /**\n * Validate if saved state is still valid.\n * arXiv uses offset-based pagination, so state is always valid.\n */\n async validateState(_state: SearchState): Promise<SearchResumeResult> {\n // Offset-based pagination doesn't expire\n return { valid: true };\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FieldType, Operator, ResolvedAST } from '../../query/types.js';
|
|
2
2
|
import { TranslatedQuery } from '../base/types.js';
|
|
3
3
|
/**
|
|
4
4
|
* Get the arXiv field prefix for a DSL field type.
|
|
@@ -11,7 +11,7 @@ export declare function translateFieldPrefix(field: FieldType): string | null;
|
|
|
11
11
|
*/
|
|
12
12
|
export declare function translateTerms(prefix: string, keywords: string[], operator: Operator): string;
|
|
13
13
|
/**
|
|
14
|
-
* Translate a
|
|
14
|
+
* Translate a ResolvedAST to arXiv-native syntax.
|
|
15
15
|
*/
|
|
16
|
-
export declare function translateQuery(
|
|
16
|
+
export declare function translateQuery(resolved: ResolvedAST): TranslatedQuery;
|
|
17
17
|
//# sourceMappingURL=translator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translator.d.ts","sourceRoot":"","sources":["../../../src/providers/arxiv/translator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"translator.d.ts","sourceRoot":"","sources":["../../../src/providers/arxiv/translator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAc,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACzF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAexD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CAEpE;AASD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAY7F;AAqID;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,WAAW,GAAG,eAAe,CA+DrE"}
|
|
@@ -96,10 +96,10 @@ function translateCategories(categories) {
|
|
|
96
96
|
}
|
|
97
97
|
return `(${catTerms.join(" OR ")})`;
|
|
98
98
|
}
|
|
99
|
-
function translateQuery(
|
|
99
|
+
function translateQuery(resolved) {
|
|
100
100
|
const parts = [];
|
|
101
101
|
const notClauses = [];
|
|
102
|
-
const blockResults =
|
|
102
|
+
const blockResults = resolved.blocks.map(translateBlock);
|
|
103
103
|
const blockParts = blockResults.map((r) => r.query).filter((part) => part !== "");
|
|
104
104
|
const blockNotClauses = blockResults.map((r) => r.notClause).filter((s) => s !== null);
|
|
105
105
|
notClauses.push(...blockNotClauses);
|
|
@@ -110,13 +110,12 @@ function translateQuery(ast) {
|
|
|
110
110
|
parts.push(blockParts.map((part) => `(${part})`).join(" AND "));
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
|
-
const dateFilter = translateDateFilter(
|
|
113
|
+
const dateFilter = translateDateFilter(resolved.filters.yearFrom, resolved.filters.yearTo);
|
|
114
114
|
if (dateFilter) {
|
|
115
115
|
parts.push(`(${dateFilter})`);
|
|
116
116
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const categoryFilter = translateCategories(arxivOverrides.categories);
|
|
117
|
+
if (resolved.filters.categories && resolved.filters.categories.length > 0) {
|
|
118
|
+
const categoryFilter = translateCategories(resolved.filters.categories);
|
|
120
119
|
if (categoryFilter) {
|
|
121
120
|
parts.push(`(${categoryFilter})`);
|
|
122
121
|
}
|
|
@@ -136,10 +135,9 @@ function translateQuery(ast) {
|
|
|
136
135
|
native = notClause;
|
|
137
136
|
}
|
|
138
137
|
}
|
|
139
|
-
const warnings = collectUnsupportedVocabWarnings(
|
|
138
|
+
const warnings = collectUnsupportedVocabWarnings(resolved.blocks, "arXiv", /* @__PURE__ */ new Set());
|
|
140
139
|
return {
|
|
141
140
|
native,
|
|
142
|
-
originalAst: ast,
|
|
143
141
|
provider: "arxiv",
|
|
144
142
|
...warnings.length > 0 ? { warnings } : {}
|
|
145
143
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translator.js","sources":["../../../src/providers/arxiv/translator.ts"],"sourcesContent":["/**\n * arXiv Query Translator\n *\n * Translates QueryAST to arXiv-native query syntax.\n *\n * Field mappings:\n * - title → ti:\n * - abstract → abs:\n * - title_abstract → (ti: OR abs:) expansion\n * - author → au:\n * - all → all:\n * - keyword → not supported\n *\n * Boolean operators: AND, OR, ANDNOT (not standard NOT)\n * Date filter: submittedDate:[YYYYMMDDHHmm TO YYYYMMDDHHmm]\n * Category filter: cat:cs.AI\n */\n\nimport type { QueryAST, QueryBlock, FieldType, Operator } from '../../query/types.js';\nimport type { TranslatedQuery } from '../base/types.js';\nimport { collectUnsupportedVocabWarnings } from '../base/warnings.js';\n\n/**\n * Field prefix mappings for arXiv API.\n */\nconst FIELD_PREFIXES: Partial<Record<FieldType, string>> = {\n title: 'ti:',\n abstract: 'abs:',\n author: 'au:',\n all: 'all:',\n // title_abstract requires expansion, not a direct prefix\n // keyword is not supported by arXiv\n};\n\n/**\n * Get the arXiv field prefix for a DSL field type.\n * Returns null if the field requires special handling or is unsupported.\n */\nexport function translateFieldPrefix(field: FieldType): string | null {\n return FIELD_PREFIXES[field] ?? null;\n}\n\n/**\n * Wrap a term in quotes if it contains spaces (phrase search).\n */\nfunction quoteIfNeeded(term: string): string {\n return term.includes(' ') ? `\"${term}\"` : term;\n}\n\n/**\n * Translate terms with a field prefix.\n * Handles quoting of multi-word phrases.\n */\nexport function translateTerms(prefix: string, keywords: string[], operator: Operator): string {\n if (keywords.length === 0) {\n return '';\n }\n\n const translatedTerms = keywords.map((keyword) => `${prefix}${quoteIfNeeded(keyword)}`);\n\n if (translatedTerms.length === 1) {\n return translatedTerms[0]!;\n }\n\n return `(${translatedTerms.join(` ${operator} `)})`;\n}\n\n/**\n * Translate a single query block to arXiv syntax.\n * Returns an object with the main query part and optional ANDNOT clause.\n */\nfunction translateBlock(block: QueryBlock): { query: string; notClause: string | null } {\n const { field, terms, operator } = block;\n\n // arXiv only uses keywords; ignore mesh and emtree\n const keywords = terms.keywords ?? [];\n\n let query = '';\n\n if (keywords.length > 0) {\n // Handle title_abstract expansion\n if (field === 'title_abstract') {\n query = translateTitleAbstract(keywords, operator);\n } else {\n // Get field prefix\n const prefix = translateFieldPrefix(field);\n if (prefix !== null) {\n query = translateTerms(prefix, keywords, operator);\n }\n }\n }\n\n // Translate exclude terms\n const notClause = terms.exclude\n ? translateExcludeTerms(terms.exclude, field)\n : null;\n\n return { query, notClause };\n}\n\n/**\n * Expand title_abstract to (ti: OR abs:) for each keyword.\n */\nfunction translateTitleAbstract(keywords: string[], operator: Operator): string {\n if (keywords.length === 0) {\n return '';\n }\n\n // Each keyword expands to (ti:keyword OR abs:keyword)\n const expandedTerms = keywords.map((keyword) => {\n const quoted = quoteIfNeeded(keyword);\n return `(ti:${quoted} OR abs:${quoted})`;\n });\n\n if (expandedTerms.length === 1) {\n return expandedTerms[0]!;\n }\n\n return `(${expandedTerms.join(` ${operator} `)})`;\n}\n\n/**\n * Translate exclude terms to ANDNOT clause.\n * arXiv uses ANDNOT instead of NOT.\n */\nfunction translateExcludeTerms(\n exclude: string[],\n field: FieldType\n): string | null {\n if (exclude.length === 0) {\n return null;\n }\n\n // Handle title_abstract expansion\n if (field === 'title_abstract') {\n const expandedTerms = exclude.map((term) => {\n const quoted = quoteIfNeeded(term);\n return `(ti:${quoted} OR abs:${quoted})`;\n });\n if (expandedTerms.length === 1) {\n return `ANDNOT (${expandedTerms[0]})`;\n }\n return `ANDNOT (${expandedTerms.join(' OR ')})`;\n }\n\n // Get field prefix\n const prefix = translateFieldPrefix(field);\n if (prefix === null) {\n // Unsupported field\n return null;\n }\n\n const translatedTerms = exclude.map((term) => `${prefix}${quoteIfNeeded(term)}`);\n\n if (translatedTerms.length === 1) {\n return `ANDNOT ${translatedTerms[0]}`;\n }\n return `ANDNOT (${translatedTerms.join(' OR ')})`;\n}\n\n/**\n * Translate date filter to arXiv submittedDate range.\n * Format: submittedDate:[YYYYMMDDHHmm TO YYYYMMDDHHmm]\n * Note: arXiv API does not support wildcards (*), so we use concrete dates:\n * - Start: 1991 (arXiv's founding year)\n * - End: current year + 1 (to include all future submissions)\n */\nfunction translateDateFilter(yearFrom?: number, yearTo?: number): string {\n if (yearFrom === undefined && yearTo === undefined) {\n return '';\n }\n\n // arXiv was founded in 1991, use as default start\n const fromDate = yearFrom !== undefined ? `${yearFrom}01010000` : '199101010000';\n // Use next year as default end to include all current submissions\n const defaultEndYear = new Date().getFullYear() + 1;\n const toDate = yearTo !== undefined ? `${yearTo}12312359` : `${defaultEndYear}12312359`;\n\n return `submittedDate:[${fromDate} TO ${toDate}]`;\n}\n\n/**\n * Translate arXiv category filter.\n */\nfunction translateCategories(categories: string[]): string {\n if (categories.length === 0) {\n return '';\n }\n\n const catTerms = categories.map((cat) => `cat:${cat}`);\n\n if (catTerms.length === 1) {\n return catTerms[0]!;\n }\n\n return `(${catTerms.join(' OR ')})`;\n}\n\n/**\n * Translate a complete QueryAST to arXiv-native syntax.\n */\nexport function translateQuery(ast: QueryAST): TranslatedQuery {\n const parts: string[] = [];\n const notClauses: string[] = [];\n\n // Translate all blocks (AND'd together)\n const blockResults = ast.blocks.map(translateBlock);\n const blockParts = blockResults.map((r) => r.query).filter((part) => part !== '');\n const blockNotClauses = blockResults\n .map((r) => r.notClause)\n .filter((s): s is string => s !== null);\n\n notClauses.push(...blockNotClauses);\n\n if (blockParts.length > 0) {\n if (blockParts.length === 1) {\n parts.push(blockParts[0]!);\n } else {\n parts.push(blockParts.map((part) => `(${part})`).join(' AND '));\n }\n }\n\n // Add date filter if present\n const dateFilter = translateDateFilter(ast.filters.yearFrom, ast.filters.yearTo);\n if (dateFilter) {\n parts.push(`(${dateFilter})`);\n }\n\n // Add category filter from arXiv overrides\n const arxivOverrides = ast.overrides.arxiv;\n if (arxivOverrides?.categories && arxivOverrides.categories.length > 0) {\n const categoryFilter = translateCategories(arxivOverrides.categories);\n if (categoryFilter) {\n parts.push(`(${categoryFilter})`);\n }\n }\n\n // Combine all parts with AND\n let native: string;\n if (parts.length === 0) {\n native = '';\n } else if (parts.length === 1) {\n native = parts[0]!;\n } else {\n native = parts.join(' AND ');\n }\n\n // Append ANDNOT clauses\n for (const notClause of notClauses) {\n if (native) {\n native = `${native} ${notClause}`;\n } else {\n native = notClause;\n }\n }\n\n // Collect warnings for unsupported controlled vocabulary\n // arXiv does not support any controlled vocabulary\n const warnings = collectUnsupportedVocabWarnings(ast.blocks, 'arXiv', new Set());\n\n return {\n native,\n originalAst: ast,\n provider: 'arxiv',\n ...(warnings.length > 0 ? { warnings } : {}),\n };\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"translator.js","sources":["../../../src/providers/arxiv/translator.ts"],"sourcesContent":["/**\n * arXiv Query Translator\n *\n * Translates ResolvedAST to arXiv-native query syntax.\n *\n * Field mappings:\n * - title → ti:\n * - abstract → abs:\n * - title_abstract → (ti: OR abs:) expansion\n * - author → au:\n * - all → all:\n * - keyword → not supported\n *\n * Boolean operators: AND, OR, ANDNOT (not standard NOT)\n * Date filter: submittedDate:[YYYYMMDDHHmm TO YYYYMMDDHHmm]\n * Category filter: cat:cs.AI\n */\n\nimport type { QueryBlock, FieldType, Operator, ResolvedAST } from '../../query/types.js';\nimport type { TranslatedQuery } from '../base/types.js';\nimport { collectUnsupportedVocabWarnings } from '../base/warnings.js';\n\n/**\n * Field prefix mappings for arXiv API.\n */\nconst FIELD_PREFIXES: Partial<Record<FieldType, string>> = {\n title: 'ti:',\n abstract: 'abs:',\n author: 'au:',\n all: 'all:',\n // title_abstract requires expansion, not a direct prefix\n // keyword is not supported by arXiv\n};\n\n/**\n * Get the arXiv field prefix for a DSL field type.\n * Returns null if the field requires special handling or is unsupported.\n */\nexport function translateFieldPrefix(field: FieldType): string | null {\n return FIELD_PREFIXES[field] ?? null;\n}\n\n/**\n * Wrap a term in quotes if it contains spaces (phrase search).\n */\nfunction quoteIfNeeded(term: string): string {\n return term.includes(' ') ? `\"${term}\"` : term;\n}\n\n/**\n * Translate terms with a field prefix.\n * Handles quoting of multi-word phrases.\n */\nexport function translateTerms(prefix: string, keywords: string[], operator: Operator): string {\n if (keywords.length === 0) {\n return '';\n }\n\n const translatedTerms = keywords.map((keyword) => `${prefix}${quoteIfNeeded(keyword)}`);\n\n if (translatedTerms.length === 1) {\n return translatedTerms[0]!;\n }\n\n return `(${translatedTerms.join(` ${operator} `)})`;\n}\n\n/**\n * Translate a single query block to arXiv syntax.\n * Returns an object with the main query part and optional ANDNOT clause.\n */\nfunction translateBlock(block: QueryBlock): { query: string; notClause: string | null } {\n const { field, terms, operator } = block;\n\n // arXiv only uses keywords; ignore mesh and emtree\n const keywords = terms.keywords ?? [];\n\n let query = '';\n\n if (keywords.length > 0) {\n // Handle title_abstract expansion\n if (field === 'title_abstract') {\n query = translateTitleAbstract(keywords, operator);\n } else {\n // Get field prefix\n const prefix = translateFieldPrefix(field);\n if (prefix !== null) {\n query = translateTerms(prefix, keywords, operator);\n }\n }\n }\n\n // Translate exclude terms\n const notClause = terms.exclude\n ? translateExcludeTerms(terms.exclude, field)\n : null;\n\n return { query, notClause };\n}\n\n/**\n * Expand title_abstract to (ti: OR abs:) for each keyword.\n */\nfunction translateTitleAbstract(keywords: string[], operator: Operator): string {\n if (keywords.length === 0) {\n return '';\n }\n\n // Each keyword expands to (ti:keyword OR abs:keyword)\n const expandedTerms = keywords.map((keyword) => {\n const quoted = quoteIfNeeded(keyword);\n return `(ti:${quoted} OR abs:${quoted})`;\n });\n\n if (expandedTerms.length === 1) {\n return expandedTerms[0]!;\n }\n\n return `(${expandedTerms.join(` ${operator} `)})`;\n}\n\n/**\n * Translate exclude terms to ANDNOT clause.\n * arXiv uses ANDNOT instead of NOT.\n */\nfunction translateExcludeTerms(\n exclude: string[],\n field: FieldType\n): string | null {\n if (exclude.length === 0) {\n return null;\n }\n\n // Handle title_abstract expansion\n if (field === 'title_abstract') {\n const expandedTerms = exclude.map((term) => {\n const quoted = quoteIfNeeded(term);\n return `(ti:${quoted} OR abs:${quoted})`;\n });\n if (expandedTerms.length === 1) {\n return `ANDNOT (${expandedTerms[0]})`;\n }\n return `ANDNOT (${expandedTerms.join(' OR ')})`;\n }\n\n // Get field prefix\n const prefix = translateFieldPrefix(field);\n if (prefix === null) {\n // Unsupported field\n return null;\n }\n\n const translatedTerms = exclude.map((term) => `${prefix}${quoteIfNeeded(term)}`);\n\n if (translatedTerms.length === 1) {\n return `ANDNOT ${translatedTerms[0]}`;\n }\n return `ANDNOT (${translatedTerms.join(' OR ')})`;\n}\n\n/**\n * Translate date filter to arXiv submittedDate range.\n * Format: submittedDate:[YYYYMMDDHHmm TO YYYYMMDDHHmm]\n * Note: arXiv API does not support wildcards (*), so we use concrete dates:\n * - Start: 1991 (arXiv's founding year)\n * - End: current year + 1 (to include all future submissions)\n */\nfunction translateDateFilter(yearFrom?: number, yearTo?: number): string {\n if (yearFrom === undefined && yearTo === undefined) {\n return '';\n }\n\n // arXiv was founded in 1991, use as default start\n const fromDate = yearFrom !== undefined ? `${yearFrom}01010000` : '199101010000';\n // Use next year as default end to include all current submissions\n const defaultEndYear = new Date().getFullYear() + 1;\n const toDate = yearTo !== undefined ? `${yearTo}12312359` : `${defaultEndYear}12312359`;\n\n return `submittedDate:[${fromDate} TO ${toDate}]`;\n}\n\n/**\n * Translate arXiv category filter.\n */\nfunction translateCategories(categories: string[]): string {\n if (categories.length === 0) {\n return '';\n }\n\n const catTerms = categories.map((cat) => `cat:${cat}`);\n\n if (catTerms.length === 1) {\n return catTerms[0]!;\n }\n\n return `(${catTerms.join(' OR ')})`;\n}\n\n/**\n * Translate a ResolvedAST to arXiv-native syntax.\n */\nexport function translateQuery(resolved: ResolvedAST): TranslatedQuery {\n const parts: string[] = [];\n const notClauses: string[] = [];\n\n // Translate all blocks (AND'd together)\n const blockResults = resolved.blocks.map(translateBlock);\n const blockParts = blockResults.map((r) => r.query).filter((part) => part !== '');\n const blockNotClauses = blockResults\n .map((r) => r.notClause)\n .filter((s): s is string => s !== null);\n\n notClauses.push(...blockNotClauses);\n\n if (blockParts.length > 0) {\n if (blockParts.length === 1) {\n parts.push(blockParts[0]!);\n } else {\n parts.push(blockParts.map((part) => `(${part})`).join(' AND '));\n }\n }\n\n // Add date filter if present\n const dateFilter = translateDateFilter(resolved.filters.yearFrom, resolved.filters.yearTo);\n if (dateFilter) {\n parts.push(`(${dateFilter})`);\n }\n\n // Add category filter from resolved filters (was in overrides)\n if (resolved.filters.categories && resolved.filters.categories.length > 0) {\n const categoryFilter = translateCategories(resolved.filters.categories);\n if (categoryFilter) {\n parts.push(`(${categoryFilter})`);\n }\n }\n\n // Combine all parts with AND\n let native: string;\n if (parts.length === 0) {\n native = '';\n } else if (parts.length === 1) {\n native = parts[0]!;\n } else {\n native = parts.join(' AND ');\n }\n\n // Append ANDNOT clauses\n for (const notClause of notClauses) {\n if (native) {\n native = `${native} ${notClause}`;\n } else {\n native = notClause;\n }\n }\n\n // Collect warnings for unsupported controlled vocabulary\n // arXiv does not support any controlled vocabulary\n const warnings = collectUnsupportedVocabWarnings(resolved.blocks, 'arXiv', new Set());\n\n return {\n native,\n provider: 'arxiv',\n ...(warnings.length > 0 ? { warnings } : {}),\n };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Provides the foundation for implementing database providers.
|
|
5
5
|
*/
|
|
6
|
-
export type { ProviderName, Author, Article, TranslatedQuery, SearchOptions, Provider, ProviderError, RateLimitError, AuthError, QueryAST, ProviderErrorCode, SearchState, SearchResumeResult, } from './types';
|
|
6
|
+
export type { ProviderName, Author, Article, TranslatedQuery, SearchOptions, Provider, ProviderError, RateLimitError, AuthError, QueryAST, ResolvedAST, ProviderErrorCode, SearchState, SearchResumeResult, } from './types';
|
|
7
7
|
export { createProviderError, isProviderError, isRateLimitError, isAuthError, } from './types';
|
|
8
8
|
export { BaseProvider, serializeState, deserializeState } from './provider';
|
|
9
9
|
export type { BaseProviderConfig } from './provider';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/base/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,YAAY,EACV,YAAY,EACZ,MAAM,EACN,OAAO,EACP,eAAe,EACf,aAAa,EACb,QAAQ,EACR,aAAa,EACb,cAAc,EACd,SAAS,EACT,QAAQ,EACR,iBAAiB,EACjB,WAAW,EACX,kBAAkB,GACnB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,WAAW,GACZ,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC5E,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAGrD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,YAAY,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGzD,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACtF,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGlD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,YAAY,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/base/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,YAAY,EACV,YAAY,EACZ,MAAM,EACN,OAAO,EACP,eAAe,EACf,aAAa,EACb,QAAQ,EACR,aAAa,EACb,cAAc,EACd,SAAS,EACT,QAAQ,EACR,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,kBAAkB,GACnB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,WAAW,GACZ,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC5E,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAGrD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,YAAY,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGzD,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACtF,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGlD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,YAAY,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BaseProvider, BaseProviderConfig } from './provider';
|
|
2
|
-
import { ProviderName, Article, TranslatedQuery, SearchOptions,
|
|
2
|
+
import { ProviderName, Article, TranslatedQuery, SearchOptions, ResolvedAST, ProviderError, SearchState, SearchResumeResult, ConnectionTestResult } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* Configuration options for MockProvider.
|
|
5
5
|
*/
|
|
@@ -42,7 +42,7 @@ export declare class MockProvider extends BaseProvider {
|
|
|
42
42
|
constructor(options?: MockProviderOptions);
|
|
43
43
|
search(_query: TranslatedQuery, options?: SearchOptions): AsyncIterable<Article>;
|
|
44
44
|
count(_query: TranslatedQuery): Promise<number>;
|
|
45
|
-
translateQuery(
|
|
45
|
+
translateQuery(_resolved: ResolvedAST): TranslatedQuery;
|
|
46
46
|
testConnection(): Promise<ConnectionTestResult>;
|
|
47
47
|
/**
|
|
48
48
|
* Update the articles to return.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mock-provider.d.ts","sourceRoot":"","sources":["../../../src/providers/base/mock-provider.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,KAAK,EACV,YAAY,EACZ,OAAO,EACP,eAAe,EACf,aAAa,EACb,
|
|
1
|
+
{"version":3,"file":"mock-provider.d.ts","sourceRoot":"","sources":["../../../src/providers/base/mock-provider.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,KAAK,EACV,YAAY,EACZ,OAAO,EACP,eAAe,EACf,aAAa,EACb,WAAW,EACX,aAAa,EACb,WAAW,EACX,kBAAkB,EAClB,oBAAoB,EACrB,MAAM,SAAS,CAAC;AAEjB;;GAEG;AACH,MAAM,WAAW,mBAAoB,SAAQ,kBAAkB;IAC7D,2BAA2B;IAC3B,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,+CAA+C;IAC/C,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,sDAAsD;IACtD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+BAA+B;IAC/B,WAAW,CAAC,EAAE,aAAa,CAAC;IAC5B,wCAAwC;IACxC,eAAe,CAAC,EAAE,kBAAkB,CAAC;CACtC;AAwBD;;;;;;;;;GASG;AACH,qBAAa,YAAa,SAAQ,YAAY;IAC5C,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,OAAO,CAAC,YAAY,CAAY;IAChC,OAAO,CAAC,uBAAuB,CAAkB;IACjD,OAAO,CAAC,gBAAgB,CAAU;IAClC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,kBAAkB,CAA4B;IACtD,OAAO,CAAC,qBAAqB,CAAqB;IAClD,OAAO,CAAC,qBAAqB,CAAK;gBAEtB,OAAO,GAAE,mBAAwB;IAqBtC,MAAM,CACX,MAAM,EAAE,eAAe,EACvB,OAAO,CAAC,EAAE,aAAa,GACtB,aAAa,CAAC,OAAO,CAAC;IA8BnB,KAAK,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;IAUrD,cAAc,CAAC,SAAS,EAAE,WAAW,GAAG,eAAe;IAMjD,cAAc,IAAI,OAAO,CAAC,oBAAoB,CAAC;IAIrD;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,IAAI;IAOtC;;OAEG;IACH,cAAc,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,GAAG,IAAI;IAIjD;;OAEG;IACH,mBAAmB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAI1C;;OAEG;IACH,cAAc,IAAI,WAAW,GAAG,IAAI;IAIpC;;OAEG;IACI,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,aAAa,CAAC,OAAO,CAAC;IAsC/D;;OAEG;IACG,aAAa,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAIrE;;OAEG;IACH,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI;IAIpD,OAAO,CAAC,KAAK;CAGd"}
|
|
@@ -33,12 +33,6 @@ class MockProvider extends BaseProvider {
|
|
|
33
33
|
this.mockArticles = options.articles ?? [...DEFAULT_ARTICLES];
|
|
34
34
|
this.translatedQueryResponse = options.translatedQuery ?? {
|
|
35
35
|
native: "mock query",
|
|
36
|
-
originalAst: {
|
|
37
|
-
name: "mock-query",
|
|
38
|
-
blocks: [],
|
|
39
|
-
filters: {},
|
|
40
|
-
overrides: {}
|
|
41
|
-
},
|
|
42
36
|
provider: this.name
|
|
43
37
|
};
|
|
44
38
|
this.connectionStatus = options.connectionStatus ?? true;
|
|
@@ -79,10 +73,9 @@ class MockProvider extends BaseProvider {
|
|
|
79
73
|
}
|
|
80
74
|
return this.mockArticles.length;
|
|
81
75
|
}
|
|
82
|
-
translateQuery(
|
|
76
|
+
translateQuery(_resolved) {
|
|
83
77
|
return {
|
|
84
|
-
...this.translatedQueryResponse
|
|
85
|
-
originalAst: ast
|
|
78
|
+
...this.translatedQueryResponse
|
|
86
79
|
};
|
|
87
80
|
}
|
|
88
81
|
async testConnection() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mock-provider.js","sources":["../../../src/providers/base/mock-provider.ts"],"sourcesContent":["/**\n * Mock provider for testing.\n *\n * Provides configurable responses for testing search orchestration\n * and other components that depend on providers.\n */\n\nimport { BaseProvider } from './provider';\nimport type { BaseProviderConfig } from './provider';\nimport type {\n ProviderName,\n Article,\n TranslatedQuery,\n SearchOptions,\n
|
|
1
|
+
{"version":3,"file":"mock-provider.js","sources":["../../../src/providers/base/mock-provider.ts"],"sourcesContent":["/**\n * Mock provider for testing.\n *\n * Provides configurable responses for testing search orchestration\n * and other components that depend on providers.\n */\n\nimport { BaseProvider } from './provider';\nimport type { BaseProviderConfig } from './provider';\nimport type {\n ProviderName,\n Article,\n TranslatedQuery,\n SearchOptions,\n ResolvedAST,\n ProviderError,\n SearchState,\n SearchResumeResult,\n ConnectionTestResult,\n} from './types';\n\n/**\n * Configuration options for MockProvider.\n */\nexport interface MockProviderOptions extends BaseProviderConfig {\n /** Provider name to use */\n name?: ProviderName;\n /** Articles to return from search */\n articles?: Article[];\n /** Pre-configured translated query response */\n translatedQuery?: TranslatedQuery;\n /** Connection status to return from testConnection */\n connectionStatus?: boolean;\n /** Delay in ms before returning search results */\n searchDelay?: number;\n /** Error to throw on search */\n searchError?: ProviderError;\n /** State validation result to return */\n stateValidation?: SearchResumeResult;\n}\n\n/**\n * Default mock articles.\n */\nconst DEFAULT_ARTICLES: Article[] = [\n {\n doi: '10.1234/mock-article-1',\n title: 'Mock Article 1',\n authors: [{ family: 'Mock', given: 'Author' }],\n source: 'pubmed',\n retrievedAt: new Date().toISOString(),\n abstract: 'This is a mock article for testing purposes.',\n },\n {\n doi: '10.1234/mock-article-2',\n title: 'Mock Article 2',\n authors: [{ family: 'Test', given: 'Researcher' }],\n source: 'pubmed',\n retrievedAt: new Date().toISOString(),\n abstract: 'Another mock article for testing.',\n },\n];\n\n/**\n * Mock provider for testing.\n *\n * Allows configuring:\n * - Articles to return from search\n * - Translated query response\n * - Connection status\n * - Search delay (for simulating network latency)\n * - Search errors (for testing error handling)\n */\nexport class MockProvider extends BaseProvider {\n readonly name: ProviderName;\n private mockArticles: Article[];\n private translatedQueryResponse: TranslatedQuery;\n private connectionStatus: boolean;\n private searchDelay: number;\n private searchError: ProviderError | null;\n private currentSearchState: SearchState | null = null;\n private stateValidationResult: SearchResumeResult;\n private currentRetrievedCount = 0;\n\n constructor(options: MockProviderOptions = {}) {\n super(options);\n\n this.name = options.name ?? 'pubmed';\n this.mockArticles = options.articles ?? [...DEFAULT_ARTICLES];\n this.translatedQueryResponse = options.translatedQuery ?? {\n native: 'mock query',\n provider: this.name,\n };\n this.connectionStatus = options.connectionStatus ?? true;\n this.searchDelay = options.searchDelay ?? 0;\n this.searchError = options.searchError ?? null;\n this.stateValidationResult = options.stateValidation ?? { valid: true };\n\n // Update articles source to match provider name\n this.mockArticles = this.mockArticles.map((article) => ({\n ...article,\n source: this.name,\n }));\n }\n\n async *search(\n _query: TranslatedQuery,\n options?: SearchOptions\n ): AsyncIterable<Article> {\n // Throw configured error if set\n if (this.searchError !== null) {\n throw this.searchError;\n }\n\n // Simulate network delay\n if (this.searchDelay > 0) {\n await this.delay(this.searchDelay);\n }\n\n // Determine how many articles to yield\n const maxResults = options?.maxResults ?? this.mockArticles.length;\n let count = 0;\n\n for (const article of this.mockArticles) {\n if (count >= maxResults) {\n break;\n }\n\n // Check for abort signal\n if (options?.signal?.aborted) {\n break;\n }\n\n yield article;\n count++;\n }\n }\n\n async count(_query: TranslatedQuery): Promise<number> {\n if (this.searchError !== null) {\n throw this.searchError;\n }\n if (this.searchDelay > 0) {\n await this.delay(this.searchDelay);\n }\n return this.mockArticles.length;\n }\n\n translateQuery(_resolved: ResolvedAST): TranslatedQuery {\n return {\n ...this.translatedQueryResponse,\n };\n }\n\n async testConnection(): Promise<ConnectionTestResult> {\n return this.connectionStatus ? { ok: true } : { ok: false, error: 'Connection test failed' };\n }\n\n /**\n * Update the articles to return.\n */\n setArticles(articles: Article[]): void {\n this.mockArticles = articles.map((article) => ({\n ...article,\n source: this.name,\n }));\n }\n\n /**\n * Set the error to throw on search.\n */\n setSearchError(error: ProviderError | null): void {\n this.searchError = error;\n }\n\n /**\n * Set the connection status.\n */\n setConnectionStatus(status: boolean): void {\n this.connectionStatus = status;\n }\n\n /**\n * Get current search state for session persistence.\n */\n getSearchState(): SearchState | null {\n return this.currentSearchState;\n }\n\n /**\n * Resume search from saved state.\n */\n async *resumeSearch(state: SearchState): AsyncIterable<Article> {\n // Extract offset from provider state\n const providerState = state.providerState as { offset?: number } | undefined;\n const offset = providerState?.offset ?? state.retrievedCount;\n\n // Throw configured error if set\n if (this.searchError !== null) {\n throw this.searchError;\n }\n\n // Simulate network delay\n if (this.searchDelay > 0) {\n await this.delay(this.searchDelay);\n }\n\n // Update current state\n this.currentSearchState = {\n ...state,\n lastUpdated: new Date(),\n };\n this.currentRetrievedCount = offset;\n\n // Yield remaining articles starting from offset\n for (let i = offset; i < this.mockArticles.length; i++) {\n const article = this.mockArticles[i];\n if (article) {\n this.currentRetrievedCount++;\n this.currentSearchState = {\n ...this.currentSearchState,\n retrievedCount: this.currentRetrievedCount,\n lastUpdated: new Date(),\n providerState: { offset: this.currentRetrievedCount },\n };\n yield article;\n }\n }\n }\n\n /**\n * Validate if state is still valid for resuming.\n */\n async validateState(_state: SearchState): Promise<SearchResumeResult> {\n return this.stateValidationResult;\n }\n\n /**\n * Set the state validation result.\n */\n setStateValidation(result: SearchResumeResult): void {\n this.stateValidationResult = result;\n }\n\n private delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RateLimiter } from './rate-limiter';
|
|
2
|
-
import { Provider, ProviderName, Article, TranslatedQuery, SearchOptions,
|
|
2
|
+
import { Provider, ProviderName, Article, TranslatedQuery, SearchOptions, ResolvedAST, SearchState, SearchResumeResult, ConnectionTestResult } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* Configuration options for BaseProvider.
|
|
5
5
|
*/
|
|
@@ -41,9 +41,9 @@ export declare abstract class BaseProvider implements Provider {
|
|
|
41
41
|
*/
|
|
42
42
|
abstract count(query: TranslatedQuery): Promise<number>;
|
|
43
43
|
/**
|
|
44
|
-
* Convert
|
|
44
|
+
* Convert ResolvedAST to database-native syntax.
|
|
45
45
|
*/
|
|
46
|
-
abstract translateQuery(
|
|
46
|
+
abstract translateQuery(resolved: ResolvedAST): TranslatedQuery;
|
|
47
47
|
/**
|
|
48
48
|
* Verify API access and credentials.
|
|
49
49
|
* Returns { ok: true } on success, { ok: false, error: string } on failure.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/providers/base/provider.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EACV,QAAQ,EACR,YAAY,EACZ,OAAO,EACP,eAAe,EACf,aAAa,EACb,
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/providers/base/provider.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EACV,QAAQ,EACR,YAAY,EACZ,OAAO,EACP,eAAe,EACf,aAAa,EACb,WAAW,EAEX,WAAW,EACX,kBAAkB,EAClB,oBAAoB,EACrB,MAAM,SAAS,CAAC;AAGjB;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,qCAAqC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iCAAiC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAUD;;;;;;;GAOG;AACH,8BAAsB,YAAa,YAAW,QAAQ;IACpD,+BAA+B;IAC/B,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAErC,4BAA4B;IAC5B,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAE5C,2BAA2B;IAC3B,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,kBAAkB,CAAC,CAAC;gBAE5C,MAAM,GAAE,kBAAuB;IAc3C;;OAEG;IACH,QAAQ,CAAC,MAAM,CACb,KAAK,EAAE,eAAe,EACtB,OAAO,CAAC,EAAE,aAAa,GACtB,aAAa,CAAC,OAAO,CAAC;IAEzB;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;IAEvD;;OAEG;IACH,QAAQ,CAAC,cAAc,CAAC,QAAQ,EAAE,WAAW,GAAG,eAAe;IAE/D;;;;OAIG;IACH,QAAQ,CAAC,cAAc,IAAI,OAAO,CAAC,oBAAoB,CAAC;IAExD;;;OAGG;IACH,QAAQ,CAAC,cAAc,IAAI,WAAW,GAAG,IAAI;IAE7C;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,aAAa,CAAC,OAAO,CAAC;IAEjE;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAEvE;;;OAGG;IACH,SAAS,CAAC,eAAe,CACvB,KAAK,EAAE,eAAe,EACtB,YAAY,EAAE,MAAM,EACpB,cAAc,EAAE,MAAM,GACrB,WAAW;IAUd;;;;;;;OAOG;cACa,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAqC9D;;OAEG;IACH,OAAO,CAAC,WAAW;IASnB;;OAEG;IACH,OAAO,CAAC,KAAK;CAGd;AAcD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAUzD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAU1D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.js","sources":["../../../src/providers/base/provider.ts"],"sourcesContent":["/**\n * Abstract base class for database providers.\n */\n\nimport { RateLimiter } from './rate-limiter';\nimport type {\n Provider,\n ProviderName,\n Article,\n TranslatedQuery,\n SearchOptions,\n
|
|
1
|
+
{"version":3,"file":"provider.js","sources":["../../../src/providers/base/provider.ts"],"sourcesContent":["/**\n * Abstract base class for database providers.\n */\n\nimport { RateLimiter } from './rate-limiter';\nimport type {\n Provider,\n ProviderName,\n Article,\n TranslatedQuery,\n SearchOptions,\n ResolvedAST,\n ProviderError,\n SearchState,\n SearchResumeResult,\n ConnectionTestResult,\n} from './types';\nimport { isProviderError, isRateLimitError } from './types';\n\n/**\n * Configuration options for BaseProvider.\n */\nexport interface BaseProviderConfig {\n /** Requests per second rate limit */\n rateLimit?: number;\n /** Request timeout in milliseconds */\n timeout?: number;\n /** Number of retry attempts */\n retries?: number;\n /** Initial backoff time in ms for exponential backoff */\n initialBackoff?: number;\n /** Maximum backoff time in ms */\n maxBackoff?: number;\n}\n\nconst DEFAULT_CONFIG: Required<BaseProviderConfig> = {\n rateLimit: 3,\n timeout: 30000,\n retries: 3,\n initialBackoff: 1000,\n maxBackoff: 60000,\n};\n\n/**\n * Abstract base class for database providers.\n *\n * Provides common infrastructure:\n * - Rate limiting\n * - Configuration management\n * - Retry logic (implemented in subclass)\n */\nexport abstract class BaseProvider implements Provider {\n /** Provider name identifier */\n abstract readonly name: ProviderName;\n\n /** Rate limiter instance */\n protected readonly rateLimiter: RateLimiter;\n\n /** Merged configuration */\n protected readonly config: Required<BaseProviderConfig>;\n\n constructor(config: BaseProviderConfig = {}) {\n this.config = {\n ...DEFAULT_CONFIG,\n ...config,\n };\n\n this.rateLimiter = new RateLimiter({\n tokensPerSecond: this.config.rateLimit,\n burstSize: this.config.rateLimit,\n initialBackoff: this.config.initialBackoff,\n maxBackoff: this.config.maxBackoff,\n });\n }\n\n /**\n * Execute search and return results as async iterable (streaming).\n */\n abstract search(\n query: TranslatedQuery,\n options?: SearchOptions\n ): AsyncIterable<Article>;\n\n /**\n * Get total hit count for a query without downloading results.\n * Used for count-only mode during query refinement.\n */\n abstract count(query: TranslatedQuery): Promise<number>;\n\n /**\n * Convert ResolvedAST to database-native syntax.\n */\n abstract translateQuery(resolved: ResolvedAST): TranslatedQuery;\n\n /**\n * Verify API access and credentials.\n * Returns { ok: true } on success, { ok: false, error: string } on failure.\n * Does not throw.\n */\n abstract testConnection(): Promise<ConnectionTestResult>;\n\n /**\n * Get the current search state for session persistence.\n * Returns null if no search is in progress.\n */\n abstract getSearchState(): SearchState | null;\n\n /**\n * Resume a search from a saved state.\n * Continues yielding articles from where the previous search left off.\n */\n abstract resumeSearch(state: SearchState): AsyncIterable<Article>;\n\n /**\n * Validate if a saved state is still valid for resuming.\n * Some providers (e.g., PubMed) have server-side state that can expire.\n */\n abstract validateState(state: SearchState): Promise<SearchResumeResult>;\n\n /**\n * Create a base SearchState with common fields.\n * Subclasses can extend this with provider-specific state.\n */\n protected createBaseState(\n query: TranslatedQuery,\n totalResults: number,\n retrievedCount: number\n ): SearchState {\n return {\n provider: this.name,\n query,\n totalResults,\n retrievedCount,\n lastUpdated: new Date(),\n };\n }\n\n /**\n * Execute a function with retry logic.\n *\n * Retries on network errors and server errors.\n * Does not retry on auth errors.\n * Uses exponential backoff between retries.\n * Respects rate limit error's retryAfter if provided.\n */\n protected async withRetry<T>(fn: () => Promise<T>): Promise<T> {\n let lastError: ProviderError | Error | undefined;\n let currentBackoff = this.config.initialBackoff;\n\n for (let attempt = 0; attempt <= this.config.retries; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error as ProviderError | Error;\n\n // Check if we should retry\n if (!this.shouldRetry(error)) {\n throw error;\n }\n\n // If we've exhausted retries, throw\n if (attempt >= this.config.retries) {\n throw error;\n }\n\n // Calculate wait time\n let waitTime: number;\n if (isRateLimitError(error) && 'retryAfter' in error && typeof error.retryAfter === 'number') {\n waitTime = error.retryAfter;\n } else {\n waitTime = currentBackoff;\n currentBackoff = Math.min(currentBackoff * 2, this.config.maxBackoff);\n }\n\n await this.sleep(waitTime);\n }\n }\n\n // This should never be reached, but TypeScript needs it\n throw lastError;\n }\n\n /**\n * Determine if an error should trigger a retry.\n */\n private shouldRetry(error: unknown): boolean {\n if (isProviderError(error)) {\n return error.retryable;\n }\n\n // Treat unknown errors as non-retryable\n return false;\n }\n\n /**\n * Sleep for specified milliseconds.\n */\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n\n/**\n * Serialized search state for JSON storage.\n */\ninterface SerializedSearchState {\n provider: string;\n query: TranslatedQuery;\n totalResults: number;\n retrievedCount: number;\n lastUpdated: string; // ISO 8601 string\n providerState?: unknown;\n}\n\n/**\n * Serialize a SearchState to a JSON string.\n * Handles Date conversion to ISO 8601 string.\n */\nexport function serializeState(state: SearchState): string {\n const serialized: SerializedSearchState = {\n provider: state.provider,\n query: state.query,\n totalResults: state.totalResults,\n retrievedCount: state.retrievedCount,\n lastUpdated: state.lastUpdated.toISOString(),\n providerState: state.providerState,\n };\n return JSON.stringify(serialized);\n}\n\n/**\n * Deserialize a JSON string to a SearchState.\n * Handles Date conversion from ISO 8601 string.\n */\nexport function deserializeState(json: string): SearchState {\n const parsed = JSON.parse(json) as SerializedSearchState;\n return {\n provider: parsed.provider as SearchState['provider'],\n query: parsed.query,\n totalResults: parsed.totalResults,\n retrievedCount: parsed.retrievedCount,\n lastUpdated: new Date(parsed.lastUpdated),\n providerState: parsed.providerState,\n };\n}\n"],"names":[],"mappings":";;AAmCA,MAAM,iBAA+C;AAAA,EACnD,WAAW;AAAA,EACX,SAAS;AAAA,EACT,SAAS;AAAA,EACT,gBAAgB;AAAA,EAChB,YAAY;AACd;AAUO,MAAe,aAAiC;AAAA;AAAA,EAKlC;AAAA;AAAA,EAGA;AAAA,EAEnB,YAAY,SAA6B,IAAI;AAC3C,SAAK,SAAS;AAAA,MACZ,GAAG;AAAA,MACH,GAAG;AAAA,IAAA;AAGL,SAAK,cAAc,IAAI,YAAY;AAAA,MACjC,iBAAiB,KAAK,OAAO;AAAA,MAC7B,WAAW,KAAK,OAAO;AAAA,MACvB,gBAAgB,KAAK,OAAO;AAAA,MAC5B,YAAY,KAAK,OAAO;AAAA,IAAA,CACzB;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAkDU,gBACR,OACA,cACA,gBACa;AACb,WAAO;AAAA,MACL,UAAU,KAAK;AAAA,MACf;AAAA,MACA;AAAA,MACA;AAAA,MACA,iCAAiB,KAAA;AAAA,IAAK;AAAA,EAE1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAgB,UAAa,IAAkC;AAC7D,QAAI;AACJ,QAAI,iBAAiB,KAAK,OAAO;AAEjC,aAAS,UAAU,GAAG,WAAW,KAAK,OAAO,SAAS,WAAW;AAC/D,UAAI;AACF,eAAO,MAAM,GAAA;AAAA,MACf,SAAS,OAAO;AACd,oBAAY;AAGZ,YAAI,CAAC,KAAK,YAAY,KAAK,GAAG;AAC5B,gBAAM;AAAA,QACR;AAGA,YAAI,WAAW,KAAK,OAAO,SAAS;AAClC,gBAAM;AAAA,QACR;AAGA,YAAI;AACJ,YAAI,iBAAiB,KAAK,KAAK,gBAAgB,SAAS,OAAO,MAAM,eAAe,UAAU;AAC5F,qBAAW,MAAM;AAAA,QACnB,OAAO;AACL,qBAAW;AACX,2BAAiB,KAAK,IAAI,iBAAiB,GAAG,KAAK,OAAO,UAAU;AAAA,QACtE;AAEA,cAAM,KAAK,MAAM,QAAQ;AAAA,MAC3B;AAAA,IACF;AAGA,UAAM;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAY,OAAyB;AAC3C,QAAI,gBAAgB,KAAK,GAAG;AAC1B,aAAO,MAAM;AAAA,IACf;AAGA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,MAAM,IAA2B;AACvC,WAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AAAA,EACzD;AACF;AAkBO,SAAS,eAAe,OAA4B;AACzD,QAAM,aAAoC;AAAA,IACxC,UAAU,MAAM;AAAA,IAChB,OAAO,MAAM;AAAA,IACb,cAAc,MAAM;AAAA,IACpB,gBAAgB,MAAM;AAAA,IACtB,aAAa,MAAM,YAAY,YAAA;AAAA,IAC/B,eAAe,MAAM;AAAA,EAAA;AAEvB,SAAO,KAAK,UAAU,UAAU;AAClC;AAMO,SAAS,iBAAiB,MAA2B;AAC1D,QAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,SAAO;AAAA,IACL,UAAU,OAAO;AAAA,IACjB,OAAO,OAAO;AAAA,IACd,cAAc,OAAO;AAAA,IACrB,gBAAgB,OAAO;AAAA,IACvB,aAAa,IAAI,KAAK,OAAO,WAAW;AAAA,IACxC,eAAe,OAAO;AAAA,EAAA;AAE1B;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { QueryAST } from '../../query/types.js';
|
|
2
|
-
export type { QueryAST };
|
|
1
|
+
import { QueryAST, ResolvedAST } from '../../query/types.js';
|
|
2
|
+
export type { QueryAST, ResolvedAST };
|
|
3
3
|
/**
|
|
4
4
|
* Supported provider names.
|
|
5
5
|
*/
|
|
@@ -45,8 +45,6 @@ export interface Article {
|
|
|
45
45
|
export interface TranslatedQuery {
|
|
46
46
|
/** Database-native query string */
|
|
47
47
|
native: string;
|
|
48
|
-
/** Reference to original AST (optional for direct query mode) */
|
|
49
|
-
originalAst?: QueryAST;
|
|
50
48
|
/** Provider that produced this translation */
|
|
51
49
|
provider: ProviderName;
|
|
52
50
|
/** Warnings about unsupported controlled vocabulary */
|
|
@@ -93,9 +91,9 @@ export interface Provider {
|
|
|
93
91
|
*/
|
|
94
92
|
count(query: TranslatedQuery): Promise<number>;
|
|
95
93
|
/**
|
|
96
|
-
* Convert
|
|
94
|
+
* Convert ResolvedAST to database-native syntax.
|
|
97
95
|
*/
|
|
98
|
-
translateQuery(
|
|
96
|
+
translateQuery(resolved: ResolvedAST): TranslatedQuery;
|
|
99
97
|
/**
|
|
100
98
|
* Verify API access and credentials.
|
|
101
99
|
* Returns { ok: true } on success, { ok: false, error: string } on failure.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/providers/base/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/providers/base/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sources":["../../../src/providers/base/types.ts"],"sourcesContent":["/**\n * Provider base types for the search-hub CLI tool.\n * These types define the common interface for all database providers.\n */\n\nimport type { QueryAST } from '../../query/types.js';\n\n// Re-export QueryAST for convenience\nexport type { QueryAST };\n\n/**\n * Supported provider names.\n */\nexport type ProviderName =\n | 'pubmed'\n | 'eric'\n | 'arxiv'\n | 'scopus'\n | 'wos'\n | 'embase';\n\n/**\n * Author information.\n */\nexport interface Author {\n /** Last name (required) */\n family: string;\n /** First name */\n given?: string;\n /** Institutional affiliation */\n affiliation?: string;\n /** ORCID identifier */\n orcid?: string;\n}\n\n/**\n * Represents a single search result from any database.\n * At least one identifier (doi, pmid, arxivId, scopusId, ericId) is required.\n */\nexport interface Article {\n // Identifiers (at least one required)\n doi?: string;\n pmid?: string;\n arxivId?: string;\n scopusId?: string;\n ericId?: string;\n\n // Required fields\n title: string;\n authors: Author[];\n source: ProviderName;\n retrievedAt: string; // ISO 8601 format\n\n // Optional fields\n abstract?: string;\n publicationDate?: string;\n journal?: string;\n volume?: string;\n issue?: string;\n pages?: string;\n rawResponse?: unknown;\n}\n\n/**\n * Result of translating a query to database-native syntax.\n */\nexport interface TranslatedQuery {\n /** Database-native query string */\n native: string;\n /**
|
|
1
|
+
{"version":3,"file":"types.js","sources":["../../../src/providers/base/types.ts"],"sourcesContent":["/**\n * Provider base types for the search-hub CLI tool.\n * These types define the common interface for all database providers.\n */\n\nimport type { QueryAST, ResolvedAST } from '../../query/types.js';\n\n// Re-export QueryAST and ResolvedAST for convenience\nexport type { QueryAST, ResolvedAST };\n\n/**\n * Supported provider names.\n */\nexport type ProviderName =\n | 'pubmed'\n | 'eric'\n | 'arxiv'\n | 'scopus'\n | 'wos'\n | 'embase';\n\n/**\n * Author information.\n */\nexport interface Author {\n /** Last name (required) */\n family: string;\n /** First name */\n given?: string;\n /** Institutional affiliation */\n affiliation?: string;\n /** ORCID identifier */\n orcid?: string;\n}\n\n/**\n * Represents a single search result from any database.\n * At least one identifier (doi, pmid, arxivId, scopusId, ericId) is required.\n */\nexport interface Article {\n // Identifiers (at least one required)\n doi?: string;\n pmid?: string;\n arxivId?: string;\n scopusId?: string;\n ericId?: string;\n\n // Required fields\n title: string;\n authors: Author[];\n source: ProviderName;\n retrievedAt: string; // ISO 8601 format\n\n // Optional fields\n abstract?: string;\n publicationDate?: string;\n journal?: string;\n volume?: string;\n issue?: string;\n pages?: string;\n rawResponse?: unknown;\n}\n\n/**\n * Result of translating a query to database-native syntax.\n */\nexport interface TranslatedQuery {\n /** Database-native query string */\n native: string;\n /** Provider that produced this translation */\n provider: ProviderName;\n /** Warnings about unsupported controlled vocabulary */\n warnings?: string[];\n}\n\n/**\n * Search options for controlling query execution.\n */\nexport interface SearchOptions {\n /** Maximum number of results to retrieve */\n maxResults?: number;\n /** Number of results per page/request */\n pageSize?: number;\n /** Date range filter */\n dateRange?: {\n start: string;\n end: string;\n };\n /** AbortSignal for cancellation */\n signal?: AbortSignal;\n}\n\n/**\n * Result of a connection test.\n */\nexport interface ConnectionTestResult {\n /** Whether the connection succeeded */\n ok: boolean;\n /** Error message if the connection failed */\n error?: string;\n}\n\n/**\n * Core provider interface that all database providers must implement.\n */\nexport interface Provider {\n /** Provider name identifier */\n readonly name: ProviderName;\n\n /**\n * Execute search and return results as async iterable (streaming).\n */\n search(\n query: TranslatedQuery,\n options?: SearchOptions\n ): AsyncIterable<Article>;\n\n /**\n * Get total hit count for a query without downloading results.\n * Used for count-only mode during query refinement.\n */\n count(query: TranslatedQuery): Promise<number>;\n\n /**\n * Convert ResolvedAST to database-native syntax.\n */\n translateQuery(resolved: ResolvedAST): TranslatedQuery;\n\n /**\n * Verify API access and credentials.\n * Returns { ok: true } on success, { ok: false, error: string } on failure.\n * Does not throw.\n */\n testConnection(): Promise<ConnectionTestResult>;\n}\n\n/**\n * Error codes used by providers.\n */\nexport type ProviderErrorCode =\n | 'PROVIDER_NOT_AVAILABLE'\n | 'API_KEY_MISSING'\n | 'API_KEY_INVALID'\n | 'ACCESS_DENIED'\n | 'RATE_LIMIT_EXCEEDED'\n | 'NETWORK_ERROR'\n | 'PARSE_ERROR'\n | 'QUERY_ERROR'\n | 'SERVER_ERROR'\n | 'TIMEOUT';\n\n/**\n * Base error type for provider errors.\n */\nexport interface ProviderError {\n code: ProviderErrorCode;\n message: string;\n provider: ProviderName;\n retryable: boolean;\n cause?: unknown;\n}\n\n/**\n * Rate limit exceeded error with retry information.\n */\nexport interface RateLimitError extends ProviderError {\n code: 'RATE_LIMIT_EXCEEDED';\n /** Time to wait before retrying (in milliseconds) */\n retryAfter?: number;\n}\n\n/**\n * Authentication/authorization error.\n */\nexport interface AuthError extends ProviderError {\n code: 'API_KEY_MISSING' | 'API_KEY_INVALID' | 'ACCESS_DENIED';\n}\n\n/**\n * Create a provider error.\n */\nexport function createProviderError(\n code: ProviderErrorCode,\n message: string,\n provider: ProviderName,\n options?: { retryable?: boolean; cause?: unknown }\n): ProviderError {\n return {\n code,\n message,\n provider,\n retryable: options?.retryable ?? false,\n cause: options?.cause,\n };\n}\n\n/**\n * Check if an error is a provider error.\n */\nexport function isProviderError(error: unknown): error is ProviderError {\n if (typeof error !== 'object' || error === null) {\n return false;\n }\n const e = error as Record<string, unknown>;\n return (\n typeof e['code'] === 'string' &&\n typeof e['message'] === 'string' &&\n typeof e['provider'] === 'string' &&\n typeof e['retryable'] === 'boolean'\n );\n}\n\n/**\n * Check if an error is a rate limit error.\n */\nexport function isRateLimitError(error: unknown): error is RateLimitError {\n return isProviderError(error) && error.code === 'RATE_LIMIT_EXCEEDED';\n}\n\n/**\n * Check if an error is an auth error.\n */\nexport function isAuthError(error: unknown): error is AuthError {\n return (\n isProviderError(error) &&\n (error.code === 'API_KEY_MISSING' || error.code === 'API_KEY_INVALID' || error.code === 'ACCESS_DENIED')\n );\n}\n\n/**\n * Represents the current state of a search for session persistence.\n * Used to resume searches after interruption or application restart.\n */\nexport interface SearchState {\n /** Provider that produced this state */\n provider: ProviderName;\n /** The query being executed */\n query: TranslatedQuery;\n /** Total number of results available */\n totalResults: number;\n /** Number of results retrieved so far */\n retrievedCount: number;\n /** When the state was last updated */\n lastUpdated: Date;\n /** Provider-specific state (e.g., PubMed webenv/querykey, or offset for other providers) */\n providerState?: unknown;\n}\n\n/**\n * Result of validating a search state for resume.\n */\nexport interface SearchResumeResult {\n /** Whether the state is valid for resuming */\n valid: boolean;\n /** Reason if the state is invalid */\n reason?: string;\n}\n"],"names":[],"mappings":"AAqLO,SAAS,oBACd,MACA,SACA,UACA,SACe;AACf,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW,SAAS,aAAa;AAAA,IACjC,OAAO,SAAS;AAAA,EAAA;AAEpB;AAKO,SAAS,gBAAgB,OAAwC;AACtE,MAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,WAAO;AAAA,EACT;AACA,QAAM,IAAI;AACV,SACE,OAAO,EAAE,MAAM,MAAM,YACrB,OAAO,EAAE,SAAS,MAAM,YACxB,OAAO,EAAE,UAAU,MAAM,YACzB,OAAO,EAAE,WAAW,MAAM;AAE9B;AAKO,SAAS,iBAAiB,OAAyC;AACxE,SAAO,gBAAgB,KAAK,KAAK,MAAM,SAAS;AAClD;AAKO,SAAS,YAAY,OAAoC;AAC9D,SACE,gBAAgB,KAAK,MACpB,MAAM,SAAS,qBAAqB,MAAM,SAAS,qBAAqB,MAAM,SAAS;AAE5F;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BaseProvider } from '../base/provider';
|
|
2
|
-
import { Article, TranslatedQuery, SearchOptions,
|
|
2
|
+
import { Article, TranslatedQuery, SearchOptions, ResolvedAST, SearchState, SearchResumeResult, ConnectionTestResult } from '../base/types';
|
|
3
3
|
import { ERICSearchOptions } from './client';
|
|
4
4
|
import { ERICSearchResult } from './parser';
|
|
5
5
|
import { ERICConfig } from './types';
|
|
@@ -30,9 +30,9 @@ export declare class ERICProvider extends BaseProvider {
|
|
|
30
30
|
private currentRetrievedCount;
|
|
31
31
|
constructor(config?: ERICProviderOptions);
|
|
32
32
|
/**
|
|
33
|
-
* Translate a
|
|
33
|
+
* Translate a ResolvedAST to ERIC-native query syntax.
|
|
34
34
|
*/
|
|
35
|
-
translateQuery(
|
|
35
|
+
translateQuery(resolved: ResolvedAST): TranslatedQuery;
|
|
36
36
|
/**
|
|
37
37
|
* Get total hit count for a query without downloading results.
|
|
38
38
|
* Uses a minimal search with rows=0 to get only the total count.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/providers/eric/provider.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAA2B,MAAM,kBAAkB,CAAC;AACzE,OAAO,KAAK,EACV,OAAO,EACP,eAAe,EACf,aAAa,EACb,
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/providers/eric/provider.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAA2B,MAAM,kBAAkB,CAAC;AACzE,OAAO,KAAK,EACV,OAAO,EACP,eAAe,EACf,aAAa,EACb,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,oBAAoB,EACrB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAc,KAAK,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEjD,OAAO,KAAK,EAAE,UAAU,EAAqB,MAAM,SAAS,CAAC;AAQ7D;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAC/E;AAED;;GAEG;AACH,MAAM,WAAW,mBAAoB,SAAQ,UAAU;IACrD,yDAAyD;IACzD,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;GAGG;AACH,qBAAa,YAAa,SAAQ,YAAY;IAC5C,QAAQ,CAAC,IAAI,EAAG,MAAM,CAAU;IAEhC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAGlC,OAAO,CAAC,YAAY,CAAgC;IACpD,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,mBAAmB,CAAK;IAChC,OAAO,CAAC,qBAAqB,CAAK;gBAEtB,MAAM,GAAE,mBAAwB;IAsB5C;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,WAAW,GAAG,eAAe;IAItD;;;OAGG;IACG,KAAK,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;IAQpD;;OAEG;IACI,MAAM,CACX,KAAK,EAAE,eAAe,EACtB,OAAO,GAAE,aAAkB,GAC1B,aAAa,CAAC,OAAO,CAAC;IA0DzB;;;OAGG;IACG,cAAc,IAAI,OAAO,CAAC,oBAAoB,CAAC;IAarD;;OAEG;IACH,cAAc,IAAI,WAAW,GAAG,IAAI;IAoBpC;;OAEG;IACI,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,aAAa,CAAC,OAAO,CAAC;IAkD/D;;;OAGG;IACG,aAAa,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,kBAAkB,CAAC;CAKtE"}
|
|
@@ -31,10 +31,10 @@ class ERICProvider extends BaseProvider {
|
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
|
-
* Translate a
|
|
34
|
+
* Translate a ResolvedAST to ERIC-native query syntax.
|
|
35
35
|
*/
|
|
36
|
-
translateQuery(
|
|
37
|
-
return translateQuery(
|
|
36
|
+
translateQuery(resolved) {
|
|
37
|
+
return translateQuery(resolved);
|
|
38
38
|
}
|
|
39
39
|
/**
|
|
40
40
|
* Get total hit count for a query without downloading results.
|