1
1
import process from 'node:process' ;
2
- import { ApiItemKind } from '@microsoft/api-extractor-model' ;
3
2
import type {
4
3
APIApplicationCommandInteractionDataOption ,
5
4
APIApplicationCommandInteractionDataStringOption ,
6
5
APIApplicationCommandInteractionDataSubcommandOption ,
7
6
} from 'discord-api-types/v10' ;
8
7
import { InteractionResponseType } from 'discord-api-types/v10' ;
9
- import type { Kysely } from 'kysely' ;
10
8
import type { Response } from 'polka' ;
11
9
import { fetch } from 'undici' ;
12
- import type { Database } from '../../types/djs-db .js' ;
10
+ import { AUTOCOMPLETE_MAX_ITEMS } from '../../util/constants .js' ;
13
11
import { truncate } from '../../util/truncate.js' ;
14
- import type { DjsDocsSearchResult } from '../djsDocs.js' ;
15
- import { fetchVersions } from '../djsDocs.js' ;
16
12
17
13
const BASE_SEARCH = `https://search.discordjs.dev/` ;
18
14
@@ -26,26 +22,26 @@ function parseDocsPath(path: string) {
26
22
// /docs/packages/builders/main/EmbedImageData:Interface#proxyURL
27
23
28
24
const parts = path . trim ( ) . split ( '/' ) . filter ( Boolean ) ;
29
- const item = parts . at ( 4 ) ;
30
- const itemParts = item ?. split ( '#' ) ;
25
+ const query = parts . at ( 4 ) ;
26
+ const queryParts = query ?. split ( '#' ) ;
27
+
28
+ const [ item , kind ] = queryParts ?. at ( 0 ) ?. split ( ':' ) ?? [ ] ;
29
+ const method = queryParts ?. at ( 1 ) ;
31
30
32
- const firstItemParts = itemParts ?. at ( 0 ) ?. split ( ':' ) ;
33
- const itemClass = firstItemParts ?. at ( 0 ) ;
34
31
const _package = parts . at ( 2 ) ;
35
32
const version = parts . at ( 3 ) ;
36
- const method = itemParts ?. at ( 1 ) ;
37
33
38
34
return {
39
35
package : _package ,
40
36
version,
37
+ query,
41
38
item,
42
- class : itemClass ,
39
+ kind ,
43
40
method,
44
41
} ;
45
42
}
46
43
47
44
export async function djsDocsDevAutoComplete (
48
- db : Kysely < Database > ,
49
45
res : Response ,
50
46
options : APIApplicationCommandInteractionDataOption [ ] ,
51
47
) : Promise < Response > {
@@ -58,54 +54,16 @@ export async function djsDocsDevAutoComplete(
58
54
| APIApplicationCommandInteractionDataStringOption
59
55
| undefined ;
60
56
61
- const versions = await fetchVersions ( db , option . name ) ;
62
- const latest = versions . at ( - 2 ) ?. version ;
63
-
64
57
res . setHeader ( 'Content-Type' , 'application/json' ) ;
65
58
66
- if ( versionOptionData ?. focused ) {
67
- const relevantVersions : { name : string ; version : string } [ ] = [ ] ;
68
-
69
- versions . reverse ( ) ;
70
-
71
- for ( const version of versions ) {
72
- if ( version . version . includes ( '.' ) ) {
73
- const [ major , minor ] = version . version . split ( '.' ) ;
74
- if ( ! relevantVersions . some ( ( version ) => version . version . startsWith ( `${ major } .${ minor } ` ) ) ) {
75
- relevantVersions . push ( version ) ;
76
- }
77
- } else {
78
- relevantVersions . push ( version ) ;
79
- }
80
- }
81
-
82
- res . write (
83
- JSON . stringify ( {
84
- data : {
85
- choices : relevantVersions . slice ( 0 , 25 ) . map ( ( version ) => ( {
86
- name : `${ version . name } ${ version . version } ` ,
87
- value : version . version ,
88
- } ) ) ,
89
- } ,
90
- type : InteractionResponseType . ApplicationCommandAutocompleteResult ,
91
- } ) ,
92
- ) ;
93
-
94
- return res ;
95
- }
96
-
97
59
if ( ! queryOptionData ) {
98
60
throw new Error ( 'expected query option, none received' ) ;
99
61
}
100
62
101
- if ( ! latest ) {
102
- throw new Error ( 'stable version could not be determined' ) ;
103
- }
104
-
105
- const searchRes = await fetch ( searchURL ( option . name , versionOptionData ?. value ?? latest ) , {
63
+ const searchRes = await fetch ( searchURL ( option . name , versionOptionData ?. value ?? 'main' ) , {
106
64
method : 'post' ,
107
65
body : JSON . stringify ( {
108
- limit : 25 ,
66
+ limit : 100 ,
109
67
// eslint-disable-next-line id-length
110
68
q : queryOptionData . value ,
111
69
} ) ,
@@ -115,22 +73,43 @@ export async function djsDocsDevAutoComplete(
115
73
} ,
116
74
} ) ;
117
75
118
- const docsResult = ( await searchRes . json ( ) ) as DjsDocsSearchResult ;
119
- const { hits } = docsResult ;
120
-
121
- const choices =
122
- hits ?. map ( ( hit ) => {
123
- const parts = parseDocsPath ( hit . path ) ;
124
- const identifier =
125
- hit . kind === ApiItemKind . Method || hit . kind === ApiItemKind . Property
126
- ? `${ parts . class } #${ hit . name } ${ hit . kind === ApiItemKind . Method ? '()' : '' } `
127
- : hit . name ;
128
-
129
- return {
130
- name : truncate ( `${ identifier } ${ hit . summary ? ` - ${ hit . summary } ` : '' } ` , 100 ) ,
131
- value : hit . path ,
132
- } ;
133
- } ) ?? [ ] ;
76
+ const docsResult = ( await searchRes . json ( ) ) as any ;
77
+ docsResult . hits . sort ( ( one : any , other : any ) => {
78
+ const oneScore = one . kind === 'Class' ? 1 : 0 ;
79
+ const otherScore = other . kind === 'Class' ? 1 : 0 ;
80
+
81
+ return otherScore - oneScore ;
82
+ } ) ;
83
+
84
+ const choices = [ ] ;
85
+
86
+ for ( const hit of docsResult . hits ) {
87
+ if ( choices . length >= AUTOCOMPLETE_MAX_ITEMS ) {
88
+ break ;
89
+ }
90
+
91
+ const parsed = parseDocsPath ( hit . path ) ;
92
+
93
+ let name = '' ;
94
+ const isMember = [ 'Property' , 'Method' , 'Event' , 'PropertySignature' , 'EnumMember' ] . includes ( hit . kind ) ;
95
+ if ( isMember ) {
96
+ name += `${ parsed . item } #${ hit . name } ${ hit . kind === 'Method' ? '()' : '' } ` ;
97
+ } else {
98
+ name += hit . name ;
99
+ }
100
+
101
+ const itemKind = isMember ? 'Class' : hit . kind ;
102
+ const parts = [ parsed . package , parsed . item . toLocaleLowerCase ( ) , parsed . kind ] ;
103
+
104
+ if ( isMember ) {
105
+ parts . push ( hit . name ) ;
106
+ }
107
+
108
+ choices . push ( {
109
+ name : truncate ( `${ name } ${ hit . summary ? ` - ${ hit . summary } ` : '' } ` , 100 , ' ' ) ,
110
+ value : parts . join ( '|' ) ,
111
+ } ) ;
112
+ }
134
113
135
114
res . write (
136
115
JSON . stringify ( {
0 commit comments