annosearch 0.0.1
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 +97 -0
- package/dist/package.json +31 -0
- package/dist/src/AnnoSearch.js +65 -0
- package/dist/src/AnnoSearch.js.map +1 -0
- package/dist/src/delete.js +31 -0
- package/dist/src/delete.js.map +1 -0
- package/dist/src/errors.js +37 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/iiif.js +39 -0
- package/dist/src/iiif.js.map +1 -0
- package/dist/src/index.js +181 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/init.js +51 -0
- package/dist/src/init.js.map +1 -0
- package/dist/src/load.js +150 -0
- package/dist/src/load.js.map +1 -0
- package/dist/src/logger.js +31 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/src/quickwit.js +19 -0
- package/dist/src/quickwit.js.map +1 -0
- package/dist/src/search.js +40 -0
- package/dist/src/search.js.map +1 -0
- package/dist/src/server.js +91 -0
- package/dist/src/server.js.map +1 -0
- package/dist/src/utils.js +118 -0
- package/dist/src/utils.js.map +1 -0
- package/package.json +31 -0
- package/src/AnnoSearch.ts +68 -0
- package/src/delete.ts +17 -0
- package/src/errors.ts +33 -0
- package/src/iiif.ts +76 -0
- package/src/index-config.yaml +15 -0
- package/src/index.ts +153 -0
- package/src/init.ts +39 -0
- package/src/load.ts +126 -0
- package/src/logger.ts +30 -0
- package/src/quickwit.ts +14 -0
- package/src/search.ts +28 -0
- package/src/server.ts +56 -0
- package/src/utils.ts +103 -0
- package/tsconfig.json +14 -0
package/dist/src/load.js
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.loadIndex = loadIndex;
|
|
13
|
+
const maniiifest_1 = require("maniiifest");
|
|
14
|
+
const utils_1 = require("./utils");
|
|
15
|
+
const errors_1 = require("./errors");
|
|
16
|
+
const quickwit_1 = require("./quickwit");
|
|
17
|
+
const contentType = 'application/x-ndjson';
|
|
18
|
+
const quickwitClient = (0, quickwit_1.createClient)(contentType);
|
|
19
|
+
function processAnnotations(indexId, parser) {
|
|
20
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
21
|
+
let currentParser = parser;
|
|
22
|
+
while (currentParser) {
|
|
23
|
+
const annotations = Array.from(currentParser.iterateAnnotationPageAnnotation());
|
|
24
|
+
if (annotations.length > 0) {
|
|
25
|
+
const payload = (0, utils_1.createJsonl)(annotations);
|
|
26
|
+
const response = yield quickwitClient.post(`${indexId}/ingest`, payload);
|
|
27
|
+
if (!response.data) {
|
|
28
|
+
throw new errors_1.AnnoSearchValidationError('No response data received from Quickwit');
|
|
29
|
+
}
|
|
30
|
+
// Check if the response is successful and has data
|
|
31
|
+
if (response.status === 200 && response.data) {
|
|
32
|
+
// Print a line of '+' symbols based on the batch length
|
|
33
|
+
console.log('|' + '+'.repeat(annotations.length) + '|');
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
throw new errors_1.AnnoSearchValidationError('Failed to ingest data: Invalid response from Quickwit');
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// Move to the next annotation page if available
|
|
40
|
+
const nextPageUrl = currentParser.getAnnotationPage().next;
|
|
41
|
+
if (nextPageUrl) {
|
|
42
|
+
const jsonData = yield (0, utils_1.fetchJson)(nextPageUrl);
|
|
43
|
+
if (!jsonData) {
|
|
44
|
+
throw new errors_1.AnnoSearchValidationError('No JSON data returned from fetchJson');
|
|
45
|
+
}
|
|
46
|
+
currentParser = new maniiifest_1.Maniiifest(jsonData, "AnnotationPage");
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
currentParser = null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function processAnnotationPageRef(indexId, annotationPageUrl) {
|
|
55
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
56
|
+
const jsonData = yield (0, utils_1.fetchJson)(annotationPageUrl);
|
|
57
|
+
const parser = new maniiifest_1.Maniiifest(jsonData, "AnnotationPage");
|
|
58
|
+
yield processAnnotations(indexId, parser);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
function processAnnotationPage(indexId, page) {
|
|
62
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
63
|
+
const parser = new maniiifest_1.Maniiifest(page, "AnnotationPage");
|
|
64
|
+
yield processAnnotations(indexId, parser);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
function processManifest(indexId, manifestUrl) {
|
|
68
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
69
|
+
const jsonData = yield (0, utils_1.fetchJson)(manifestUrl);
|
|
70
|
+
const parser = new maniiifest_1.Maniiifest(jsonData);
|
|
71
|
+
const type = parser.getSpecificationType();
|
|
72
|
+
if (type !== 'Manifest') {
|
|
73
|
+
throw new errors_1.AnnoSearchParseError('Specification should be a Manifest');
|
|
74
|
+
}
|
|
75
|
+
const annotationPages = parser.iterateManifestCanvasW3cAnnotationPage();
|
|
76
|
+
for (const page of annotationPages) {
|
|
77
|
+
if (page.items) {
|
|
78
|
+
yield processAnnotationPage(indexId, page);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
yield processAnnotationPageRef(indexId, page.id);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
function processCollection(indexId, collectionUrl) {
|
|
87
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
88
|
+
const jsonData = yield (0, utils_1.fetchJson)(collectionUrl);
|
|
89
|
+
const parser = new maniiifest_1.Maniiifest(jsonData);
|
|
90
|
+
const type = parser.getSpecificationType();
|
|
91
|
+
if (type !== 'Collection') {
|
|
92
|
+
throw new errors_1.AnnoSearchParseError('Specification should be a Collection');
|
|
93
|
+
}
|
|
94
|
+
const manifests = parser.iterateCollectionManifest();
|
|
95
|
+
// need to remove count later once tested
|
|
96
|
+
let count = 0;
|
|
97
|
+
for (const item of manifests) {
|
|
98
|
+
if (count >= 1)
|
|
99
|
+
break;
|
|
100
|
+
const manifestRef = new maniiifest_1.Maniiifest(item);
|
|
101
|
+
const manifestId = manifestRef.getManifestId();
|
|
102
|
+
if (manifestId) {
|
|
103
|
+
yield processManifest(indexId, manifestId);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
throw new errors_1.AnnoSearchValidationError('Manifest ID is null');
|
|
107
|
+
}
|
|
108
|
+
count++;
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
function processAnnotationCollection(indexId, annotationCollectionUrl) {
|
|
113
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
114
|
+
const jsonData = yield (0, utils_1.fetchJson)(annotationCollectionUrl);
|
|
115
|
+
const parser = new maniiifest_1.Maniiifest(jsonData, "AnnotationCollection");
|
|
116
|
+
const type = parser.getAnnotationCollectionType();
|
|
117
|
+
if (type !== 'AnnotationCollection') {
|
|
118
|
+
throw new errors_1.AnnoSearchParseError('Should be a W3C annotation collection');
|
|
119
|
+
}
|
|
120
|
+
const firstPage = parser.getAnnotationCollectionFirst();
|
|
121
|
+
if (typeof firstPage === 'string') { // means it is a URI
|
|
122
|
+
yield processAnnotationPageRef(indexId, firstPage);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
yield processAnnotationPage(indexId, firstPage);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
function loadIndex(indexId, uri, type) {
|
|
130
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
131
|
+
if (!indexId.trim() || !uri.trim()) {
|
|
132
|
+
throw new errors_1.AnnoSearchValidationError('Invalid index or uri parameter');
|
|
133
|
+
}
|
|
134
|
+
console.log(`Loading ${type} from ${uri} into index ${indexId}`);
|
|
135
|
+
switch (type) {
|
|
136
|
+
case 'Manifest':
|
|
137
|
+
yield processManifest(indexId, uri);
|
|
138
|
+
break;
|
|
139
|
+
case 'Collection':
|
|
140
|
+
yield processCollection(indexId, uri);
|
|
141
|
+
break;
|
|
142
|
+
case 'AnnotationCollection':
|
|
143
|
+
yield processAnnotationCollection(indexId, uri);
|
|
144
|
+
break;
|
|
145
|
+
default:
|
|
146
|
+
throw new errors_1.AnnoSearchValidationError('unsupported type');
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=load.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load.js","sourceRoot":"","sources":["../../src/load.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// FILE: logger.ts
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.logErrorHandler = logErrorHandler;
|
|
8
|
+
const utils_1 = require("./utils");
|
|
9
|
+
const pino_1 = __importDefault(require("pino"));
|
|
10
|
+
// Define the logger configuration
|
|
11
|
+
const logger = (0, pino_1.default)({
|
|
12
|
+
level: 'info', // Default log level
|
|
13
|
+
timestamp: pino_1.default.stdTimeFunctions.isoTime, // ISO time format for easier readability and consistency
|
|
14
|
+
formatters: {
|
|
15
|
+
level: (label) => ({ level: label }), // Single-line style for log levels
|
|
16
|
+
},
|
|
17
|
+
messageKey: 'msg', // Key for the log message
|
|
18
|
+
transport: {
|
|
19
|
+
target: 'pino-pretty', // Use pino-pretty to format logs in a readable way
|
|
20
|
+
options: {
|
|
21
|
+
colorize: true, // Adds color to the console output
|
|
22
|
+
singleLine: true, // Ensures logs appear in a single line for easier parsing and reading
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
// Middleware to log other errors using handleWebError
|
|
27
|
+
function logErrorHandler(error, req, res, next) {
|
|
28
|
+
(0, utils_1.handleWebError)(error, res);
|
|
29
|
+
}
|
|
30
|
+
exports.default = logger;
|
|
31
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/logger.ts"],"names":[],"mappings":";AAAA,kBAAkB;;;;;AAyBlB,0CAEC;AAxBD,mCAAyC;AACzC,gDAAwB;AAExB,kCAAkC;AAClC,MAAM,MAAM,GAAG,IAAA,cAAI,EAAC;IAChB,KAAK,EAAE,MAAM,EAAG,oBAAoB;IACpC,SAAS,EAAE,cAAI,CAAC,gBAAgB,CAAC,OAAO,EAAG,yDAAyD;IACpG,UAAU,EAAE;QACR,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAG,mCAAmC;KAC7E;IACD,UAAU,EAAE,KAAK,EAAG,0BAA0B;IAC9C,SAAS,EAAE;QACP,MAAM,EAAE,aAAa,EAAG,mDAAmD;QAC3E,OAAO,EAAE;YACL,QAAQ,EAAE,IAAI,EAAG,mCAAmC;YACpD,UAAU,EAAE,IAAI,EAAG,sEAAsE;SAC5F;KACJ;CACJ,CAAC,CAAC;AAGH,sDAAsD;AACtD,SAAgB,eAAe,CAAC,KAAU,EAAE,GAAY,EAAE,GAAa,EAAE,IAAkB;IACvF,IAAA,sBAAc,EAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAC/B,CAAC;AAED,kBAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createClient = createClient;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const baseURL = process.env.QUICKWIT_BASE_URL || 'http://localhost:7280/api/v1/';
|
|
9
|
+
const timeout = parseInt(process.env.QUICKWIT_TIMEOUT || '5000', 10);
|
|
10
|
+
function createClient(contentType) {
|
|
11
|
+
return axios_1.default.create({
|
|
12
|
+
baseURL: baseURL,
|
|
13
|
+
headers: {
|
|
14
|
+
'Content-Type': contentType,
|
|
15
|
+
},
|
|
16
|
+
timeout: timeout, // 5 seconds timeout
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=quickwit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quickwit.js","sourceRoot":"","sources":["../../src/quickwit.ts"],"names":[],"mappings":";;;;;AAKA,oCAQC;AAbD,kDAA0B;AAE1B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,+BAA+B,CAAC;AACjF,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;AAErE,SAAgB,YAAY,CAAC,WAA6E;IACtG,OAAO,eAAK,CAAC,MAAM,CAAC;QAChB,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE;YACL,cAAc,EAAE,WAAW;SAC9B;QACD,OAAO,EAAE,OAAO,EAAE,oBAAoB;KACzC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.searchIndex = searchIndex;
|
|
13
|
+
const quickwit_1 = require("./quickwit");
|
|
14
|
+
const errors_1 = require("./errors");
|
|
15
|
+
const iiif_1 = require("./iiif");
|
|
16
|
+
const contentType = 'application/json';
|
|
17
|
+
const quickwitClient = (0, quickwit_1.createClient)(contentType);
|
|
18
|
+
function searchIndex(indexId, query, maxHits, page, searchUrl) {
|
|
19
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
20
|
+
const startOffset = page * maxHits;
|
|
21
|
+
if (startOffset < 0) {
|
|
22
|
+
throw new errors_1.AnnoSearchValidationError('Invalid paging');
|
|
23
|
+
}
|
|
24
|
+
if (!query.trim()) {
|
|
25
|
+
throw new errors_1.AnnoSearchValidationError('Missing query parameter');
|
|
26
|
+
}
|
|
27
|
+
const response = yield quickwitClient.post(`${indexId}/search`, {
|
|
28
|
+
query: query,
|
|
29
|
+
max_hits: maxHits,
|
|
30
|
+
start_offset: startOffset,
|
|
31
|
+
});
|
|
32
|
+
if (response.status === 200 && response.data) {
|
|
33
|
+
return (0, iiif_1.makeSearchResponse)(indexId, response.data, searchUrl, query, maxHits, page);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
throw new errors_1.AnnoSearchValidationError('Failed to delete index');
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/search.ts"],"names":[],"mappings":";;;;;;;;;;;AAQA,kCAmBC;AA3BD,yCAA0C;AAC1C,qCAAqD;AACrD,iCAA4C;AAE5C,MAAM,WAAW,GAAG,kBAAkB,CAAC;AACvC,MAAM,cAAc,GAAG,IAAA,uBAAY,EAAC,WAAW,CAAC,CAAC;AAGjD,SAAsB,WAAW,CAAC,OAAe,EAAE,KAAa,EAAE,OAAe,EAAE,IAAY,EAAE,SAAiB;;QAC9G,MAAM,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC;QACnC,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;YAClB,MAAM,IAAI,kCAAyB,CAAC,gBAAgB,CAAC,CAAC;QAC1D,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;YAChB,MAAM,IAAI,kCAAyB,CAAC,yBAAyB,CAAC,CAAC;QACnE,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,GAAG,OAAO,SAAS,EAAE;YAC5D,KAAK,EAAE,KAAK;YACZ,QAAQ,EAAE,OAAO;YACjB,YAAY,EAAE,WAAW;SAC5B,CAAC,CAAC;QAEH,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC3C,OAAO,IAAA,yBAAkB,EAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QACvF,CAAC;aAAM,CAAC;YACJ,MAAM,IAAI,kCAAyB,CAAC,wBAAwB,CAAC,CAAC;QAClE,CAAC;IACL,CAAC;CAAA"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// FILE: server.ts
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
20
|
+
if (mod && mod.__esModule) return mod;
|
|
21
|
+
var result = {};
|
|
22
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
23
|
+
__setModuleDefault(result, mod);
|
|
24
|
+
return result;
|
|
25
|
+
};
|
|
26
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
27
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
28
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
29
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
30
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
31
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
32
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.serve = serve;
|
|
40
|
+
const express_1 = __importDefault(require("express"));
|
|
41
|
+
const package_json_1 = require("../package.json"); // Import version from package.json
|
|
42
|
+
const utils_1 = require("./utils");
|
|
43
|
+
const logger_1 = __importStar(require("./logger")); // Import shared logger
|
|
44
|
+
const pino_http_1 = __importDefault(require("pino-http"));
|
|
45
|
+
const errors_1 = require("./errors");
|
|
46
|
+
function serve(client) {
|
|
47
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
48
|
+
const app = (0, express_1.default)();
|
|
49
|
+
const port = client.getPort();
|
|
50
|
+
const host = client.getHost();
|
|
51
|
+
app.use((0, pino_http_1.default)({ logger: logger_1.default }));
|
|
52
|
+
app.get('/:index/search', (req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
53
|
+
try {
|
|
54
|
+
const { index = '' } = req.params;
|
|
55
|
+
const { q = '', page = '0' } = req.query;
|
|
56
|
+
const pageNumber = parseInt(page);
|
|
57
|
+
const maxHits = client.getMaxHits();
|
|
58
|
+
// Validate the 'page' parameter
|
|
59
|
+
if (!Number.isInteger(pageNumber) || pageNumber < 0) {
|
|
60
|
+
throw new errors_1.AnnoSearchValidationError('Invalid "page" parameter: must be a non-negative integer');
|
|
61
|
+
}
|
|
62
|
+
// Validate the 'maxHits' parameter
|
|
63
|
+
if (!Number.isInteger(maxHits) || maxHits <= 0) {
|
|
64
|
+
throw new errors_1.AnnoSearchValidationError('Invalid "maxHits" configuration: must be a positive integer');
|
|
65
|
+
}
|
|
66
|
+
const results = yield client.searchIndex(index, q, pageNumber);
|
|
67
|
+
res.json(results);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
(0, utils_1.handleWebError)(error, res);
|
|
71
|
+
}
|
|
72
|
+
}));
|
|
73
|
+
app.get('/version', (req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
74
|
+
try {
|
|
75
|
+
res.json({ version: package_json_1.version });
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
(0, utils_1.handleWebError)(error, res);
|
|
79
|
+
}
|
|
80
|
+
}));
|
|
81
|
+
app.use((req, res, next) => {
|
|
82
|
+
const error = new errors_1.AnnoSearchNotFoundError(`404 Not Found: ${req.method} ${req.originalUrl}`);
|
|
83
|
+
next(error);
|
|
84
|
+
});
|
|
85
|
+
app.use(logger_1.logErrorHandler);
|
|
86
|
+
app.listen(port, host, () => {
|
|
87
|
+
console.log(`Server is running on http://${host}:${port}`);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":";AAAA,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUlB,sBA6CC;AArDD,sDAA8B;AAE9B,kDAA0C,CAAC,mCAAmC;AAC9E,mCAAyC;AACzC,mDAAmD,CAAC,uBAAuB;AAC3E,0DAAiC;AACjC,qCAA8E;AAE9E,SAAsB,KAAK,CAAC,MAAkB;;QAC1C,MAAM,GAAG,GAAG,IAAA,iBAAO,GAAE,CAAC;QACtB,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,EAAE,CAAA;QAE7B,GAAG,CAAC,GAAG,CAAC,IAAA,mBAAQ,EAAC,EAAE,MAAM,EAAN,gBAAM,EAAE,CAAC,CAAC,CAAC;QAE9B,GAAG,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAO,GAAG,EAAE,GAAG,EAAE,EAAE;YACzC,IAAI,CAAC;gBACD,MAAM,EAAE,KAAK,GAAG,EAAE,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC;gBAClC,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,IAAI,GAAG,GAAG,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC;gBACzC,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAc,CAAC,CAAC;gBAC5C,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;gBACpC,gCAAgC;gBAChC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;oBAClD,MAAM,IAAI,kCAAyB,CAAC,0DAA0D,CAAC,CAAC;gBACpG,CAAC;gBACD,mCAAmC;gBACnC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;oBAC7C,MAAM,IAAI,kCAAyB,CAAC,6DAA6D,CAAC,CAAC;gBACvG,CAAC;gBACD,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,KAAe,EAAE,CAAW,EAAE,UAAU,CAAC,CAAC;gBACnF,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACtB,CAAC;YAAC,OAAO,KAAU,EAAE,CAAC;gBAClB,IAAA,sBAAc,EAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAC/B,CAAC;QACL,CAAC,CAAA,CAAC,CAAC;QAEH,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,CAAO,GAAG,EAAE,GAAG,EAAE,EAAE;YACnC,IAAI,CAAC;gBACD,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAP,sBAAO,EAAE,CAAC,CAAC;YAC1B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,IAAA,sBAAc,EAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAC/B,CAAC;QACL,CAAC,CAAA,CAAC,CAAC;QAEH,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;YACvB,MAAM,KAAK,GAAG,IAAI,gCAAuB,CAAC,kBAAkB,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;YAC7F,IAAI,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,GAAG,CAAC,wBAAe,CAAC,CAAC;QAEzB,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE;YACxB,OAAO,CAAC,GAAG,CAAC,+BAA+B,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC;QAC/D,CAAC,CAAC,CAAC;IACP,CAAC;CAAA"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.printJson = printJson;
|
|
16
|
+
exports.logError = logError;
|
|
17
|
+
exports.handleError = handleError;
|
|
18
|
+
exports.handleWebError = handleWebError;
|
|
19
|
+
exports.fetchJson = fetchJson;
|
|
20
|
+
exports.createJsonl = createJsonl;
|
|
21
|
+
const axios_1 = __importDefault(require("axios"));
|
|
22
|
+
const errors_1 = require("./errors");
|
|
23
|
+
const axios_2 = require("axios");
|
|
24
|
+
const logger_1 = __importDefault(require("./logger")); // Import Pino logger instance
|
|
25
|
+
// Function to print the results
|
|
26
|
+
function printJson(results) {
|
|
27
|
+
console.log(JSON.stringify(results, null, 2)); // Print the returned JSON
|
|
28
|
+
}
|
|
29
|
+
// Function to log errors in a single-line JSON format
|
|
30
|
+
function logError(error, context = 'General') {
|
|
31
|
+
const errorObject = { context, error: {} };
|
|
32
|
+
if (error instanceof errors_1.AnnoSearchNetworkError || error instanceof axios_2.AxiosError) {
|
|
33
|
+
errorObject.error = { type: 'Network Error', message: error.message };
|
|
34
|
+
}
|
|
35
|
+
else if (error instanceof errors_1.AnnoSearchNotFoundError) {
|
|
36
|
+
errorObject.error = { type: 'Not Found Error', message: error.message };
|
|
37
|
+
}
|
|
38
|
+
else if (error instanceof errors_1.AnnoSearchParseError) {
|
|
39
|
+
errorObject.error = { type: 'Parse Error', message: error.message };
|
|
40
|
+
}
|
|
41
|
+
else if (error instanceof errors_1.AnnoSearchValidationError) {
|
|
42
|
+
errorObject.error = { type: 'Validation Error', message: error.message };
|
|
43
|
+
}
|
|
44
|
+
else if (error instanceof errors_1.AnnoSearchError) {
|
|
45
|
+
errorObject.error = { type: 'General AnnoSearch Error', message: error.message };
|
|
46
|
+
}
|
|
47
|
+
else if (error instanceof Error) {
|
|
48
|
+
errorObject.error = { type: 'General Error', message: error.message };
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
errorObject.error = { type: 'Unknown Error', details: JSON.stringify(error) };
|
|
52
|
+
}
|
|
53
|
+
logger_1.default.error(JSON.stringify(errorObject)); // Log as a single-line JSON object
|
|
54
|
+
}
|
|
55
|
+
// Function to handle errors
|
|
56
|
+
function handleError(error) {
|
|
57
|
+
logError(error);
|
|
58
|
+
throw error;
|
|
59
|
+
}
|
|
60
|
+
function handleWebError(error, res) {
|
|
61
|
+
var _a;
|
|
62
|
+
logError(error, 'Web Request');
|
|
63
|
+
let statusCode = 500;
|
|
64
|
+
let errorMessage = 'An error occurred during processing';
|
|
65
|
+
switch (true) {
|
|
66
|
+
case error instanceof errors_1.AnnoSearchValidationError:
|
|
67
|
+
statusCode = 400;
|
|
68
|
+
errorMessage = `Validation error: ${error.message}`;
|
|
69
|
+
break;
|
|
70
|
+
case error instanceof axios_2.AxiosError:
|
|
71
|
+
statusCode = ((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) || 503;
|
|
72
|
+
errorMessage = `Network error: ${error.message}`;
|
|
73
|
+
break;
|
|
74
|
+
case error instanceof errors_1.AnnoSearchNetworkError:
|
|
75
|
+
statusCode = 503;
|
|
76
|
+
errorMessage = `Network error: ${error.message}`;
|
|
77
|
+
break;
|
|
78
|
+
case error instanceof errors_1.AnnoSearchNotFoundError:
|
|
79
|
+
statusCode = 404;
|
|
80
|
+
errorMessage = `Not found: ${error.message}`;
|
|
81
|
+
break;
|
|
82
|
+
case error instanceof errors_1.AnnoSearchParseError:
|
|
83
|
+
statusCode = 400;
|
|
84
|
+
errorMessage = `Parse error: ${error.message}`;
|
|
85
|
+
break;
|
|
86
|
+
case error instanceof errors_1.AnnoSearchError:
|
|
87
|
+
statusCode = 400;
|
|
88
|
+
errorMessage = `Application error: ${error.message}`;
|
|
89
|
+
break;
|
|
90
|
+
case error instanceof Error:
|
|
91
|
+
statusCode = 500;
|
|
92
|
+
errorMessage = `General error: ${error.message}`;
|
|
93
|
+
break;
|
|
94
|
+
default:
|
|
95
|
+
errorMessage = error.message || 'Internal Server Error';
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
res.status(statusCode).json({ error: errorMessage });
|
|
99
|
+
}
|
|
100
|
+
// Function to fetch JSON data
|
|
101
|
+
function fetchJson(url) {
|
|
102
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
103
|
+
const response = yield axios_1.default.get(url);
|
|
104
|
+
if (!response.data) {
|
|
105
|
+
throw new errors_1.AnnoSearchValidationError('No JSON data returned');
|
|
106
|
+
}
|
|
107
|
+
return response.data;
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
function createJsonl(data) {
|
|
111
|
+
if (Array.isArray(data)) {
|
|
112
|
+
return data.map(item => JSON.stringify(item)).join('\n') + '\n';
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
return JSON.stringify(data) + '\n';
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAQA,8BAEC;AAGD,4BAoBC;AAKD,kCAGC;AAED,wCAwCC;AAID,8BAOC;AAED,kCAMC;AAtGD,kDAA0B;AAE1B,qCAA6I;AAC7I,iCAAmC;AACnC,sDAA8B,CAAC,8BAA8B;AAG7D,gCAAgC;AAChC,SAAgB,SAAS,CAAC,OAAgB;IACtC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,0BAA0B;AAC7E,CAAC;AAED,sDAAsD;AACtD,SAAgB,QAAQ,CAAC,KAAc,EAAE,UAAkB,SAAS;IAChE,MAAM,WAAW,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IAE3C,IAAI,KAAK,YAAY,+BAAsB,IAAI,KAAK,YAAY,kBAAU,EAAE,CAAC;QACzE,WAAW,CAAC,KAAK,GAAG,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IAC1E,CAAC;SAAM,IAAI,KAAK,YAAY,gCAAuB,EAAE,CAAC;QAClD,WAAW,CAAC,KAAK,GAAG,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IAC5E,CAAC;SAAM,IAAI,KAAK,YAAY,6BAAoB,EAAE,CAAC;QAC/C,WAAW,CAAC,KAAK,GAAG,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IACxE,CAAC;SAAM,IAAI,KAAK,YAAY,kCAAyB,EAAE,CAAC;QACpD,WAAW,CAAC,KAAK,GAAG,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IAC7E,CAAC;SAAM,IAAI,KAAK,YAAY,wBAAe,EAAE,CAAC;QAC1C,WAAW,CAAC,KAAK,GAAG,EAAE,IAAI,EAAE,0BAA0B,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IACrF,CAAC;SAAM,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAChC,WAAW,CAAC,KAAK,GAAG,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IAC1E,CAAC;SAAM,CAAC;QACJ,WAAW,CAAC,KAAK,GAAG,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;IAClF,CAAC;IAED,gBAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,mCAAmC;AAClF,CAAC;AAID,4BAA4B;AAC5B,SAAgB,WAAW,CAAC,KAAU;IAClC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChB,MAAM,KAAK,CAAC;AAChB,CAAC;AAED,SAAgB,cAAc,CAAC,KAAU,EAAE,GAAa;;IACpD,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;IAC/B,IAAI,UAAU,GAAG,GAAG,CAAC;IACrB,IAAI,YAAY,GAAG,qCAAqC,CAAC;IAEzD,QAAQ,IAAI,EAAE,CAAC;QACX,KAAK,KAAK,YAAY,kCAAyB;YAC3C,UAAU,GAAG,GAAG,CAAC;YACjB,YAAY,GAAG,qBAAqB,KAAK,CAAC,OAAO,EAAE,CAAC;YACpD,MAAM;QACV,KAAK,KAAK,YAAY,kBAAU;YAC5B,UAAU,GAAG,CAAA,MAAA,KAAK,CAAC,QAAQ,0CAAE,MAAM,KAAI,GAAG,CAAC;YAC3C,YAAY,GAAG,kBAAkB,KAAK,CAAC,OAAO,EAAE,CAAC;YACjD,MAAM;QACV,KAAK,KAAK,YAAY,+BAAsB;YACxC,UAAU,GAAG,GAAG,CAAC;YACjB,YAAY,GAAG,kBAAkB,KAAK,CAAC,OAAO,EAAE,CAAC;YACjD,MAAM;QACV,KAAK,KAAK,YAAY,gCAAuB;YACzC,UAAU,GAAG,GAAG,CAAC;YACjB,YAAY,GAAG,cAAc,KAAK,CAAC,OAAO,EAAE,CAAC;YAC7C,MAAM;QACV,KAAK,KAAK,YAAY,6BAAoB;YACtC,UAAU,GAAG,GAAG,CAAC;YACjB,YAAY,GAAG,gBAAgB,KAAK,CAAC,OAAO,EAAE,CAAC;YAC/C,MAAM;QACV,KAAK,KAAK,YAAY,wBAAe;YACjC,UAAU,GAAG,GAAG,CAAC;YACjB,YAAY,GAAG,sBAAsB,KAAK,CAAC,OAAO,EAAE,CAAC;YACrD,MAAM;QACV,KAAK,KAAK,YAAY,KAAK;YACvB,UAAU,GAAG,GAAG,CAAC;YACjB,YAAY,GAAG,kBAAkB,KAAK,CAAC,OAAO,EAAE,CAAC;YACjD,MAAM;QACV;YACI,YAAY,GAAG,KAAK,CAAC,OAAO,IAAI,uBAAuB,CAAC;YACxD,MAAM;IACd,CAAC;IAED,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;AACzD,CAAC;AAGD,8BAA8B;AAC9B,SAAsB,SAAS,CAAC,GAAW;;QACvC,MAAM,QAAQ,GAAG,MAAM,eAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACtC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACjB,MAAM,IAAI,kCAAyB,CAAC,uBAAuB,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,QAAQ,CAAC,IAAI,CAAC;IAEzB,CAAC;CAAA;AAED,SAAgB,WAAW,CAAC,IAAyB;IACjD,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACpE,CAAC;SAAM,CAAC;QACJ,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACvC,CAAC;AACL,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "annosearch",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "tsc",
|
|
7
|
+
"start": "ts-node src/index.ts",
|
|
8
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [],
|
|
11
|
+
"author": "John P. T. Moore",
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"description": "",
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@types/express": "^5.0.0",
|
|
16
|
+
"@types/node": "^22.8.4",
|
|
17
|
+
"@types/pino": "^7.0.4",
|
|
18
|
+
"@types/yargs": "^17.0.33",
|
|
19
|
+
"maniiifest": "^1.2.9",
|
|
20
|
+
"typescript": "^5.6.3"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"axios": "^1.7.7",
|
|
24
|
+
"express": "^4.21.1",
|
|
25
|
+
"pino": "^9.5.0",
|
|
26
|
+
"pino-http": "^10.3.0",
|
|
27
|
+
"pino-pretty": "^12.1.0",
|
|
28
|
+
"yaml": "^2.6.0",
|
|
29
|
+
"yargs": "^17.7.2"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { searchIndex as searchFunction } from './search';
|
|
2
|
+
import { initIndex as initFunction } from './init';
|
|
3
|
+
import { deleteIndex as deleteFunction } from './delete';
|
|
4
|
+
import { loadIndex as loadFunction } from './load';
|
|
5
|
+
|
|
6
|
+
interface Config {
|
|
7
|
+
maxHits: number;
|
|
8
|
+
port: number;
|
|
9
|
+
host: string;
|
|
10
|
+
searchUrl: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function loadConfig(): Config {
|
|
14
|
+
return {
|
|
15
|
+
maxHits: parseInt(process.env.ANNOSEARCH_MAX_HITS || '20'),
|
|
16
|
+
port: parseInt(process.env.ANNOSEARCH_PORT || '3000'),
|
|
17
|
+
host: process.env.ANNOSEARCH_HOST || 'localhost',
|
|
18
|
+
searchUrl: process.env.ANNOSEARCH_PUBLIC_URL || 'http://localhost:3000',
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
class AnnoSearch {
|
|
23
|
+
private maxHits: number;
|
|
24
|
+
private port: number;
|
|
25
|
+
private host: string;
|
|
26
|
+
private searchUrl: string;
|
|
27
|
+
|
|
28
|
+
constructor({ maxHits, port, host, searchUrl }: Config = loadConfig()) {
|
|
29
|
+
this.maxHits = maxHits;
|
|
30
|
+
this.port = port;
|
|
31
|
+
this.host = host;
|
|
32
|
+
this.searchUrl = searchUrl;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
getHost(): string {
|
|
36
|
+
return this.host;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
getPort(): number {
|
|
40
|
+
return this.port;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
getMaxHits(): number {
|
|
44
|
+
return this.maxHits;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
getSearchUrl(): string {
|
|
48
|
+
return this.searchUrl;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async loadIndex(indexId: string, uri: string, type: string) {
|
|
52
|
+
return await loadFunction(indexId, uri, type);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async searchIndex(indexId: string, query: string, page: number) {
|
|
56
|
+
return searchFunction(indexId, query, this.maxHits, page, this.searchUrl);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async initIndex(indexId: string) {
|
|
60
|
+
return await initFunction(indexId);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async deleteIndex(indexId: string) {
|
|
64
|
+
return await deleteFunction(indexId);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export default AnnoSearch;
|
package/src/delete.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createClient } from './quickwit';
|
|
2
|
+
import { AnnoSearchValidationError } from './errors';
|
|
3
|
+
|
|
4
|
+
const contentType = 'application/json';
|
|
5
|
+
const quickwitClient = createClient(contentType);
|
|
6
|
+
|
|
7
|
+
export async function deleteIndex(indexId: string) {
|
|
8
|
+
if (!indexId.trim()) {
|
|
9
|
+
throw new AnnoSearchValidationError('Invalid index parameter');
|
|
10
|
+
}
|
|
11
|
+
const response = await quickwitClient.delete(`indexes/${indexId}`);
|
|
12
|
+
if (response.status === 200 && response.data) {
|
|
13
|
+
console.log('Index deleted successfully');
|
|
14
|
+
} else {
|
|
15
|
+
throw new AnnoSearchValidationError('Failed to delete index');
|
|
16
|
+
}
|
|
17
|
+
}
|
package/src/errors.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// errors.ts
|
|
2
|
+
|
|
3
|
+
export class AnnoSearchError extends Error {
|
|
4
|
+
constructor(message: string) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = this.constructor.name;
|
|
7
|
+
Error.captureStackTrace(this, this.constructor); // Captures the correct stack trace
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class AnnoSearchValidationError extends AnnoSearchError {
|
|
12
|
+
constructor(message = 'Invalid input data') {
|
|
13
|
+
super(message);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class AnnoSearchNetworkError extends AnnoSearchError {
|
|
18
|
+
constructor(message = 'Network error occurred') {
|
|
19
|
+
super(message);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class AnnoSearchNotFoundError extends AnnoSearchError {
|
|
24
|
+
constructor(message = 'Resource not found') {
|
|
25
|
+
super(message);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export class AnnoSearchParseError extends AnnoSearchError {
|
|
30
|
+
constructor(message = 'Error parsing data') {
|
|
31
|
+
super(message);
|
|
32
|
+
}
|
|
33
|
+
}
|