fix(website): remove several obsolete special handling of dtypes (#10898)

* fix(website): remove several obsolete special handling of dtypes

* fix: reduce hardcoded places

* chore: api-extractor.json setting mainEntryPointName
This commit is contained in:
Qjuh
2025-05-13 20:40:41 +02:00
committed by GitHub
parent aa533efe26
commit 14e226b72b
12 changed files with 49 additions and 94 deletions

View File

@@ -17,24 +17,21 @@ export function EntryPointSelect({
const { entryPoints: parsedEntrypoints } = parseDocsPathParams(params.item as string[] | undefined); const { entryPoints: parsedEntrypoints } = parseDocsPathParams(params.item as string[] | undefined);
return ( return (
<Select <Select aria-label="Select an entrypoint" defaultSelectedKey={parsedEntrypoints.join('/')}>
aria-label="Select an entrypoint"
defaultSelectedKey={parsedEntrypoints.length ? parsedEntrypoints.join('/') : 'global'}
>
<SelectTrigger className="bg-[#f3f3f4] dark:bg-[#121214]" /> <SelectTrigger className="bg-[#f3f3f4] dark:bg-[#121214]" />
<SelectList classNames={{ popover: 'bg-[#f3f3f4] dark:bg-[#28282d]' }} items={entryPoints}> <SelectList classNames={{ popover: 'bg-[#f3f3f4] dark:bg-[#28282d]' }} items={entryPoints}>
{(item) => ( {(item) => (
<SelectOption <SelectOption
className="dark:pressed:bg-[#313135] bg-[#f3f3f4] dark:bg-[#28282d] dark:hover:bg-[#313135]" className="dark:pressed:bg-[#313135] bg-[#f3f3f4] dark:bg-[#28282d] dark:hover:bg-[#313135]"
href={`/docs/packages/${params.packageName}/${params.version}/${item.entryPoint}`} href={`/docs/packages/${params.packageName}/${params.version}/${item.entryPoint}`}
id={item.entryPoint || 'global'} id={item.entryPoint}
key={item.entryPoint || 'global'} key={item.entryPoint}
onHoverStart={() => onHoverStart={() =>
router.prefetch(`/docs/packages/${params.packageName}/${params.version}/${item.entryPoint}`) router.prefetch(`/docs/packages/${params.packageName}/${params.version}/${item.entryPoint}`)
} }
textValue={item.entryPoint || 'global'} textValue={item.entryPoint}
> >
{item.entryPoint || 'global'} {item.entryPoint}
</SelectOption> </SelectOption>
)} )}
</SelectList> </SelectList>

View File

@@ -1,6 +1,6 @@
import Cloudflare from 'cloudflare'; import Cloudflare from 'cloudflare';
import { NextResponse, type NextRequest } from 'next/server'; import { NextResponse, type NextRequest } from 'next/server';
import { PACKAGES } from './util/constants'; import { DEFAULT_ENTRY_POINT, PACKAGES, PACKAGES_WITH_ENTRY_POINTS } from './util/constants';
import { ENV } from './util/env'; import { ENV } from './util/env';
const client = new Cloudflare({ const client = new Cloudflare({
@@ -8,7 +8,12 @@ const client = new Cloudflare({
}); });
async function fetchLatestVersion(packageName: string): Promise<string> { async function fetchLatestVersion(packageName: string): Promise<string> {
const hasEntryPoints = PACKAGES_WITH_ENTRY_POINTS.includes(packageName);
if (ENV.IS_LOCAL_DEV) { if (ENV.IS_LOCAL_DEV) {
if (hasEntryPoints) {
return ['main', ...DEFAULT_ENTRY_POINT].join('/');
}
return 'main'; return 'main';
} }
@@ -19,7 +24,7 @@ async function fetchLatestVersion(packageName: string): Promise<string> {
params: [packageName], params: [packageName],
}); });
return (result[0]?.results as { version: string }[] | undefined)?.[0]?.version ?? 'main'; return `${(result[0]?.results as { version: string }[] | undefined)?.[0]?.version ?? 'main'}${hasEntryPoints ? ['', ...DEFAULT_ENTRY_POINT].join('/') : ''}`;
} catch { } catch {
return ''; return '';
} }

View File

@@ -16,5 +16,7 @@ export const PACKAGES = [
export const PACKAGES_WITH_ENTRY_POINTS = ['discord-api-types']; export const PACKAGES_WITH_ENTRY_POINTS = ['discord-api-types'];
export const DEFAULT_ENTRY_POINT = ['v10'];
export const DESCRIPTION = export const DESCRIPTION =
"discord.js is a powerful Node.js module that allows you to interact with the Discord API very easily. It takes a much more object-oriented approach than most other JS Discord libraries, making your bot's code significantly tidier and easier to comprehend."; "discord.js is a powerful Node.js module that allows you to interact with the Discord API very easily. It takes a much more object-oriented approach than most other JS Discord libraries, making your bot's code significantly tidier and easier to comprehend.";

View File

@@ -1,3 +1,5 @@
import { DEFAULT_ENTRY_POINT } from './constants';
export function parseDocsPathParams(item: string[] | undefined): { export function parseDocsPathParams(item: string[] | undefined): {
entryPoints: string[]; entryPoints: string[];
foundItem: string | undefined; foundItem: string | undefined;
@@ -10,7 +12,7 @@ export function parseDocsPathParams(item: string[] | undefined): {
const hasTypeMarker = lastElement?.includes('%3A'); const hasTypeMarker = lastElement?.includes('%3A');
return { return {
entryPoints: hasTypeMarker ? item.slice(0, -1) : item, entryPoints: hasTypeMarker ? item.slice(0, -1) : lastElement?.length === 0 ? DEFAULT_ENTRY_POINT : item,
foundItem: hasTypeMarker ? lastElement : undefined, foundItem: hasTypeMarker ? lastElement : undefined,
}; };
} }

View File

@@ -15,16 +15,14 @@ import { ApiPackage } from './ApiPackage.js';
export interface IApiEntryPointOptions extends IApiItemContainerMixinOptions, IApiNameMixinOptions {} export interface IApiEntryPointOptions extends IApiItemContainerMixinOptions, IApiNameMixinOptions {}
/** /**
* Represents the entry point for an NPM package. * Represents an entry point for an NPM package.
* *
* @remarks * @remarks
* *
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of * This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
* API declarations. * API declarations.
* *
* `ApiEntryPoint` represents the entry point to an NPM package. API Extractor does not currently support * `ApiEntryPoint` represents an entry point to an NPM package.
* analysis of multiple entry points, but the `ApiEntryPoint` object is included to support a future feature.
* In the current implementation, `ApiEntryPoint.importPath` is always the empty string.
* *
* For example, suppose the package.json file looks like this: * For example, suppose the package.json file looks like this:
* *
@@ -37,7 +35,7 @@ export interface IApiEntryPointOptions extends IApiItemContainerMixinOptions, IA
* } * }
* ``` * ```
* *
* In this example, the `ApiEntryPoint` would represent the TypeScript module for `./lib/index.js`. * In this example, the main `ApiEntryPoint` would represent the TypeScript module for `./lib/index.js`.
* @public * @public
*/ */
export class ApiEntryPoint extends ApiItemContainerMixin(ApiNameMixin(ApiItem)) { export class ApiEntryPoint extends ApiItemContainerMixin(ApiNameMixin(ApiItem)) {
@@ -62,12 +60,7 @@ export class ApiEntryPoint extends ApiItemContainerMixin(ApiNameMixin(ApiItem))
/** /**
* The module path for this entry point, relative to the parent `ApiPackage`. In the current implementation, * The module path for this entry point, relative to the parent `ApiPackage`. In the current implementation,
* this is always the empty string, indicating the default entry point. * this is used to distinguish different entry points,
*
* @remarks
*
* API Extractor does not currently support analysis of multiple entry points. If that feature is implemented
* in the future, then the `ApiEntryPoint.importPath` will be used to distinguish different entry points,
* for example: `controls/Button` in `import { Button } from "example-package/controls/Button";`. * for example: `controls/Button` in `import { Button } from "example-package/controls/Button";`.
* *
* The `ApiEntryPoint.name` property stores the same value as `ApiEntryPoint.importPath`. * The `ApiEntryPoint.name` property stores the same value as `ApiEntryPoint.importPath`.

View File

@@ -209,6 +209,7 @@ interface IExtractorConfigParameters {
docModelIncludeForgottenExports: boolean; docModelIncludeForgottenExports: boolean;
enumMemberOrder: EnumMemberOrder; enumMemberOrder: EnumMemberOrder;
mainEntryPointFilePath: string; mainEntryPointFilePath: string;
mainEntryPointName: string;
messages: IExtractorMessagesConfig; messages: IExtractorMessagesConfig;
newlineKind: NewlineKind; newlineKind: NewlineKind;
omitTrimmingComments: boolean; omitTrimmingComments: boolean;
@@ -474,6 +475,7 @@ export class ExtractorConfig {
projectFolder, projectFolder,
packageJson, packageJson,
packageFolder, packageFolder,
mainEntryPointName,
mainEntryPointFilePath, mainEntryPointFilePath,
additionalEntryPoints, additionalEntryPoints,
bundledPackages, bundledPackages,
@@ -509,7 +511,7 @@ export class ExtractorConfig {
this.packageJson = packageJson; this.packageJson = packageJson;
this.packageFolder = packageFolder; this.packageFolder = packageFolder;
this.mainEntryPointFilePath = { this.mainEntryPointFilePath = {
modulePath: '', modulePath: mainEntryPointName,
filePath: mainEntryPointFilePath, filePath: mainEntryPointFilePath,
}; };
this.additionalEntryPoints = additionalEntryPoints; this.additionalEntryPoints = additionalEntryPoints;
@@ -1003,6 +1005,8 @@ export class ExtractorConfig {
tokenContext, tokenContext,
); );
const mainEntryPointName = configObject.mainEntryPointName ?? '';
if (!ExtractorConfig.hasDtsFileExtension(mainEntryPointFilePath)) { if (!ExtractorConfig.hasDtsFileExtension(mainEntryPointFilePath)) {
throw new Error('The "mainEntryPointFilePath" value is not a declaration file: ' + mainEntryPointFilePath); throw new Error('The "mainEntryPointFilePath" value is not a declaration file: ' + mainEntryPointFilePath);
} }
@@ -1289,6 +1293,7 @@ export class ExtractorConfig {
packageJson, packageJson,
packageFolder, packageFolder,
mainEntryPointFilePath, mainEntryPointFilePath,
mainEntryPointName,
additionalEntryPoints, additionalEntryPoints,
bundledPackages, bundledPackages,
tsconfigFilePath, tsconfigFilePath,

View File

@@ -491,6 +491,11 @@ export interface IConfigFile {
*/ */
mainEntryPointFilePath: string; mainEntryPointFilePath: string;
/**
* Specifies the import path of the entrypoint used as the starting point for analysis.
*/
mainEntryPointName: string;
/** /**
* {@inheritDoc IExtractorMessagesConfig} * {@inheritDoc IExtractorMessagesConfig}
*/ */

View File

@@ -291,6 +291,7 @@ export class ApiModelGenerator {
docComment: packageDocComment, docComment: packageDocComment,
tsdocConfiguration: this._collector.extractorConfig.tsdocConfiguration, tsdocConfiguration: this._collector.extractorConfig.tsdocConfiguration,
projectFolderUrl: this._collector.extractorConfig.projectFolderUrl, projectFolderUrl: this._collector.extractorConfig.projectFolderUrl,
preserveMemberOrder: true,
}); });
this._apiModel.addMember(apiPackage); this._apiModel.addMember(apiPackage);

View File

@@ -3,6 +3,8 @@
// ("mainEntryPointFilePath" is required) // ("mainEntryPointFilePath" is required)
"mainEntryPointName": "",
"bundledPackages": [], "bundledPackages": [],
"newlineKind": "crlf", "newlineKind": "crlf",

View File

@@ -47,6 +47,11 @@
*/ */
"mainEntryPointFilePath": "<projectFolder>/lib/index.d.ts", "mainEntryPointFilePath": "<projectFolder>/lib/index.d.ts",
/**
* Specifies the import path of the entrypoint used as the starting point for analysis.
*/
// "mainEntryPointName": "",
/** /**
* A list of NPM package names whose exports should be treated as part of this package. * A list of NPM package names whose exports should be treated as part of this package.
* *

View File

@@ -23,6 +23,11 @@
"type": "string" "type": "string"
}, },
"mainEntryPointName": {
"description": "Specifies the import path of the entrypoint used as the starting point for analysis.",
"type": "string"
},
"additionalEntryPoints": { "additionalEntryPoints": {
"description": "Specifies the .d.ts files to be used as the starting points for analysis.", "description": "Specifies the .d.ts files to be used as the starting points for analysis.",
"type": "array", "type": "array",

View File

@@ -223,39 +223,8 @@ function resolveItemURI(item: ApiItemLike, entryPoint?: ApiEntryPoint): string {
} }
function itemExcerptText(excerpt: Excerpt, apiPackage: ApiPackage, parent?: ApiTypeParameterListMixin) { function itemExcerptText(excerpt: Excerpt, apiPackage: ApiPackage, parent?: ApiTypeParameterListMixin) {
const DISCORD_API_TYPES_VERSION = 'v10';
const DISCORD_API_TYPES_DOCS_URL = `https://discord-api-types.dev/api/discord-api-types-${DISCORD_API_TYPES_VERSION}`;
return excerpt.spannedTokens.map((token) => { return excerpt.spannedTokens.map((token) => {
if (token.kind === ExcerptTokenKind.Reference) { if (token.kind === ExcerptTokenKind.Reference) {
const source = token.canonicalReference?.source;
const symbol = token.canonicalReference?.symbol;
if (source && 'packageName' in source && source.packageName === 'discord-api-types' && symbol) {
const { meaning, componentPath: path } = symbol;
let href = DISCORD_API_TYPES_DOCS_URL;
// dapi-types doesn't have routes for class members
// so we can assume this member is for an enum
if (meaning === 'member' && path && 'parent' in path) {
// unless it's a variable like FormattingPatterns.Role
if (path.parent.toString() === '__type') {
href += `#${token.text.split('.')[0]}`;
} else {
href += `/enum/${path.parent}#${path.component}`;
}
} else if (meaning === 'type' || meaning === 'var') {
href += `#${token.text}`;
} else {
href += `/${meaning}/${token.text}`;
}
return {
text: token.text,
href,
};
}
if (token.canonicalReference) { if (token.canonicalReference) {
const resolved = resolveCanonicalReference(token.canonicalReference, apiPackage); const resolved = resolveCanonicalReference(token.canonicalReference, apiPackage);
@@ -316,9 +285,6 @@ function itemExcerptText(excerpt: Excerpt, apiPackage: ApiPackage, parent?: ApiT
} }
function itemTsDoc(item: DocNode, apiItem: ApiItem) { function itemTsDoc(item: DocNode, apiItem: ApiItem) {
const DISCORD_API_TYPES_VERSION = 'v10';
const DISCORD_API_TYPES_DOCS_URL = `https://discord-api-types.dev/api/discord-api-types-${DISCORD_API_TYPES_VERSION}`;
const createNode = (node: DocNode): any => { const createNode = (node: DocNode): any => {
switch (node.kind) { switch (node.kind) {
case DocNodeKind.PlainText: case DocNodeKind.PlainText:
@@ -380,29 +346,6 @@ function itemTsDoc(item: DocNode, apiItem: ApiItem) {
}; };
} }
if (resolved && resolved.package === 'discord-api-types') {
const { displayName, kind, members, containerKey } = resolved.item;
let href = DISCORD_API_TYPES_DOCS_URL;
// dapi-types doesn't have routes for class members
// so we can assume this member is for an enum
if (kind === 'enum' && members?.[0]) {
href += `/enum/${displayName}#${members[0].displayName}`;
} else if (kind === 'type' || kind === 'var') {
href += `#${displayName}`;
} else {
href += `/${kind}/${displayName}`;
}
return {
kind: DocNodeKind.LinkTag,
text: displayName,
containerKey,
uri: href,
members: members?.map((member) => `.${member.displayName}`).join('') ?? '',
};
}
return { return {
kind: DocNodeKind.LinkTag, kind: DocNodeKind.LinkTag,
text: linkText ?? foundItem?.displayName ?? resolved!.item.displayName, text: linkText ?? foundItem?.displayName ?? resolved!.item.displayName,
@@ -545,8 +488,6 @@ function itemInfo(item: ApiDeclaredItem) {
function resolveFileUrl(item: ApiDeclaredItem) { function resolveFileUrl(item: ApiDeclaredItem) {
const { const {
displayName,
kind,
sourceLocation: { fileUrl, fileLine }, sourceLocation: { fileUrl, fileLine },
} = item; } = item;
if (fileUrl?.includes('/node_modules/')) { if (fileUrl?.includes('/node_modules/')) {
@@ -571,20 +512,12 @@ function resolveFileUrl(item: ApiDeclaredItem) {
// https://github.com/discordjs/discord.js/tree/main/node_modules/.pnpm/discord-api-types@0.37.97/node_modules/discord-api-types/payloads/v10/gateway.d.ts#L240 // https://github.com/discordjs/discord.js/tree/main/node_modules/.pnpm/discord-api-types@0.37.97/node_modules/discord-api-types/payloads/v10/gateway.d.ts#L240
if (pkgName === 'discord-api-types') { if (pkgName === 'discord-api-types') {
const DISCORD_API_TYPES_VERSION = 'v10'; let currentItem = item;
const DISCORD_API_TYPES_DOCS_URL = `https://discord-api-types.dev/api/discord-api-types-${DISCORD_API_TYPES_VERSION}`; while (currentItem.parent && currentItem.parent.kind !== ApiItemKind.EntryPoint)
let href = DISCORD_API_TYPES_DOCS_URL; currentItem = currentItem.parent as ApiDeclaredItem;
if (kind === ApiItemKind.EnumMember) {
href += `/enum/${item.parent!.displayName}#${displayName}`;
} else if (kind === ApiItemKind.TypeAlias || kind === ApiItemKind.Variable) {
href += `#${displayName}`;
} else {
href += `/${kindToMeaning.get(kind)}/${displayName}`;
}
return { return {
sourceURL: href, sourceURL: `/docs/packages/${pkgName}/${version}/${(currentItem.parent as ApiEntryPoint).importPath}/${currentItem.displayName}:${currentItem.kind}`,
}; };
} }
} else if (fileUrl?.includes('/dist/') && fileUrl.includes('/main/packages/')) { } else if (fileUrl?.includes('/dist/') && fileUrl.includes('/main/packages/')) {