Skip to content

Commit 2a84b5c

Browse files
committed
feat(*): experimental support for new docs stack
1 parent 30ea36a commit 2a84b5c

11 files changed

+266
-802
lines changed

package.json

-6
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@
4141
"he": "^1.2.0",
4242
"html-entities": "^2.4.0",
4343
"kleur": "^4.1.5",
44-
"kysely": "^0.26.3",
45-
"kysely-planetscale": "^1.4.0",
4644
"pino": "^8.15.0",
4745
"polka": "1.0.0-next.15",
4846
"readdirp": "^3.6.0",
@@ -52,9 +50,6 @@
5250
"devDependencies": {
5351
"@commitlint/cli": "^17.7.1",
5452
"@commitlint/config-angular": "^17.7.0",
55-
"@microsoft/api-extractor-model": "^7.27.6",
56-
"@microsoft/tsdoc": "^0.14.2",
57-
"@microsoft/tsdoc-config": "^0.16.2",
5853
"@types/he": "^1.2.0",
5954
"@types/node": "20.5.7",
6055
"@types/pino": "^7.0.5",
@@ -66,7 +61,6 @@
6661
"eslint-config-prettier": "^9.0.0",
6762
"eslint-plugin-prettier": "^5.0.0",
6863
"husky": "^8.0.3",
69-
"kysely-codegen": "^0.10.1",
7064
"lint-staged": "^14.0.1",
7165
"prettier": "^3.0.2",
7266
"prettier-plugin-toml": "^1.0.0",

src/functions/autocomplete/docsDevAutoComplete.ts

+47-68
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
11
import process from 'node:process';
2-
import { ApiItemKind } from '@microsoft/api-extractor-model';
32
import type {
43
APIApplicationCommandInteractionDataOption,
54
APIApplicationCommandInteractionDataStringOption,
65
APIApplicationCommandInteractionDataSubcommandOption,
76
} from 'discord-api-types/v10';
87
import { InteractionResponseType } from 'discord-api-types/v10';
9-
import type { Kysely } from 'kysely';
108
import type { Response } from 'polka';
119
import { fetch } from 'undici';
12-
import type { Database } from '../../types/djs-db.js';
10+
import { AUTOCOMPLETE_MAX_ITEMS } from '../../util/constants.js';
1311
import { truncate } from '../../util/truncate.js';
14-
import type { DjsDocsSearchResult } from '../djsDocs.js';
15-
import { fetchVersions } from '../djsDocs.js';
1612

1713
const BASE_SEARCH = `https://search.discordjs.dev/`;
1814

@@ -26,26 +22,26 @@ function parseDocsPath(path: string) {
2622
// /docs/packages/builders/main/EmbedImageData:Interface#proxyURL
2723

2824
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);
3130

32-
const firstItemParts = itemParts?.at(0)?.split(':');
33-
const itemClass = firstItemParts?.at(0);
3431
const _package = parts.at(2);
3532
const version = parts.at(3);
36-
const method = itemParts?.at(1);
3733

3834
return {
3935
package: _package,
4036
version,
37+
query,
4138
item,
42-
class: itemClass,
39+
kind,
4340
method,
4441
};
4542
}
4643

4744
export async function djsDocsDevAutoComplete(
48-
db: Kysely<Database>,
4945
res: Response,
5046
options: APIApplicationCommandInteractionDataOption[],
5147
): Promise<Response> {
@@ -58,54 +54,16 @@ export async function djsDocsDevAutoComplete(
5854
| APIApplicationCommandInteractionDataStringOption
5955
| undefined;
6056

61-
const versions = await fetchVersions(db, option.name);
62-
const latest = versions.at(-2)?.version;
63-
6457
res.setHeader('Content-Type', 'application/json');
6558

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-
9759
if (!queryOptionData) {
9860
throw new Error('expected query option, none received');
9961
}
10062

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'), {
10664
method: 'post',
10765
body: JSON.stringify({
108-
limit: 25,
66+
limit: 100,
10967
// eslint-disable-next-line id-length
11068
q: queryOptionData.value,
11169
}),
@@ -115,22 +73,43 @@ export async function djsDocsDevAutoComplete(
11573
},
11674
});
11775

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+
}
134113

135114
res.write(
136115
JSON.stringify({

0 commit comments

Comments
 (0)