@hesed/search 0.1.0 → 0.2.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 +2 -2
- package/dist/commands/search.js +1 -1
- package/dist/search-logic.d.ts +2 -1
- package/dist/search-logic.js +33 -12
- package/oclif.manifest.json +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ $ npm install -g @hesed/search
|
|
|
20
20
|
$ search COMMAND
|
|
21
21
|
running command...
|
|
22
22
|
$ search (--version)
|
|
23
|
-
@hesed/search/0.1
|
|
23
|
+
@hesed/search/0.2.1 linux-x64 node-v24.16.0
|
|
24
24
|
$ search --help [COMMAND]
|
|
25
25
|
USAGE
|
|
26
26
|
$ search COMMAND
|
|
@@ -62,5 +62,5 @@ EXAMPLES
|
|
|
62
62
|
$ search search "update jira" --details
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
_See code: [src/commands/search.ts](https://github.com/hesedcasa/search/blob/v0.1
|
|
65
|
+
_See code: [src/commands/search.ts](https://github.com/hesedcasa/search/blob/v0.2.1/src/commands/search.ts)_
|
|
66
66
|
<!-- commandsstop -->
|
package/dist/commands/search.js
CHANGED
|
@@ -18,7 +18,7 @@ export default class Search extends Command {
|
|
|
18
18
|
async run() {
|
|
19
19
|
const { args, flags } = await this.parse(Search);
|
|
20
20
|
const allCommands = this.config.commands.filter((c) => !c.hidden && c.pluginName !== '@oclif/plugin-plugins');
|
|
21
|
-
const scored = searchCommands(args.query, allCommands).slice(0, flags.limit);
|
|
21
|
+
const scored = (await searchCommands(args.query, allCommands)).slice(0, flags.limit);
|
|
22
22
|
const results = scored.map((entry) => {
|
|
23
23
|
const { cmd } = entry;
|
|
24
24
|
const configuredId = toConfiguredId(cmd.id, this.config);
|
package/dist/search-logic.d.ts
CHANGED
|
@@ -8,4 +8,5 @@ export type ScoredCommand<T extends SearchableCommand = SearchableCommand> = {
|
|
|
8
8
|
cmd: T;
|
|
9
9
|
score: number;
|
|
10
10
|
};
|
|
11
|
-
export declare function searchCommands<T extends SearchableCommand>(query: string, commands: T[]): Array<ScoredCommand<T
|
|
11
|
+
export declare function searchCommands<T extends SearchableCommand>(query: string, commands: T[]): Promise<Array<ScoredCommand<T>>>;
|
|
12
|
+
export declare function searchCommandsLexically<T extends SearchableCommand>(query: string, commands: T[], haystack?: string[]): Array<ScoredCommand<T>>;
|
package/dist/search-logic.js
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
if (
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
const require = createRequire(import.meta.url);
|
|
3
|
+
const { Index } = require('flexsearch');
|
|
4
|
+
export async function searchCommands(query, commands) {
|
|
5
|
+
const normalizedQuery = query.trim();
|
|
6
|
+
if (normalizedQuery.length === 0 || commands.length === 0)
|
|
7
|
+
return [];
|
|
8
|
+
const haystack = commands.map((command) => commandSearchText(command));
|
|
9
|
+
return searchCommandsLexically(normalizedQuery, commands, haystack);
|
|
10
|
+
}
|
|
11
|
+
export function searchCommandsLexically(query, commands, haystack = commands.map((command) => commandSearchText(command))) {
|
|
12
|
+
const index = createCommandSearchIndex(haystack);
|
|
13
|
+
const idxs = index.search(query, { limit: commands.length, suggest: true });
|
|
14
|
+
if (idxs.length > 0) {
|
|
15
|
+
return idxs.map((idx, rank) => ({ cmd: commands[Number(idx)], score: rank }));
|
|
9
16
|
}
|
|
10
17
|
// Multi-token fallback: score each command by how many individual query
|
|
11
18
|
// tokens it matches. Handles queries containing unknown alias words (e.g.
|
|
@@ -15,13 +22,27 @@ export function searchCommands(query, commands) {
|
|
|
15
22
|
return [];
|
|
16
23
|
const hitCount = new Map();
|
|
17
24
|
for (const token of tokens) {
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
25
|
+
const tIdxs = index.search(token, { limit: commands.length, suggest: true });
|
|
26
|
+
for (const idx of tIdxs) {
|
|
27
|
+
const commandIndex = Number(idx);
|
|
28
|
+
hitCount.set(commandIndex, (hitCount.get(commandIndex) ?? 0) + 1);
|
|
22
29
|
}
|
|
23
30
|
}
|
|
24
31
|
return [...hitCount.entries()]
|
|
25
32
|
.sort((a, b) => b[1] - a[1] || a[0] - b[0])
|
|
26
33
|
.map(([idx, hits]) => ({ cmd: commands[idx], score: tokens.length - hits }));
|
|
27
34
|
}
|
|
35
|
+
function createCommandSearchIndex(haystack) {
|
|
36
|
+
const index = new Index({ encoder: 'LatinAdvanced', resolution: 9, tokenize: 'forward' });
|
|
37
|
+
for (const [idx, text] of haystack.entries()) {
|
|
38
|
+
index.add(idx, text);
|
|
39
|
+
}
|
|
40
|
+
return index;
|
|
41
|
+
}
|
|
42
|
+
function commandSearchText(command) {
|
|
43
|
+
return [command.id, command.summary ?? command.description ?? '', command.pluginName ?? '']
|
|
44
|
+
.filter(Boolean)
|
|
45
|
+
.join(' ')
|
|
46
|
+
.replaceAll(/\s+/g, ' ')
|
|
47
|
+
.trim();
|
|
48
|
+
}
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hesed/search",
|
|
3
3
|
"description": "Intelligence search plugin",
|
|
4
|
-
"version": "0.1
|
|
4
|
+
"version": "0.2.1",
|
|
5
5
|
"author": "Hesed",
|
|
6
6
|
"bin": {
|
|
7
7
|
"permission": "./bin/run.js"
|
|
8
8
|
},
|
|
9
9
|
"bugs": "https://github.com/hesedcasa/search/issues",
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@
|
|
12
|
-
"
|
|
11
|
+
"@oclif/core": "^4",
|
|
12
|
+
"flexsearch": "^0.8.212"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
15
|
"@eslint/compat": "^1",
|