mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-09 16:13:31 +01:00
refactor: minify api.json by shortening keys (#9971)
* refactor: minify api.json by shortening keys * fix: links to other packages * refactor: get doclink from canonicalReference, not model * fix: types * fix: again * fix: @link tags with alt texts
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
import { Buffer } from 'node:buffer';
|
||||
import path from 'node:path';
|
||||
import util from 'node:util';
|
||||
import { TSDocConfiguration } from '@microsoft/tsdoc';
|
||||
import { DeclarationReference } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
|
||||
import { TSDocConfigFile } from '@microsoft/tsdoc-config';
|
||||
@@ -29,10 +31,58 @@ export interface IApiPackageOptions
|
||||
extends IApiItemContainerMixinOptions,
|
||||
IApiNameMixinOptions,
|
||||
IApiDocumentedItemOptions {
|
||||
dependencies?: Record<string, string> | undefined;
|
||||
projectFolderUrl?: string | undefined;
|
||||
tsdocConfiguration: TSDocConfiguration;
|
||||
}
|
||||
|
||||
const MinifyJSONMapping = {
|
||||
canonicalReference: 'c',
|
||||
constraintTokenRange: 'ctr',
|
||||
dependencies: 'dp',
|
||||
defaultTypeTokenRange: 'dtr',
|
||||
docComment: 'd',
|
||||
endIndex: 'en',
|
||||
excerptTokens: 'ex',
|
||||
extendsTokenRange: 'etr',
|
||||
extendsTokenRanges: 'etrs',
|
||||
fileColumn: 'co',
|
||||
fileLine: 'l',
|
||||
fileUrlPath: 'pat',
|
||||
implementsTokenRanges: 'itrs',
|
||||
initializerTokenRange: 'itr',
|
||||
isAbstract: 'ab',
|
||||
isOptional: 'op',
|
||||
isProtected: 'pr',
|
||||
isReadonly: 'ro',
|
||||
isRest: 'rs',
|
||||
isStatic: 'sta',
|
||||
kind: 'k',
|
||||
members: 'ms',
|
||||
metadata: 'meta',
|
||||
name: 'n',
|
||||
oldestForwardsCompatibleVersion: 'ov',
|
||||
overloadIndex: 'oi',
|
||||
parameterName: 'pn',
|
||||
parameterTypeTokenRange: 'ptr',
|
||||
parameters: 'ps',
|
||||
preserveMemberOrder: 'pmo',
|
||||
projectFolderUrl: 'pdir',
|
||||
propertyTypeTokenRange: 'prtr',
|
||||
releaseTag: 'r',
|
||||
returnTypeTokenRange: 'rtr',
|
||||
schemaVersion: 'v',
|
||||
startIndex: 'st',
|
||||
text: 't',
|
||||
toolPackage: 'tpk',
|
||||
toolVersion: 'tv',
|
||||
tsdocConfig: 'ts',
|
||||
typeParameterName: 'tp',
|
||||
typeParameters: 'tps',
|
||||
typeTokenRange: 'ttr',
|
||||
variableTypeTokenRange: 'vtr',
|
||||
};
|
||||
|
||||
export interface IApiPackageMetadataJson {
|
||||
/**
|
||||
* To support forwards compatibility, the `oldestForwardsCompatibleVersion` field tracks the oldest schema version
|
||||
@@ -77,10 +127,15 @@ export interface IApiPackageMetadataJson {
|
||||
* Normally this configuration is loaded from the project's tsdoc.json file. It is stored
|
||||
* in the .api.json file so that doc comments can be parsed accurately when loading the file.
|
||||
*/
|
||||
tsdocConfig: JsonObject;
|
||||
tsdocConfig?: JsonObject;
|
||||
}
|
||||
|
||||
export interface IApiPackageJson extends IApiItemJson {
|
||||
/**
|
||||
* Names of packages in the same monorepo this one uses mapped to the version of said package.
|
||||
*/
|
||||
dependencies?: Record<string, string>;
|
||||
|
||||
/**
|
||||
* A file header that stores metadata about the tool that wrote the *.api.json file.
|
||||
*/
|
||||
@@ -141,11 +196,31 @@ export class ApiPackage extends ApiItemContainerMixin(ApiNameMixin(ApiDocumented
|
||||
|
||||
private readonly _projectFolderUrl?: string | undefined;
|
||||
|
||||
private readonly _dependencies?: Record<string, string> | undefined;
|
||||
|
||||
public constructor(options: IApiPackageOptions) {
|
||||
super(options);
|
||||
|
||||
this._tsdocConfiguration = options.tsdocConfiguration;
|
||||
this._projectFolderUrl = options.projectFolderUrl;
|
||||
|
||||
if (options.dependencies) {
|
||||
this._dependencies = options.dependencies;
|
||||
} else {
|
||||
const packageJson = PackageJsonLookup.instance.tryLoadPackageJsonFor('.');
|
||||
if (packageJson?.dependencies) {
|
||||
this._dependencies = {};
|
||||
for (const [pack, semVer] of Object.entries(packageJson.dependencies)) {
|
||||
const pathToPackage = path.join('..', pack.includes('/') ? pack.slice(pack.lastIndexOf('/')) : pack);
|
||||
if (semVer === 'workspace:^') {
|
||||
this._dependencies[pack] =
|
||||
PackageJsonLookup.instance.tryLoadPackageJsonFor(pathToPackage)?.version ?? 'unknown';
|
||||
} else if (FileSystem.exists(pathToPackage)) {
|
||||
this._dependencies[pack] = semVer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,11 +234,17 @@ export class ApiPackage extends ApiItemContainerMixin(ApiNameMixin(ApiDocumented
|
||||
super.onDeserializeInto(options, context, jsonObject);
|
||||
|
||||
options.projectFolderUrl = jsonObject.projectFolderUrl;
|
||||
options.dependencies = jsonObject.dependencies;
|
||||
}
|
||||
|
||||
public static loadFromJsonFile(apiJsonFilename: string): ApiPackage {
|
||||
const jsonObject: IApiPackageJson = JsonFile.load(apiJsonFilename);
|
||||
return this.loadFromJson(JsonFile.load(apiJsonFilename), apiJsonFilename);
|
||||
}
|
||||
|
||||
public static loadFromJson(rawJson: any, apiJsonFilename: string = ''): ApiPackage {
|
||||
const jsonObject =
|
||||
MinifyJSONMapping.metadata in rawJson ? this._mapFromMinified(rawJson) : (rawJson as IApiPackageJson);
|
||||
if (!jsonObject?.metadata) throw new Error(util.inspect(rawJson, { depth: 2 }));
|
||||
if (!jsonObject?.metadata || typeof jsonObject.metadata.schemaVersion !== 'number') {
|
||||
throw new Error(
|
||||
`Error loading ${apiJsonFilename}:` +
|
||||
@@ -212,7 +293,7 @@ export class ApiPackage extends ApiItemContainerMixin(ApiNameMixin(ApiDocumented
|
||||
|
||||
const tsdocConfiguration: TSDocConfiguration = new TSDocConfiguration();
|
||||
|
||||
if (versionToDeserialize >= ApiJsonSchemaVersion.V_1004) {
|
||||
if (versionToDeserialize >= ApiJsonSchemaVersion.V_1004 && 'tsdocConfiguration' in jsonObject) {
|
||||
const tsdocConfigFile: TSDocConfigFile = TSDocConfigFile.loadFromObject(jsonObject.metadata.tsdocConfig);
|
||||
if (tsdocConfigFile.hasErrors) {
|
||||
throw new Error(`Error loading ${apiJsonFilename}:\n` + tsdocConfigFile.getErrorSummary());
|
||||
@@ -251,6 +332,10 @@ export class ApiPackage extends ApiItemContainerMixin(ApiNameMixin(ApiDocumented
|
||||
return this.members as readonly ApiEntryPoint[];
|
||||
}
|
||||
|
||||
public get dependencies(): Record<string, string> | undefined {
|
||||
return this._dependencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* The TSDoc configuration that was used when analyzing the API for this package.
|
||||
*
|
||||
@@ -306,9 +391,13 @@ export class ApiPackage extends ApiItemContainerMixin(ApiNameMixin(ApiDocumented
|
||||
jsonObject.projectFolderUrl = this.projectFolderUrl;
|
||||
}
|
||||
|
||||
if (this._dependencies) {
|
||||
jsonObject.dependencies = this._dependencies;
|
||||
}
|
||||
|
||||
this.serializeInto(jsonObject);
|
||||
if (ioptions.minify) {
|
||||
FileSystem.writeFile(apiJsonFilename, Buffer.from(JSON.stringify(jsonObject), 'utf8'), {
|
||||
FileSystem.writeFile(apiJsonFilename, Buffer.from(JSON.stringify(this._mapToMinified(jsonObject)), 'utf8'), {
|
||||
ensureFolderExists: ioptions.ensureFolderExists ?? true,
|
||||
});
|
||||
} else {
|
||||
@@ -322,4 +411,47 @@ export class ApiPackage extends ApiItemContainerMixin(ApiNameMixin(ApiDocumented
|
||||
public override buildCanonicalReference(): DeclarationReference {
|
||||
return DeclarationReference.package(this.name);
|
||||
}
|
||||
|
||||
private _mapToMinified(jsonObject: IApiPackageJson) {
|
||||
const mapper = (item: any): any => {
|
||||
if (Array.isArray(item)) return item.map(mapper);
|
||||
else {
|
||||
const result: any = {};
|
||||
for (const key of Object.keys(item)) {
|
||||
if (key === 'dependencies') {
|
||||
result[MinifyJSONMapping.dependencies] = item.dependencies;
|
||||
} else
|
||||
result[MinifyJSONMapping[key as keyof typeof MinifyJSONMapping]] =
|
||||
typeof item[key] === 'object' ? mapper(item[key]) : item[key];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
return mapper(jsonObject);
|
||||
}
|
||||
|
||||
private static _mapFromMinified(jsonObject: any): IApiPackageJson {
|
||||
const mapper = (item: any): any => {
|
||||
if (Array.isArray(item)) return item.map(mapper);
|
||||
else {
|
||||
const result: any = {};
|
||||
for (const key of Object.keys(item)) {
|
||||
if (key === MinifyJSONMapping.dependencies) {
|
||||
result.dependencies = item[MinifyJSONMapping.dependencies];
|
||||
} else
|
||||
result[
|
||||
Object.keys(MinifyJSONMapping).find(
|
||||
(look) => MinifyJSONMapping[look as keyof typeof MinifyJSONMapping] === key,
|
||||
)!
|
||||
] = typeof item[key] === 'object' ? mapper(item[key]) : item[key];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
return mapper(jsonObject) as IApiPackageJson;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,13 +96,18 @@ export enum ApiJsonSchemaVersion {
|
||||
*/
|
||||
V_1012 = 1_012,
|
||||
|
||||
/**
|
||||
* Make tsdocConfiguration optional
|
||||
*/
|
||||
V_1013 = 1_013,
|
||||
|
||||
/**
|
||||
* The current latest .api.json schema version.
|
||||
*
|
||||
* IMPORTANT: When incrementing this number, consider whether `OLDEST_SUPPORTED` or `OLDEST_FORWARDS_COMPATIBLE`
|
||||
* should be updated.
|
||||
*/
|
||||
LATEST = V_1012,
|
||||
LATEST = V_1013,
|
||||
|
||||
/**
|
||||
* The oldest .api.json schema version that is still supported for backwards compatibility.
|
||||
@@ -119,7 +124,7 @@ export enum ApiJsonSchemaVersion {
|
||||
* if the older library would not be able to deserialize your new file format. Adding a nonessential field
|
||||
* is generally okay. Removing, modifying, or reinterpreting existing fields is NOT safe.
|
||||
*/
|
||||
OLDEST_FORWARDS_COMPATIBLE = V_1001,
|
||||
OLDEST_FORWARDS_COMPATIBLE = V_1013,
|
||||
}
|
||||
|
||||
export class DeserializerContext {
|
||||
|
||||
Reference in New Issue
Block a user