@gmod/trix 3.0.3 → 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 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 _getBuffer;
13
+ private getBuffer;
12
14
  }
package/dist/index.js CHANGED
@@ -9,8 +9,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- const dedupe_1 = require("./dedupe");
13
- const util_1 = require("./util");
12
+ const dedupe_ts_1 = require("./dedupe.js");
13
+ const util_ts_1 = require("./util.js");
14
14
  const CHUNK_SIZE = 65536;
15
15
  // this is the number of hex characters to use for the address in ixixx, see
16
16
  // https://github.com/GMOD/ixixx-js/blob/master/src/index.ts#L182
@@ -20,79 +20,73 @@ 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
- // we only search one word at a time
29
- const searchWord = searchWords[0].toLowerCase();
30
- const res = yield this._getBuffer(searchWord, opts);
31
- if (!res) {
32
- return [];
33
- }
34
- let { end, buffer } = res;
35
- let done = false;
36
- const decoder = new TextDecoder('utf8');
37
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
38
- while (!done) {
39
- let foundSomething = false;
40
- const str = decoder.decode(buffer);
41
- // slice to lastIndexOf('\n') to make sure we get complete records
42
- // since the buffer fetch could get halfway into a record
43
- const lines = str
44
- .slice(0, str.lastIndexOf('\n'))
45
- .split('\n')
46
- .filter(f => !!f);
47
- const hits2 = [];
48
- for (const line of lines) {
49
- const word = line.split(' ')[0];
50
- const match = word.startsWith(searchWord);
51
- if (!foundSomething && match) {
52
- foundSomething = true;
53
- }
54
- // we are done scanning if we are lexicographically greater than the
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
- if (match) {
60
- hits2.push(line);
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
- buffer = (0, util_1.concatUint8Array)([buffer, res2]);
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
- return (0, dedupe_1.dedupe)(resultArr, elt => elt[1]).slice(0, this.maxResults);
78
+ return (0, dedupe_ts_1.dedupe)(resultArr, elt => elt[1]).slice(0, this.maxResults);
88
79
  });
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
- return file
87
+ const result = file
94
88
  .split('\n')
95
- .filter(f => !!f)
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
- _getBuffer(searchWord, opts) {
101
+ getBuffer(searchWord, opts) {
106
102
  return __awaiter(this, void 0, void 0, function* () {
107
103
  let start = 0;
108
- let end = 65536;
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 + 65536;
110
+ end = value + CHUNK_SIZE;
115
111
  }
116
112
  }
117
- // Return the buffer and its end position in the file.
118
- const len = end - start;
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":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
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 sum = 0;
6
+ let total = 0;
7
7
  for (const entry of array) {
8
- sum += entry.length;
8
+ total += entry.length;
9
9
  }
10
- return sum;
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,GAAG,GAAG,CAAC,CAAA;IACX,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;QAC1B,GAAG,IAAI,KAAK,CAAC,MAAM,CAAA;IACrB,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,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"}
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 _getBuffer;
13
+ private getBuffer;
12
14
  }
package/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { dedupe } from './dedupe';
2
- import { concatUint8Array } from './util';
1
+ import { dedupe } from "./dedupe.js";
2
+ import { concatUint8Array } from "./util.js";
3
3
  const CHUNK_SIZE = 65536;
4
4
  // this is the number of hex characters to use for the address in ixixx, see
5
5
  // https://github.com/GMOD/ixixx-js/blob/master/src/index.ts#L182
@@ -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
- // we only search one word at a time
20
- const searchWord = searchWords[0].toLowerCase();
21
- const res = await this._getBuffer(searchWord, opts);
22
- if (!res) {
23
- return [];
24
- }
25
- let { end, buffer } = res;
26
- let done = false;
27
- const decoder = new TextDecoder('utf8');
28
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
29
- while (!done) {
30
- let foundSomething = false;
31
- const str = decoder.decode(buffer);
32
- // slice to lastIndexOf('\n') to make sure we get complete records
33
- // since the buffer fetch could get halfway into a record
34
- const lines = str
35
- .slice(0, str.lastIndexOf('\n'))
36
- .split('\n')
37
- .filter(f => !!f);
38
- const hits2 = [];
39
- for (const line of lines) {
40
- const word = line.split(' ')[0];
41
- const match = word.startsWith(searchWord);
42
- if (!foundSomething && match) {
43
- foundSomething = true;
44
- }
45
- // we are done scanning if we are lexicographically greater than the
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
- if (match) {
51
- hits2.push(line);
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
- return file
80
+ const result = file
86
81
  .split('\n')
87
- .filter(f => !!f)
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 _getBuffer(searchWord, opts) {
93
+ async getBuffer(searchWord, opts) {
97
94
  let start = 0;
98
- let end = 65536;
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 + 65536;
101
+ end = value + CHUNK_SIZE;
105
102
  }
106
103
  }
107
- // Return the buffer and its end position in the file.
108
- const len = end - start;
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":"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"}
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 sum = 0;
2
+ let total = 0;
3
3
  for (const entry of array) {
4
- sum += entry.length;
4
+ total += entry.length;
5
5
  }
6
- return sum;
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,GAAG,GAAG,CAAC,CAAA;IACX,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;QAC1B,GAAG,IAAI,KAAK,CAAC,MAAM,CAAA;IACrB,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,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"}
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.3",
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": "npm run build:esm && npm run build:es5",
20
- "preversion": "npm run lint && npm test run && npm run build",
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": "^20.14.11",
30
- "@typescript-eslint/eslint-plugin": "^8.4.0",
31
- "@typescript-eslint/parser": "^8.4.0",
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
- "eslint-plugin-unicorn": "^58.0.0",
35
- "generic-filehandle2": "^1.0.0",
36
- "prettier": "^3.3.3",
35
+ "eslint-plugin-unicorn": "^62.0.0",
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.4.0",
40
- "vitest": "^3.0.7"
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
@@ -1,5 +1,5 @@
1
- import { dedupe } from './dedupe'
2
- import { concatUint8Array } from './util'
1
+ import { dedupe } from './dedupe.ts'
2
+ import { concatUint8Array } from './util.ts'
3
3
 
4
4
  import type { GenericFilehandle } from 'generic-filehandle2'
5
5
 
@@ -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
- // we only search one word at a time
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
- let { end, buffer } = res
31
- let done = false
32
- const decoder = new TextDecoder('utf8')
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
- // we are done scanning if we are lexicographically greater than the
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
- return file
93
+ const result = file
99
94
  .split('\n')
100
- .filter(f => !!f)
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 _getBuffer(
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 = 65536
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 + 65536
115
+ end = value + CHUNK_SIZE
122
116
  }
123
117
  }
124
118
 
125
- // Return the buffer and its end position in the file.
126
- const len = end - start
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 sum = 0
2
+ let total = 0
3
3
  for (const entry of array) {
4
- sum += entry.length
4
+ total += entry.length
5
5
  }
6
- return sum
6
+ return total
7
7
  }
8
8
  export function concatUint8Array(args: Uint8Array[]) {
9
9
  const mergedArray = new Uint8Array(sum(args))