@gmod/trix 3.0.4 → 3.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +3 -1
- package/dist/index.js +51 -63
- package/dist/index.js.map +1 -1
- package/dist/package.json +1 -0
- package/dist/util.js +3 -3
- package/dist/util.js.map +1 -1
- package/esm/index.d.ts +3 -1
- package/esm/index.js +52 -63
- package/esm/index.js.map +1 -1
- package/esm/util.js +3 -3
- package/esm/util.js.map +1 -1
- package/package.json +12 -11
- package/src/index.ts +58 -72
- package/src/util.ts +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -3,10 +3,12 @@ export default class Trix {
|
|
|
3
3
|
ixxFile: GenericFilehandle;
|
|
4
4
|
ixFile: GenericFilehandle;
|
|
5
5
|
maxResults: number;
|
|
6
|
+
private decoder;
|
|
7
|
+
private indexCache?;
|
|
6
8
|
constructor(ixxFile: GenericFilehandle, ixFile: GenericFilehandle, maxResults?: number);
|
|
7
9
|
search(searchString: string, opts?: {
|
|
8
10
|
signal?: AbortSignal;
|
|
9
11
|
}): Promise<[string, string][]>;
|
|
10
12
|
private getIndex;
|
|
11
|
-
private
|
|
13
|
+
private getBuffer;
|
|
12
14
|
}
|
package/dist/index.js
CHANGED
|
@@ -20,68 +20,59 @@ class Trix {
|
|
|
20
20
|
this.ixxFile = ixxFile;
|
|
21
21
|
this.ixFile = ixFile;
|
|
22
22
|
this.maxResults = maxResults;
|
|
23
|
+
this.decoder = new TextDecoder('utf8');
|
|
23
24
|
}
|
|
24
25
|
search(searchString, opts) {
|
|
25
26
|
return __awaiter(this, void 0, void 0, function* () {
|
|
26
27
|
let resultArr = [];
|
|
27
28
|
const searchWords = searchString.split(' ');
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
// search string
|
|
56
|
-
if (word.slice(0, searchWord.length) > searchWord) {
|
|
57
|
-
done = true;
|
|
29
|
+
const firstWord = searchWords[0];
|
|
30
|
+
// validate that we have a non-empty search term
|
|
31
|
+
if (firstWord) {
|
|
32
|
+
const searchWord = firstWord.toLowerCase();
|
|
33
|
+
const res = yield this.getBuffer(searchWord, opts);
|
|
34
|
+
let { end, buffer } = res;
|
|
35
|
+
let done = false;
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
37
|
+
while (!done) {
|
|
38
|
+
const str = this.decoder.decode(buffer);
|
|
39
|
+
// slice to lastIndexOf('\n') to make sure we get complete records
|
|
40
|
+
// since the buffer fetch could get halfway into a record
|
|
41
|
+
const lines = str
|
|
42
|
+
.slice(0, str.lastIndexOf('\n'))
|
|
43
|
+
.split('\n')
|
|
44
|
+
.filter(Boolean);
|
|
45
|
+
const hits2 = [];
|
|
46
|
+
for (const line of lines) {
|
|
47
|
+
const word = line.split(' ')[0];
|
|
48
|
+
if (word.startsWith(searchWord)) {
|
|
49
|
+
hits2.push(line);
|
|
50
|
+
}
|
|
51
|
+
else if (word > searchWord) {
|
|
52
|
+
// we are done scanning if we are lexicographically greater than
|
|
53
|
+
// the search string
|
|
54
|
+
done = true;
|
|
55
|
+
}
|
|
58
56
|
}
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
const hits = hits2.flatMap(line => {
|
|
58
|
+
const [term, ...parts] = line.split(' ');
|
|
59
|
+
return parts
|
|
60
|
+
.filter(Boolean)
|
|
61
|
+
.map(elt => [term, elt.split(',')[0]]);
|
|
62
|
+
});
|
|
63
|
+
resultArr = resultArr.concat(hits);
|
|
64
|
+
// if we are done or have filled up maxResults, break
|
|
65
|
+
if (done || resultArr.length >= this.maxResults) {
|
|
66
|
+
break;
|
|
61
67
|
}
|
|
62
|
-
|
|
63
|
-
const hits = hits2.flatMap(line => {
|
|
64
|
-
const [term, ...parts] = line.split(' ');
|
|
65
|
-
return parts.map(elt => [term, elt.split(',')[0]]);
|
|
66
|
-
});
|
|
67
|
-
// if we are not done, and we haven't filled up maxResults with hits yet,
|
|
68
|
-
// then refetch
|
|
69
|
-
if (resultArr.length + hits.length < this.maxResults && !done) {
|
|
68
|
+
// fetch more data
|
|
70
69
|
const res2 = yield this.ixFile.read(CHUNK_SIZE, end, opts);
|
|
71
|
-
// early break if empty response
|
|
72
70
|
if (res2.length === 0) {
|
|
73
|
-
resultArr = resultArr.concat(hits);
|
|
74
71
|
break;
|
|
75
72
|
}
|
|
76
73
|
buffer = (0, util_ts_1.concatUint8Array)([buffer, res2]);
|
|
77
74
|
end += CHUNK_SIZE;
|
|
78
75
|
}
|
|
79
|
-
// if we have filled up the hits, or we are detected to be done via the
|
|
80
|
-
// filtering, then return
|
|
81
|
-
else if (resultArr.length + hits.length >= this.maxResults || done) {
|
|
82
|
-
resultArr = resultArr.concat(hits);
|
|
83
|
-
break;
|
|
84
|
-
}
|
|
85
76
|
}
|
|
86
77
|
// de-duplicate results based on the detail column (resultArr[1])
|
|
87
78
|
return (0, dedupe_ts_1.dedupe)(resultArr, elt => elt[1]).slice(0, this.maxResults);
|
|
@@ -89,10 +80,13 @@ class Trix {
|
|
|
89
80
|
}
|
|
90
81
|
getIndex(opts) {
|
|
91
82
|
return __awaiter(this, void 0, void 0, function* () {
|
|
83
|
+
if (this.indexCache) {
|
|
84
|
+
return this.indexCache;
|
|
85
|
+
}
|
|
92
86
|
const file = yield this.ixxFile.readFile(Object.assign({ encoding: 'utf8' }, opts));
|
|
93
|
-
|
|
87
|
+
const result = file
|
|
94
88
|
.split('\n')
|
|
95
|
-
.filter(
|
|
89
|
+
.filter(Boolean)
|
|
96
90
|
.map(line => {
|
|
97
91
|
const p = line.length - ADDRESS_SIZE;
|
|
98
92
|
const prefix = line.slice(0, p);
|
|
@@ -100,30 +94,24 @@ class Trix {
|
|
|
100
94
|
const pos = Number.parseInt(posStr, 16);
|
|
101
95
|
return [prefix, pos];
|
|
102
96
|
});
|
|
97
|
+
this.indexCache = result;
|
|
98
|
+
return result;
|
|
103
99
|
});
|
|
104
100
|
}
|
|
105
|
-
|
|
101
|
+
getBuffer(searchWord, opts) {
|
|
106
102
|
return __awaiter(this, void 0, void 0, function* () {
|
|
107
103
|
let start = 0;
|
|
108
|
-
let end =
|
|
104
|
+
let end = CHUNK_SIZE;
|
|
109
105
|
const indexes = yield this.getIndex(opts);
|
|
110
106
|
for (const [key, value] of indexes) {
|
|
111
107
|
const trimmedKey = key.slice(0, searchWord.length);
|
|
112
108
|
if (trimmedKey < searchWord) {
|
|
113
109
|
start = value;
|
|
114
|
-
end = value +
|
|
110
|
+
end = value + CHUNK_SIZE;
|
|
115
111
|
}
|
|
116
112
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if (len < 0) {
|
|
120
|
-
return undefined;
|
|
121
|
-
}
|
|
122
|
-
const buffer = yield this.ixFile.read(len, start, opts);
|
|
123
|
-
return {
|
|
124
|
-
buffer,
|
|
125
|
-
end,
|
|
126
|
-
};
|
|
113
|
+
const buffer = yield this.ixFile.read(end - start, start, opts);
|
|
114
|
+
return { buffer, end };
|
|
127
115
|
});
|
|
128
116
|
}
|
|
129
117
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,2CAAoC;AACpC,uCAA4C;AAI5C,MAAM,UAAU,GAAG,KAAK,CAAA;AAExB,4EAA4E;AAC5E,iEAAiE;AACjE,MAAM,YAAY,GAAG,EAAE,CAAA;AAEvB,MAAqB,IAAI;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,2CAAoC;AACpC,uCAA4C;AAI5C,MAAM,UAAU,GAAG,KAAK,CAAA;AAExB,4EAA4E;AAC5E,iEAAiE;AACjE,MAAM,YAAY,GAAG,EAAE,CAAA;AAEvB,MAAqB,IAAI;IAIvB,YACS,OAA0B,EAC1B,MAAyB,EACzB,aAAa,EAAE;QAFf,YAAO,GAAP,OAAO,CAAmB;QAC1B,WAAM,GAAN,MAAM,CAAmB;QACzB,eAAU,GAAV,UAAU,CAAK;QANhB,YAAO,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,CAAA;IAOtC,CAAC;IAEE,MAAM,CAAC,YAAoB,EAAE,IAA+B;;YAChE,IAAI,SAAS,GAAG,EAAwB,CAAA;YACxC,MAAM,WAAW,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YAC3C,MAAM,SAAS,GAAG,WAAW,CAAC,CAAC,CAAC,CAAA;YAEhC,gDAAgD;YAChD,IAAI,SAAS,EAAE,CAAC;gBACd,MAAM,UAAU,GAAG,SAAS,CAAC,WAAW,EAAE,CAAA;gBAC1C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;gBAElD,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,GAAG,CAAA;gBACzB,IAAI,IAAI,GAAG,KAAK,CAAA;gBAChB,uEAAuE;gBACvE,OAAO,CAAC,IAAI,EAAE,CAAC;oBACb,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;oBAEvC,kEAAkE;oBAClE,yDAAyD;oBACzD,MAAM,KAAK,GAAG,GAAG;yBACd,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;yBAC/B,KAAK,CAAC,IAAI,CAAC;yBACX,MAAM,CAAC,OAAO,CAAC,CAAA;oBAElB,MAAM,KAAK,GAAG,EAAc,CAAA;oBAC5B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;wBACzB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;wBAE/B,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;4BAChC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;wBAClB,CAAC;6BAAM,IAAI,IAAI,GAAG,UAAU,EAAE,CAAC;4BAC7B,gEAAgE;4BAChE,oBAAoB;4BACpB,IAAI,GAAG,IAAI,CAAA;wBACb,CAAC;oBACH,CAAC;oBACD,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;wBAChC,MAAM,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;wBACxC,OAAO,KAAK;6BACT,MAAM,CAAC,OAAO,CAAC;6BACf,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAqB,CAAC,CAAA;oBAC9D,CAAC,CAAC,CAAA;oBAEF,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;oBAElC,qDAAqD;oBACrD,IAAI,IAAI,IAAI,SAAS,CAAC,MAAM,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;wBAChD,MAAK;oBACP,CAAC;oBAED,kBAAkB;oBAClB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,EAAE,IAAI,CAAC,CAAA;oBAC1D,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;wBACtB,MAAK;oBACP,CAAC;oBACD,MAAM,GAAG,IAAA,0BAAgB,EAAC,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAA;oBACzC,GAAG,IAAI,UAAU,CAAA;gBACnB,CAAC;YACH,CAAC;YAED,iEAAiE;YACjE,OAAO,IAAA,kBAAM,EAAC,SAAS,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAA;QACnE,CAAC;KAAA;IAEa,QAAQ,CAAC,IAA+B;;YACpD,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;gBACpB,OAAO,IAAI,CAAC,UAAU,CAAA;YACxB,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,iBACtC,QAAQ,EAAE,MAAM,IACb,IAAI,EACP,CAAA;YACF,MAAM,MAAM,GAAG,IAAI;iBAChB,KAAK,CAAC,IAAI,CAAC;iBACX,MAAM,CAAC,OAAO,CAAC;iBACf,GAAG,CAAC,IAAI,CAAC,EAAE;gBACV,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,YAAY,CAAA;gBACpC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;gBAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;gBAC5B,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;gBACvC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAU,CAAA;YAC/B,CAAC,CAAC,CAAA;YACJ,IAAI,CAAC,UAAU,GAAG,MAAM,CAAA;YACxB,OAAO,MAAM,CAAA;QACf,CAAC;KAAA;IAEa,SAAS,CAAC,UAAkB,EAAE,IAA+B;;YACzE,IAAI,KAAK,GAAG,CAAC,CAAA;YACb,IAAI,GAAG,GAAG,UAAU,CAAA;YACpB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;YACzC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;gBACnC,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,MAAM,CAAC,CAAA;gBAClD,IAAI,UAAU,GAAG,UAAU,EAAE,CAAC;oBAC5B,KAAK,GAAG,KAAK,CAAA;oBACb,GAAG,GAAG,KAAK,GAAG,UAAU,CAAA;gBAC1B,CAAC;YACH,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,CAAA;YAC/D,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAA;QACxB,CAAC;KAAA;CACF;AA9GD,uBA8GC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type": "commonjs"}
|
package/dist/util.js
CHANGED
|
@@ -3,11 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.sum = sum;
|
|
4
4
|
exports.concatUint8Array = concatUint8Array;
|
|
5
5
|
function sum(array) {
|
|
6
|
-
let
|
|
6
|
+
let total = 0;
|
|
7
7
|
for (const entry of array) {
|
|
8
|
-
|
|
8
|
+
total += entry.length;
|
|
9
9
|
}
|
|
10
|
-
return
|
|
10
|
+
return total;
|
|
11
11
|
}
|
|
12
12
|
function concatUint8Array(args) {
|
|
13
13
|
const mergedArray = new Uint8Array(sum(args));
|
package/dist/util.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":";;AAAA,kBAMC;AACD,4CAQC;AAfD,SAAgB,GAAG,CAAC,KAAmB;IACrC,IAAI,
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":";;AAAA,kBAMC;AACD,4CAQC;AAfD,SAAgB,GAAG,CAAC,KAAmB;IACrC,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;QAC1B,KAAK,IAAI,KAAK,CAAC,MAAM,CAAA;IACvB,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AACD,SAAgB,gBAAgB,CAAC,IAAkB;IACjD,MAAM,WAAW,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAA;IAC7C,IAAI,MAAM,GAAG,CAAC,CAAA;IACd,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;QACzB,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;QAC9B,MAAM,IAAI,KAAK,CAAC,MAAM,CAAA;IACxB,CAAC;IACD,OAAO,WAAW,CAAA;AACpB,CAAC"}
|
package/esm/index.d.ts
CHANGED
|
@@ -3,10 +3,12 @@ export default class Trix {
|
|
|
3
3
|
ixxFile: GenericFilehandle;
|
|
4
4
|
ixFile: GenericFilehandle;
|
|
5
5
|
maxResults: number;
|
|
6
|
+
private decoder;
|
|
7
|
+
private indexCache?;
|
|
6
8
|
constructor(ixxFile: GenericFilehandle, ixFile: GenericFilehandle, maxResults?: number);
|
|
7
9
|
search(searchString: string, opts?: {
|
|
8
10
|
signal?: AbortSignal;
|
|
9
11
|
}): Promise<[string, string][]>;
|
|
10
12
|
private getIndex;
|
|
11
|
-
private
|
|
13
|
+
private getBuffer;
|
|
12
14
|
}
|
package/esm/index.js
CHANGED
|
@@ -8,6 +8,8 @@ export default class Trix {
|
|
|
8
8
|
ixxFile;
|
|
9
9
|
ixFile;
|
|
10
10
|
maxResults;
|
|
11
|
+
decoder = new TextDecoder('utf8');
|
|
12
|
+
indexCache;
|
|
11
13
|
constructor(ixxFile, ixFile, maxResults = 20) {
|
|
12
14
|
this.ixxFile = ixxFile;
|
|
13
15
|
this.ixFile = ixFile;
|
|
@@ -16,75 +18,68 @@ export default class Trix {
|
|
|
16
18
|
async search(searchString, opts) {
|
|
17
19
|
let resultArr = [];
|
|
18
20
|
const searchWords = searchString.split(' ');
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
// search string
|
|
47
|
-
if (word.slice(0, searchWord.length) > searchWord) {
|
|
48
|
-
done = true;
|
|
21
|
+
const firstWord = searchWords[0];
|
|
22
|
+
// validate that we have a non-empty search term
|
|
23
|
+
if (firstWord) {
|
|
24
|
+
const searchWord = firstWord.toLowerCase();
|
|
25
|
+
const res = await this.getBuffer(searchWord, opts);
|
|
26
|
+
let { end, buffer } = res;
|
|
27
|
+
let done = false;
|
|
28
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
29
|
+
while (!done) {
|
|
30
|
+
const str = this.decoder.decode(buffer);
|
|
31
|
+
// slice to lastIndexOf('\n') to make sure we get complete records
|
|
32
|
+
// since the buffer fetch could get halfway into a record
|
|
33
|
+
const lines = str
|
|
34
|
+
.slice(0, str.lastIndexOf('\n'))
|
|
35
|
+
.split('\n')
|
|
36
|
+
.filter(Boolean);
|
|
37
|
+
const hits2 = [];
|
|
38
|
+
for (const line of lines) {
|
|
39
|
+
const word = line.split(' ')[0];
|
|
40
|
+
if (word.startsWith(searchWord)) {
|
|
41
|
+
hits2.push(line);
|
|
42
|
+
}
|
|
43
|
+
else if (word > searchWord) {
|
|
44
|
+
// we are done scanning if we are lexicographically greater than
|
|
45
|
+
// the search string
|
|
46
|
+
done = true;
|
|
47
|
+
}
|
|
49
48
|
}
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
const hits = hits2.flatMap(line => {
|
|
50
|
+
const [term, ...parts] = line.split(' ');
|
|
51
|
+
return parts
|
|
52
|
+
.filter(Boolean)
|
|
53
|
+
.map(elt => [term, elt.split(',')[0]]);
|
|
54
|
+
});
|
|
55
|
+
resultArr = resultArr.concat(hits);
|
|
56
|
+
// if we are done or have filled up maxResults, break
|
|
57
|
+
if (done || resultArr.length >= this.maxResults) {
|
|
58
|
+
break;
|
|
52
59
|
}
|
|
53
|
-
|
|
54
|
-
const hits = hits2.flatMap(line => {
|
|
55
|
-
const [term, ...parts] = line.split(' ');
|
|
56
|
-
return parts.map(elt => [term, elt.split(',')[0]]);
|
|
57
|
-
});
|
|
58
|
-
// if we are not done, and we haven't filled up maxResults with hits yet,
|
|
59
|
-
// then refetch
|
|
60
|
-
if (resultArr.length + hits.length < this.maxResults && !done) {
|
|
60
|
+
// fetch more data
|
|
61
61
|
const res2 = await this.ixFile.read(CHUNK_SIZE, end, opts);
|
|
62
|
-
// early break if empty response
|
|
63
62
|
if (res2.length === 0) {
|
|
64
|
-
resultArr = resultArr.concat(hits);
|
|
65
63
|
break;
|
|
66
64
|
}
|
|
67
65
|
buffer = concatUint8Array([buffer, res2]);
|
|
68
66
|
end += CHUNK_SIZE;
|
|
69
67
|
}
|
|
70
|
-
// if we have filled up the hits, or we are detected to be done via the
|
|
71
|
-
// filtering, then return
|
|
72
|
-
else if (resultArr.length + hits.length >= this.maxResults || done) {
|
|
73
|
-
resultArr = resultArr.concat(hits);
|
|
74
|
-
break;
|
|
75
|
-
}
|
|
76
68
|
}
|
|
77
69
|
// de-duplicate results based on the detail column (resultArr[1])
|
|
78
70
|
return dedupe(resultArr, elt => elt[1]).slice(0, this.maxResults);
|
|
79
71
|
}
|
|
80
72
|
async getIndex(opts) {
|
|
73
|
+
if (this.indexCache) {
|
|
74
|
+
return this.indexCache;
|
|
75
|
+
}
|
|
81
76
|
const file = await this.ixxFile.readFile({
|
|
82
77
|
encoding: 'utf8',
|
|
83
78
|
...opts,
|
|
84
79
|
});
|
|
85
|
-
|
|
80
|
+
const result = file
|
|
86
81
|
.split('\n')
|
|
87
|
-
.filter(
|
|
82
|
+
.filter(Boolean)
|
|
88
83
|
.map(line => {
|
|
89
84
|
const p = line.length - ADDRESS_SIZE;
|
|
90
85
|
const prefix = line.slice(0, p);
|
|
@@ -92,28 +87,22 @@ export default class Trix {
|
|
|
92
87
|
const pos = Number.parseInt(posStr, 16);
|
|
93
88
|
return [prefix, pos];
|
|
94
89
|
});
|
|
90
|
+
this.indexCache = result;
|
|
91
|
+
return result;
|
|
95
92
|
}
|
|
96
|
-
async
|
|
93
|
+
async getBuffer(searchWord, opts) {
|
|
97
94
|
let start = 0;
|
|
98
|
-
let end =
|
|
95
|
+
let end = CHUNK_SIZE;
|
|
99
96
|
const indexes = await this.getIndex(opts);
|
|
100
97
|
for (const [key, value] of indexes) {
|
|
101
98
|
const trimmedKey = key.slice(0, searchWord.length);
|
|
102
99
|
if (trimmedKey < searchWord) {
|
|
103
100
|
start = value;
|
|
104
|
-
end = value +
|
|
101
|
+
end = value + CHUNK_SIZE;
|
|
105
102
|
}
|
|
106
103
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (len < 0) {
|
|
110
|
-
return undefined;
|
|
111
|
-
}
|
|
112
|
-
const buffer = await this.ixFile.read(len, start, opts);
|
|
113
|
-
return {
|
|
114
|
-
buffer,
|
|
115
|
-
end,
|
|
116
|
-
};
|
|
104
|
+
const buffer = await this.ixFile.read(end - start, start, opts);
|
|
105
|
+
return { buffer, end };
|
|
117
106
|
}
|
|
118
107
|
}
|
|
119
108
|
//# sourceMappingURL=index.js.map
|
package/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAI5C,MAAM,UAAU,GAAG,KAAK,CAAA;AAExB,4EAA4E;AAC5E,iEAAiE;AACjE,MAAM,YAAY,GAAG,EAAE,CAAA;AAEvB,MAAM,CAAC,OAAO,OAAO,IAAI;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/esm/util.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export function sum(array) {
|
|
2
|
-
let
|
|
2
|
+
let total = 0;
|
|
3
3
|
for (const entry of array) {
|
|
4
|
-
|
|
4
|
+
total += entry.length;
|
|
5
5
|
}
|
|
6
|
-
return
|
|
6
|
+
return total;
|
|
7
7
|
}
|
|
8
8
|
export function concatUint8Array(args) {
|
|
9
9
|
const mergedArray = new Uint8Array(sum(args));
|
package/esm/util.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,GAAG,CAAC,KAAmB;IACrC,IAAI,
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,GAAG,CAAC,KAAmB;IACrC,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;QAC1B,KAAK,IAAI,KAAK,CAAC,MAAM,CAAA;IACvB,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AACD,MAAM,UAAU,gBAAgB,CAAC,IAAkB;IACjD,MAAM,WAAW,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAA;IAC7C,IAAI,MAAM,GAAG,CAAC,CAAA;IACd,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;QACzB,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;QAC9B,MAAM,IAAI,KAAK,CAAC,MAAM,CAAA;IACxB,CAAC;IACD,OAAO,WAAW,CAAA;AACpB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "3.0.
|
|
2
|
+
"version": "3.0.5",
|
|
3
3
|
"license": "Apache-2.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"module": "esm/index.js",
|
|
@@ -16,28 +16,29 @@
|
|
|
16
16
|
"prebuild": "rimraf dist esm",
|
|
17
17
|
"build:esm": "tsc --target esnext --outDir esm",
|
|
18
18
|
"build:es5": "tsc --target es2015 --outDir dist --module commonjs",
|
|
19
|
-
"build": "
|
|
20
|
-
"preversion": "
|
|
19
|
+
"build": "yarn build:esm && yarn build:es5",
|
|
20
|
+
"preversion": "yarn lint && yarn test --run && yarn build",
|
|
21
21
|
"postbuild:es5": "echo '{\"type\": \"commonjs\"}' > dist/package.json",
|
|
22
22
|
"postversion": "git push --follow-tags",
|
|
23
|
-
"test": "vitest"
|
|
23
|
+
"test": "vitest",
|
|
24
|
+
"format": "prettier --write ."
|
|
24
25
|
},
|
|
25
26
|
"name": "@gmod/trix",
|
|
26
27
|
"author": "Matt Morgan",
|
|
27
28
|
"repository": "GMOD/trix-js",
|
|
28
29
|
"devDependencies": {
|
|
29
|
-
"@types/node": "^
|
|
30
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
31
|
-
"@typescript-eslint/parser": "^8.
|
|
30
|
+
"@types/node": "^25.0.9",
|
|
31
|
+
"@typescript-eslint/eslint-plugin": "^8.53.0",
|
|
32
|
+
"@typescript-eslint/parser": "^8.53.0",
|
|
32
33
|
"eslint": "^9.0.0",
|
|
33
34
|
"eslint-plugin-import": "^2.31.0",
|
|
34
35
|
"eslint-plugin-unicorn": "^62.0.0",
|
|
35
|
-
"generic-filehandle2": "^2.0.
|
|
36
|
-
"prettier": "^3.
|
|
36
|
+
"generic-filehandle2": "^2.0.18",
|
|
37
|
+
"prettier": "^3.8.0",
|
|
37
38
|
"rimraf": "^6.0.1",
|
|
38
39
|
"typescript": "^5.7.0",
|
|
39
|
-
"typescript-eslint": "^8.
|
|
40
|
-
"vitest": "^4.0.
|
|
40
|
+
"typescript-eslint": "^8.53.0",
|
|
41
|
+
"vitest": "^4.0.17"
|
|
41
42
|
},
|
|
42
43
|
"publishConfig": {
|
|
43
44
|
"access": "public"
|
package/src/index.ts
CHANGED
|
@@ -10,6 +10,9 @@ const CHUNK_SIZE = 65536
|
|
|
10
10
|
const ADDRESS_SIZE = 10
|
|
11
11
|
|
|
12
12
|
export default class Trix {
|
|
13
|
+
private decoder = new TextDecoder('utf8')
|
|
14
|
+
private indexCache?: readonly (readonly [string, number])[]
|
|
15
|
+
|
|
13
16
|
constructor(
|
|
14
17
|
public ixxFile: GenericFilehandle,
|
|
15
18
|
public ixFile: GenericFilehandle,
|
|
@@ -19,71 +22,60 @@ export default class Trix {
|
|
|
19
22
|
async search(searchString: string, opts?: { signal?: AbortSignal }) {
|
|
20
23
|
let resultArr = [] as [string, string][]
|
|
21
24
|
const searchWords = searchString.split(' ')
|
|
25
|
+
const firstWord = searchWords[0]
|
|
26
|
+
|
|
27
|
+
// validate that we have a non-empty search term
|
|
28
|
+
if (firstWord) {
|
|
29
|
+
const searchWord = firstWord.toLowerCase()
|
|
30
|
+
const res = await this.getBuffer(searchWord, opts)
|
|
31
|
+
|
|
32
|
+
let { end, buffer } = res
|
|
33
|
+
let done = false
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
35
|
+
while (!done) {
|
|
36
|
+
const str = this.decoder.decode(buffer)
|
|
37
|
+
|
|
38
|
+
// slice to lastIndexOf('\n') to make sure we get complete records
|
|
39
|
+
// since the buffer fetch could get halfway into a record
|
|
40
|
+
const lines = str
|
|
41
|
+
.slice(0, str.lastIndexOf('\n'))
|
|
42
|
+
.split('\n')
|
|
43
|
+
.filter(Boolean)
|
|
44
|
+
|
|
45
|
+
const hits2 = [] as string[]
|
|
46
|
+
for (const line of lines) {
|
|
47
|
+
const word = line.split(' ')[0]
|
|
48
|
+
|
|
49
|
+
if (word.startsWith(searchWord)) {
|
|
50
|
+
hits2.push(line)
|
|
51
|
+
} else if (word > searchWord) {
|
|
52
|
+
// we are done scanning if we are lexicographically greater than
|
|
53
|
+
// the search string
|
|
54
|
+
done = true
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const hits = hits2.flatMap(line => {
|
|
58
|
+
const [term, ...parts] = line.split(' ')
|
|
59
|
+
return parts
|
|
60
|
+
.filter(Boolean)
|
|
61
|
+
.map(elt => [term, elt.split(',')[0]] as [string, string])
|
|
62
|
+
})
|
|
22
63
|
|
|
23
|
-
|
|
24
|
-
const searchWord = searchWords[0].toLowerCase()
|
|
25
|
-
const res = await this._getBuffer(searchWord, opts)
|
|
26
|
-
if (!res) {
|
|
27
|
-
return []
|
|
28
|
-
}
|
|
64
|
+
resultArr = resultArr.concat(hits)
|
|
29
65
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
34
|
-
while (!done) {
|
|
35
|
-
let foundSomething = false
|
|
36
|
-
const str = decoder.decode(buffer)
|
|
37
|
-
|
|
38
|
-
// slice to lastIndexOf('\n') to make sure we get complete records
|
|
39
|
-
// since the buffer fetch could get halfway into a record
|
|
40
|
-
const lines = str
|
|
41
|
-
.slice(0, str.lastIndexOf('\n'))
|
|
42
|
-
.split('\n')
|
|
43
|
-
.filter(f => !!f)
|
|
44
|
-
|
|
45
|
-
const hits2 = [] as string[]
|
|
46
|
-
for (const line of lines) {
|
|
47
|
-
const word = line.split(' ')[0]
|
|
48
|
-
const match = word.startsWith(searchWord)
|
|
49
|
-
if (!foundSomething && match) {
|
|
50
|
-
foundSomething = true
|
|
66
|
+
// if we are done or have filled up maxResults, break
|
|
67
|
+
if (done || resultArr.length >= this.maxResults) {
|
|
68
|
+
break
|
|
51
69
|
}
|
|
52
70
|
|
|
53
|
-
//
|
|
54
|
-
// search string
|
|
55
|
-
if (word.slice(0, searchWord.length) > searchWord) {
|
|
56
|
-
done = true
|
|
57
|
-
}
|
|
58
|
-
if (match) {
|
|
59
|
-
hits2.push(line)
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
const hits = hits2.flatMap(line => {
|
|
63
|
-
const [term, ...parts] = line.split(' ')
|
|
64
|
-
return parts.map(elt => [term, elt.split(',')[0]] as [string, string])
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
// if we are not done, and we haven't filled up maxResults with hits yet,
|
|
68
|
-
// then refetch
|
|
69
|
-
if (resultArr.length + hits.length < this.maxResults && !done) {
|
|
71
|
+
// fetch more data
|
|
70
72
|
const res2 = await this.ixFile.read(CHUNK_SIZE, end, opts)
|
|
71
|
-
|
|
72
|
-
// early break if empty response
|
|
73
73
|
if (res2.length === 0) {
|
|
74
|
-
resultArr = resultArr.concat(hits)
|
|
75
74
|
break
|
|
76
75
|
}
|
|
77
76
|
buffer = concatUint8Array([buffer, res2])
|
|
78
77
|
end += CHUNK_SIZE
|
|
79
78
|
}
|
|
80
|
-
|
|
81
|
-
// if we have filled up the hits, or we are detected to be done via the
|
|
82
|
-
// filtering, then return
|
|
83
|
-
else if (resultArr.length + hits.length >= this.maxResults || done) {
|
|
84
|
-
resultArr = resultArr.concat(hits)
|
|
85
|
-
break
|
|
86
|
-
}
|
|
87
79
|
}
|
|
88
80
|
|
|
89
81
|
// de-duplicate results based on the detail column (resultArr[1])
|
|
@@ -91,13 +83,16 @@ export default class Trix {
|
|
|
91
83
|
}
|
|
92
84
|
|
|
93
85
|
private async getIndex(opts?: { signal?: AbortSignal }) {
|
|
86
|
+
if (this.indexCache) {
|
|
87
|
+
return this.indexCache
|
|
88
|
+
}
|
|
94
89
|
const file = await this.ixxFile.readFile({
|
|
95
90
|
encoding: 'utf8',
|
|
96
91
|
...opts,
|
|
97
92
|
})
|
|
98
|
-
|
|
93
|
+
const result = file
|
|
99
94
|
.split('\n')
|
|
100
|
-
.filter(
|
|
95
|
+
.filter(Boolean)
|
|
101
96
|
.map(line => {
|
|
102
97
|
const p = line.length - ADDRESS_SIZE
|
|
103
98
|
const prefix = line.slice(0, p)
|
|
@@ -105,32 +100,23 @@ export default class Trix {
|
|
|
105
100
|
const pos = Number.parseInt(posStr, 16)
|
|
106
101
|
return [prefix, pos] as const
|
|
107
102
|
})
|
|
103
|
+
this.indexCache = result
|
|
104
|
+
return result
|
|
108
105
|
}
|
|
109
106
|
|
|
110
|
-
private async
|
|
111
|
-
searchWord: string,
|
|
112
|
-
opts?: { signal?: AbortSignal },
|
|
113
|
-
) {
|
|
107
|
+
private async getBuffer(searchWord: string, opts?: { signal?: AbortSignal }) {
|
|
114
108
|
let start = 0
|
|
115
|
-
let end =
|
|
109
|
+
let end = CHUNK_SIZE
|
|
116
110
|
const indexes = await this.getIndex(opts)
|
|
117
111
|
for (const [key, value] of indexes) {
|
|
118
112
|
const trimmedKey = key.slice(0, searchWord.length)
|
|
119
113
|
if (trimmedKey < searchWord) {
|
|
120
114
|
start = value
|
|
121
|
-
end = value +
|
|
115
|
+
end = value + CHUNK_SIZE
|
|
122
116
|
}
|
|
123
117
|
}
|
|
124
118
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
if (len < 0) {
|
|
128
|
-
return undefined
|
|
129
|
-
}
|
|
130
|
-
const buffer = await this.ixFile.read(len, start, opts)
|
|
131
|
-
return {
|
|
132
|
-
buffer,
|
|
133
|
-
end,
|
|
134
|
-
}
|
|
119
|
+
const buffer = await this.ixFile.read(end - start, start, opts)
|
|
120
|
+
return { buffer, end }
|
|
135
121
|
}
|
|
136
122
|
}
|
package/src/util.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export function sum(array: Uint8Array[]) {
|
|
2
|
-
let
|
|
2
|
+
let total = 0
|
|
3
3
|
for (const entry of array) {
|
|
4
|
-
|
|
4
|
+
total += entry.length
|
|
5
5
|
}
|
|
6
|
-
return
|
|
6
|
+
return total
|
|
7
7
|
}
|
|
8
8
|
export function concatUint8Array(args: Uint8Array[]) {
|
|
9
9
|
const mergedArray = new Uint8Array(sum(args))
|