@jsdocs-io/extractor
Version:
The API extractor for npm packages powering jsdocs.io
474 lines (429 loc) • 15.8 kB
TypeScript
import { SourceFile, ModuleDeclaration, Project } from 'ts-morph';
import * as effect_Cause from 'effect/Cause';
import * as effect_Types from 'effect/Types';
import { Context, Effect } from 'effect';
import * as effect_Scope from 'effect/Scope';
import * as read_pkg from 'read-pkg';
import { NormalizedPackageJson } from 'read-pkg';
import { DocComment } from '@microsoft/tsdoc';
type ExtractedClass = {
kind: "class";
id: string;
name: string;
docs: string[];
file: string;
line: number;
signature: string;
constructors: ExtractedClassConstructor[];
properties: ExtractedClassProperty[];
methods: ExtractedClassMethod[];
};
type ExtractedClassConstructor = {
kind: "class-constructor";
id: string;
name: string;
docs: string[];
file: string;
line: number;
signature: string;
};
type ExtractedClassProperty = {
kind: "class-property";
id: string;
name: string;
docs: string[];
file: string;
line: number;
signature: string;
};
type ExtractedClassMethod = {
kind: "class-method";
id: string;
name: string;
docs: string[];
file: string;
line: number;
signature: string;
};
type ExtractedEnum = {
kind: "enum";
id: string;
name: string;
docs: string[];
file: string;
line: number;
signature: string;
members: ExtractedEnumMember[];
};
type ExtractedEnumMember = {
kind: "enum-member";
id: string;
name: string;
docs: string[];
file: string;
line: number;
signature: string;
};
type ExtractedFunction = {
kind: "function";
id: string;
name: string;
docs: string[];
file: string;
line: number;
signature: string;
};
type ExtractedInterface = {
kind: "interface";
id: string;
name: string;
docs: string[];
file: string;
line: number;
signature: string;
properties: ExtractedInterfaceProperty[];
methods: ExtractedInterfaceMethod[];
constructSignatures: ExtractedInterfaceConstructSignature[];
callSignatures: ExtractedInterfaceCallSignature[];
indexSignatures: ExtractedInterfaceIndexSignature[];
getAccessors: ExtractedInterfaceGetAccessor[];
setAccessors: ExtractedInterfaceSetAccessor[];
};
type ExtractedInterfaceProperty = {
kind: "interface-property";
id: string;
name: string;
docs: string[];
file: string;
line: number;
signature: string;
};
type ExtractedInterfaceMethod = {
kind: "interface-method";
id: string;
name: string;
docs: string[];
file: string;
line: number;
signature: string;
};
type ExtractedInterfaceConstructSignature = {
kind: "interface-construct-signature";
id: string;
name: string;
docs: string[];
file: string;
line: number;
signature: string;
};
type ExtractedInterfaceCallSignature = {
kind: "interface-call-signature";
id: string;
name: string;
docs: string[];
file: string;
line: number;
signature: string;
};
type ExtractedInterfaceIndexSignature = {
kind: "interface-index-signature";
id: string;
name: string;
docs: string[];
file: string;
line: number;
signature: string;
};
type ExtractedInterfaceGetAccessor = {
kind: "interface-get-accessor";
id: string;
name: string;
docs: string[];
file: string;
line: number;
signature: string;
};
type ExtractedInterfaceSetAccessor = {
kind: "interface-set-accessor";
id: string;
name: string;
docs: string[];
file: string;
line: number;
signature: string;
};
type ExtractedTypeAlias = {
kind: "type";
id: string;
name: string;
docs: string[];
file: string;
line: number;
signature: string;
};
type ExtractedVariable = {
kind: "variable";
id: string;
name: string;
docs: string[];
file: string;
line: number;
signature: string;
};
/**
`ExtractDeclarationsOptions` contains all the options
for calling {@link extractDeclarations}.
@internal
*/
type ExtractDeclarationsOptions = {
/**
Name of the container that contains the top-level declarations
(e.g., a namespace's name). This is used to generate declaration IDs.
*/
containerName: string;
/** Container that contains the top-level declarations. */
container: SourceFile | ModuleDeclaration;
/** Maximum extraction depth for nested namespaces. */
maxDepth: number;
/**
Instance of a `ts-morph` `Project`. This is used to find ambient modules.
*/
project?: Project;
/**
Name of the package being analyzed. This is used to filter ambient modules.
*/
pkgName?: string;
};
/**
`ExtractedDeclaration` is the union of all possible top-level declarations
that can be extracted from a package, module or namespace.
*/
type ExtractedDeclaration = ExtractedVariable | ExtractedFunction | ExtractedClass | ExtractedInterface | ExtractedEnum | ExtractedTypeAlias | ExtractedNamespace;
/**
`ExtractedDeclarationKind` is the union of all discriminators
used to detect the kind of top-level declaration.
*/
type ExtractedDeclarationKind = ExtractedDeclaration["kind"];
/**
`extractDeclarations` extracts the top-level declarations found in a container
and/or a project.
@param options - {@link ExtractDeclarationsOptions}
@internal
*/
declare const extractDeclarations: ({ containerName, container, maxDepth, project, pkgName, }: ExtractDeclarationsOptions) => Promise<ExtractedDeclaration[]>;
type ExtractedNamespace = {
kind: "namespace";
id: string;
name: string;
docs: string[];
file: string;
line: number;
signature: string;
declarations: ExtractedDeclaration[];
};
/**
`AllExtractedDeclaration` is the union of all possible declarations
that can be extracted, with some being found only in other declarations
(e.g., class method declarations are found only in a class declaration).
*/
type AllExtractedDeclaration = ExtractedVariable | ExtractedFunction | ExtractedClass | ExtractedClassConstructor | ExtractedClassProperty | ExtractedClassMethod | ExtractedInterface | ExtractedInterfaceProperty | ExtractedInterfaceMethod | ExtractedInterfaceConstructSignature | ExtractedInterfaceCallSignature | ExtractedInterfaceIndexSignature | ExtractedInterfaceGetAccessor | ExtractedInterfaceSetAccessor | ExtractedEnum | ExtractedEnumMember | ExtractedTypeAlias | ExtractedNamespace;
/**
`AllExtractedDeclarationKind` is the union of all discriminators
used to detect the kind of declaration.
*/
type AllExtractedDeclarationKind = AllExtractedDeclaration["kind"];
/** @internal */
type InstallPackageOptions = {
pkg: string;
cwd: string;
};
declare const InstallPackageError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & {
readonly _tag: "InstallPackageError";
} & Readonly<A>;
/** @internal */
declare class InstallPackageError extends InstallPackageError_base<{
cause?: unknown;
}> {
}
declare const PackageManager_base: Context.TagClass<PackageManager, "PackageManager", {
readonly installPackage: ({ pkg, cwd, }: InstallPackageOptions) => Effect.Effect<string[], InstallPackageError>;
}>;
/** @internal */
declare class PackageManager extends PackageManager_base {
}
/** @internal */
declare const bunPackageManager: (bunPath?: string) => {
readonly installPackage: ({ pkg, cwd, }: InstallPackageOptions) => Effect.Effect<string[], InstallPackageError>;
};
declare const ProjectError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & {
readonly _tag: "ProjectError";
} & Readonly<A>;
/** @internal */
declare class ProjectError extends ProjectError_base<{
readonly cause?: unknown;
}> {
}
/**
`ExtractPackageApiOptions` contains all the options
for calling {@link extractPackageApi}.
*/
type ExtractPackageApiOptions = {
/**
Package to extract the API from.
This can be either a package name (e.g., `foo`) or any other query
that can be passed to `bun add` (e.g., `foo@1.0.0`).
@see {@link https://bun.sh/docs/cli/add | Bun docs}
*/
pkg: string;
/**
Specific subpath to consider in a package.
If a package has multiple entrypoints listed in the `exports` property
of its `package.json`, use `subpath` to select a specific one by its name
(e.g., `someFeature`).
@defaultValue `.` (package root)
@see {@link https://nodejs.org/api/packages.html#subpath-exports | Node.js docs}
@see {@link https://github.com/lukeed/resolve.exports | resolve.exports docs}
*/
subpath?: string;
/**
Packages can have deeply nested modules and namespaces.
Use `maxDepth` to limit the depth of the extraction.
Declarations nested at levels deeper than this value will be ignored.
@defaultValue 5
*/
maxDepth?: number;
/**
Absolute path to the `bun` executable.
Used to locate bun if it's not in `PATH`.
@defaultValue `bun`
*/
bunPath?: string;
};
/**
`PackageApi` contains all the information extracted from a package.
*/
type PackageApi = {
/** Package name (e.g., `foo`). */
name: string;
/** Package version number (e.g., `1.0.0`). */
version: string;
/**
Package subpath selected when extracting the API (e.g., `.`, `someFeature`).
@see {@link ExtractPackageApiOptions.subpath}
@see {@link https://nodejs.org/api/packages.html#subpath-exports | Node.js docs}
*/
subpath: string;
/**
Type declarations file, resolved from the selected `subpath`,
that acts as the entrypoint for the package (e.g., `index.d.ts`).
*/
types: string;
/**
Package description extracted from the `types` file if a
JSDoc comment with the `@packageDocumentation` tag is found.
*/
overview: string | undefined;
/** Declarations exported (or re-exported) by the package. */
declarations: ExtractedDeclaration[];
/**
All packages resolved and installed when installing the package (included).
@example
```ts
["foo@1.0.0", "bar@2.0.0", "baz@3.0.0"]
```
*/
packages: string[];
/** Timestamp of when the package was analyzed. */
analyzedAt: string;
/** Package analysis duration in milliseconds. */
analyzedIn: number;
};
/**
`extractPackageApi` extracts the API from a package.
If the extraction succeeds, `extractPackageApi` returns a {@link PackageApi} object.
If the extraction fails, `extractPackageApi` throws an error.
Warning: The extraction process is slow and blocks the main thread, using workers is recommended.
@example
```ts
const packageApi = await extractPackageApi({
pkg: "foo", // Extract API from npm package `foo` [Required]
subpath: ".", // Select subpath `.` (root subpath) [Optional]
maxDepth: 5, // Maximum depth for analyzing nested namespaces [Optional]
bunPath: "bun" // Absolute path to the `bun` executable [Optional]
});
console.log(JSON.stringify(packageApi, null, 2));
```
@param options - {@link ExtractPackageApiOptions}
@returns A {@link PackageApi} object
*/
declare const extractPackageApi: ({ pkg, subpath, maxDepth, bunPath, }: ExtractPackageApiOptions) => Promise<PackageApi>;
/** @internal */
type WorkDir = {
readonly path: string;
readonly close: () => Promise<void>;
};
declare const WorkDirError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & {
readonly _tag: "WorkDirError";
} & Readonly<A>;
/** @internal */
declare class WorkDirError extends WorkDirError_base<{
cause?: unknown;
}> {
}
/** @internal */
declare const workDir: Effect.Effect<{
path: string;
close: () => Promise<void>;
}, WorkDirError, effect_Scope.Scope>;
declare const PackageTypesError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & {
readonly _tag: "PackageTypesError";
} & Readonly<A>;
/** @internal */
declare class PackageTypesError extends PackageTypesError_base {
}
/**
`packageTypes` resolves the types entrypoint file (e.g., `index.d.ts`).
@param pkgJson - the contents of `package.json`
@param subpath - the selected subpath from the `exports` property of `package.json`
@internal
*/
declare const packageTypes: (pkgJson: Partial<NormalizedPackageJson>, subpath: string) => Effect.Effect<string, PackageTypesError, never>;
declare const PackageJsonError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & {
readonly _tag: "PackageJsonError";
} & Readonly<A>;
/** @internal */
declare class PackageJsonError extends PackageJsonError_base<{
cause?: unknown;
}> {
}
/** @internal */
declare const packageJson: (pkgDir: string) => Effect.Effect<read_pkg.NormalizedPackageJson, PackageJsonError, never>;
declare const PackageDeclarationsError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & {
readonly _tag: "PackageDeclarationsError";
} & Readonly<A>;
/** @internal */
declare class PackageDeclarationsError extends PackageDeclarationsError_base<{
cause?: unknown;
}> {
}
/** @internal */
declare const extractPackageApiEffect: ({ pkg, subpath, maxDepth, }: Omit<ExtractPackageApiOptions, "bunPath">) => Effect.Effect<PackageApi, InstallPackageError | ProjectError | PackageDeclarationsError | PackageJsonError | PackageTypesError | WorkDirError, PackageManager | effect_Scope.Scope>;
declare const PackageNameError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & {
readonly _tag: "PackageNameError";
} & Readonly<A>;
/** @internal */
declare class PackageNameError extends PackageNameError_base<{
warnings?: string[];
errors?: string[];
}> {
}
/** @internal */
declare const packageName: (pkg: string) => Effect.Effect<string, PackageNameError, never>;
/**
`parseDocComment` parses a JSDoc comment using `@microsoft/tsdoc`.
Parsed comments are memoized.
@param s - the raw string comment
@internal
*/
declare const parseDocComment: (s: string) => DocComment;
export { type AllExtractedDeclaration, type AllExtractedDeclarationKind, type ExtractDeclarationsOptions, type ExtractPackageApiOptions, type ExtractedClass, type ExtractedClassConstructor, type ExtractedClassMethod, type ExtractedClassProperty, type ExtractedDeclaration, type ExtractedDeclarationKind, type ExtractedEnum, type ExtractedEnumMember, type ExtractedFunction, type ExtractedInterface, type ExtractedInterfaceCallSignature, type ExtractedInterfaceConstructSignature, type ExtractedInterfaceGetAccessor, type ExtractedInterfaceIndexSignature, type ExtractedInterfaceMethod, type ExtractedInterfaceProperty, type ExtractedInterfaceSetAccessor, type ExtractedNamespace, type ExtractedTypeAlias, type ExtractedVariable, InstallPackageError, type InstallPackageOptions, type PackageApi, PackageDeclarationsError, PackageJsonError, PackageManager, PackageNameError, PackageTypesError, ProjectError, type WorkDir, WorkDirError, bunPackageManager, extractDeclarations, extractPackageApi, extractPackageApiEffect, packageJson, packageName, packageTypes, parseDocComment, workDir };