UNPKG

@modern-js/libuild

Version:

A tool for building modern JavaScript libraries

822 lines (725 loc) 24 kB
/// <reference types="less" /> /// <reference types="node" /> import type { AcceptedPlugin } from 'postcss'; import type { BuildOptions } from 'esbuild'; import { Message as EsbuildError } from 'esbuild'; import { ImportKind } from 'esbuild'; import type { Loader as Loader_2 } from 'esbuild'; import type { Metafile } from 'esbuild'; import type { MinifyOptions } from 'terser'; import type { OnLoadArgs } from 'esbuild'; import type { OnLoadResult } from 'esbuild'; import type { OnResolveArgs } from 'esbuild'; import type { OnResolveResult } from 'esbuild'; import type { Plugin as Plugin_2 } from 'postcss'; import type { ProcessOptions } from 'postcss'; import type { Options as sassOptions } from 'sass'; declare type AdditionalData = string | ((filePath: string) => string); declare type Append<T extends any[], U> = { 0: [U]; 1: [T[0], U]; 2: [T[0], T[1], U]; 3: [T[0], T[1], T[2], U]; 4: [T[0], T[1], T[2], T[3], U]; 5: [T[0], T[1], T[2], T[3], T[4], U]; 6: [T[0], T[1], T[2], T[3], T[4], T[5], U]; 7: [T[0], T[1], T[2], T[3], T[4], T[5], T[6], U]; 8: [T[0], T[1], T[2], T[3], T[4], T[5], T[6], T[7], U]; }[Measure<T["length"]>]; declare type ArgumentNames<T extends any[]> = FixedSizeArray<T["length"], string>; declare type AsArray<T> = T extends any[] ? T : [T]; export declare type Asset = { outdir?: string; /** * rebase relative url, default is true when format is 'cjs' or 'esm'. */ rebase?: boolean; name?: string | ((filePath: string) => string); /** * Specify the limit size to inline * @default 0 */ limit?: number; publicPath?: string | ((filePath: string) => string); }; export declare type AssetChunk = { type: 'asset'; contents: string | Buffer; /** * absolute file path */ fileName: string; originalFileName?: string; entryPoint?: string; }; export declare type AssetNormalized = Required<Asset>; declare class AsyncHook<T, R, AdditionalOptions = UnsetAdditionalOptions> extends Hook<T, R, AdditionalOptions> { tapAsync( options: string | Tap & IfSet<AdditionalOptions>, fn: (...args: Append<AsArray<T>, InnerCallback<Error, R>>) => void ): void; tapPromise( options: string | Tap & IfSet<AdditionalOptions>, fn: (...args: AsArray<T>) => Promise<R> ): void; } declare class AsyncSeriesBailHook<T, R, AdditionalOptions = UnsetAdditionalOptions> extends AsyncHook<T, R, AdditionalOptions> {} declare class AsyncSeriesHook<T, AdditionalOptions = UnsetAdditionalOptions> extends AsyncHook<T, void, AdditionalOptions> {} declare class AsyncSeriesWaterfallHook<T, AdditionalOptions = UnsetAdditionalOptions> extends AsyncHook<T, AsArray<T>[0], AdditionalOptions> {} export declare interface BuildConfig extends Required<Omit<CLIConfig, 'sideEffects' | 'chunkNames'>> { chunkNames?: string; sideEffects?: SideEffects; logger: ILogger; resolve: ResolveNormalized; asset: AssetNormalized; css_resolve: (id: string, dir: string) => string; node_resolve: (id: string, dir: string, kind?: ImportKind) => string; } export declare interface BuilderResolveOptions { kind?: ImportKind; importer?: string; resolveDir?: string; skipSideEffects?: boolean; } export declare interface BuilderResolveResult { path: string; suffix?: string; external?: boolean; sideEffects?: boolean; } export declare interface CacheValue extends Source { originCode: string; } export declare type Callback = (err?: any) => void; declare type Callback_2<E, T> = (error: E | null, result?: T) => void; export declare type Chunk = AssetChunk | JsChunk; export declare const enum ChunkType { chunk = "chunk", asset = "asset" } export declare interface CLIConfig extends UserConfig { /** * project root dir */ root?: string; } export declare interface CodeFrameFileOption { filePath: string; } /** * Compatible with esbuild */ export declare interface CodeFrameLineOption { filePath: string; lineText: string; start?: CodeFramePosition; length?: number; } export declare interface CodeFrameNormalOption { filePath: string; fileContent: string; start?: CodeFramePosition; end?: CodeFramePosition; } export declare type CodeFrameOption = CodeFrameFileOption | CodeFrameNormalOption | CodeFrameLineOption; export declare interface CodeFramePosition { line: number; column?: number; } export declare interface ControllerOption { /** * No stack displayed * @default `true` */ noStack?: boolean; /** * No color displayed * @default `false` */ noColor?: boolean; } declare type Define = Record<string, string>; export declare enum ErrorLevel { Ignore = 0, Warn = 1, Error = 2 } export { EsbuildError } export declare interface EsbuildResultInfo { errors: EsbuildError[]; warnings: EsbuildError[]; } declare type External_2 = (string | RegExp)[]; export declare type ExtraContext = Record<string, any>; declare type FixedSizeArray<T extends number, U> = T extends 0 ? void[] : ReadonlyArray<U> & { 0: U; length: T; }; export declare type Format = 'esm' | 'cjs' | 'umd' | 'iife'; export declare function formatError(err: Error | LibuildErrorInstance): string; declare type FullTap = Tap & { type: "sync" | "async" | "promise", fn: Function } declare type GenerateScopedNameFunction = (name: string, filename: string, css: string) => string; declare type Globals = Record<any, any>; declare class Hook<T, R, AdditionalOptions = UnsetAdditionalOptions> { constructor(args?: ArgumentNames<AsArray<T>>, name?: string); name: string | undefined; taps: FullTap[]; intercept(interceptor: HookInterceptor<T, R, AdditionalOptions>): void; isUsed(): boolean; callAsync(...args: Append<AsArray<T>, Callback_2<Error, R>>): void; promise(...args: AsArray<T>): Promise<R>; tap(options: string | Tap & IfSet<AdditionalOptions>, fn: (...args: AsArray<T>) => R): void; withOptions(options: TapOptions & IfSet<AdditionalOptions>): Omit<this, "call" | "callAsync" | "promise">; } declare interface HookInterceptor<T, R, AdditionalOptions = UnsetAdditionalOptions> { name?: string; tap?: (tap: FullTap & IfSet<AdditionalOptions>) => void; call?: (...args: any[]) => void; loop?: (...args: any[]) => void; error?: (err: Error) => void; result?: (result: R) => void; done?: () => void; register?: (tap: FullTap & IfSet<AdditionalOptions>) => FullTap & IfSet<AdditionalOptions>; } export declare interface IBuilderBase { build: () => Promise<void>; reBuild: (type: 'link' | 'change') => Promise<void>; close: (callack?: Callback) => void; } declare type IfSet<X> = X extends UnsetAdditionalOptions ? {} : X; export declare interface ILibuilder { name?: string; version: string; compilation: IBuilderBase; hooks: ILibuilderHooks; STAGE: ILibuilderStage; userConfig: CLIConfig; config: BuildConfig; plugins: LibuildPlugin[]; outputChunk: Map<string, Chunk>; virtualModule: Map<string, string>; init: (config: CLIConfig) => Promise<void>; build: () => Promise<void>; close: (callBack?: Callback) => Promise<void>; emitAsset: ((name: string, chunk: AssetChunk) => void) & ((name: string, chunk: JsChunk) => void) & ((name: string, chunk: string) => void); watchedFiles: Set<string>; addWatchFile: (id: string) => void; resolve: (source: string, options?: BuilderResolveOptions) => Promise<BuilderResolveResult>; loadSvgr: (path: string) => Promise<LoadSvgrResult | void>; getTransformContext: (path: string) => ITransformContext; getSourcemapContext: (path: string) => ISourcemapContext; report: (error: any) => void; throw: (message: string, option: LibuildErrorParams) => void; printErrors: () => void; getErrors: () => LibuildFailure; clearErrors: () => void; removeError: (...errors: LibuildErrorInstance[]) => void; } export declare interface ILibuilderHooks { /** * Asynchronous initialization. Executed after normalized `buildConfig` and `plugins`. */ initialize: AsyncSeriesHook<[], void>; /** * Equal to esbuild#onResolve and rollup#resolveId */ resolve: AsyncSeriesBailHook<[ResolveArgs], ResolveResult | undefined>; /** * Equal to esbuild#onLoad and rollup#load */ load: AsyncSeriesBailHook<[LoadArgs], LoadResult | undefined | void>; /** * */ transform: AsyncSeriesWaterfallHook<Source>; /** * Modify the chunk */ processAsset: AsyncSeriesWaterfallHook<[Chunk]>; /** * After esbuild onStart, also called by watchChange */ startCompilation: AsyncSeriesHook<[]>; /** * After esbuild onEnd, also called by watchChange */ endCompilation: AsyncSeriesHook<[LibuildFailure]>; /** * Post processing for assets */ processAssets: AsyncSeriesHook<[Map<string, Chunk>, LibuildManifest]>; /** * Watch related hook */ watchChange: SyncHook<[string[]]>; /** * Before close */ shutdown: AsyncSeriesHook<[]>; } export declare interface ILibuilderStage { /** * Execute Before Internal Plugin */ PRE_INTERNAL: number; /** * Execute After Internal Plugin */ POST_INTERNAL: number; } export declare abstract class ILogger { abstract timesLog: Map<Label, number>; abstract info(...msg: string[]): void; abstract warn(...msg: string[]): void; abstract error(...msg: string[]): void; abstract debug(...msg: string[]): void; abstract time(label: Label): void; abstract timeEnd(label: Label): void; } export declare interface ILoggerOptions { /** * @default 'info' */ level?: LogLevel; /** * @default false */ timestamp?: boolean; } declare type InnerCallback<E, T> = (error?: E | null | false, result?: T) => void; declare type Input = { [name: string]: string; } | string[]; export declare function insertSpace(rawLines: string, line: number, width: number): string; /** * we can't use instanceof LibuildError, because it may not be an singleton class * @param err * @returns */ export declare function isLibuildErrorInstance(err: unknown): err is LibuildError; export declare interface ISourcemapContext { addSourceMap: (pluginId: number, map?: SourceMap) => void; getInlineSourceMap: () => string; getSourceMap: () => SourceMap | undefined; getSourceMapChain: () => SourceMap[]; genPluginId: (id: string) => number; } export declare interface ITransformContext extends ISourcemapContext { addTransformResult: (pluginId: number, result: CacheValue) => void; getValidCache: (pluginId: number, code: string) => undefined | CacheValue; } export declare type JsChunk = { type: 'chunk'; contents: string; /** * absolute file path */ fileName: string; originalFileName?: string; map?: SourceMap; entryPoint?: string; modules?: Record<string, any>; isEntry: boolean; }; declare type Label = string; export declare class Libuilder implements ILibuilder { static run(config?: CLIConfig, name?: string): Promise<Libuilder | Libuilder[]>; static create(config?: CLIConfig, name?: string): Promise<Libuilder>; compilation: IBuilderBase; version: string; watchedFiles: Set<string>; hooks: ILibuilderHooks; STAGE: ILibuilderStage; userConfig: CLIConfig; config: BuildConfig; plugins: LibuildPlugin[]; outputChunk: Map<string, Chunk>; virtualModule: Map<string, string>; name?: string; private errors; private watcher?; private transformContextMap; private sourcemapContextMap; init(config: CLIConfig): Promise<void>; build(): Promise<void>; close(callback?: Callback): Promise<void>; emitAsset(name: string, chunk: string | Chunk): void; addWatchFile(id: string): void; resolve(_source: string, _opt?: BuilderResolveOptions): Promise<BuilderResolveResult>; loadSvgr(_path: string): Promise<void>; getTransformContext(path: string): TransformContext; getSourcemapContext(path: string): SourcemapContext; report(err: any): void; throw(message: string, opts?: LibuildErrorParams): void; printErrors(): void; getErrors(): LibuildFailure; clearErrors(): void; removeError(...errors: LibuildErrorInstance[]): void; } export declare class LibuildError extends Error implements LibuildErrorInstance { static from(err: unknown, opt?: LibuildErrorParams): LibuildError; readonly prefixCode: string; readonly code: string; readonly reason?: string; readonly hint?: string; readonly referenceUrl?: string; private codeFrame?; private _controller; private readonly _level; constructor(code: string, message: string, opts?: LibuildErrorParams); get level(): "Ignore" | "Warn" | "Error"; get path(): string | undefined; set path(file: string | undefined); private printCodeFrame; toString(): string; setControllerOption(opt: ControllerOption): void; setCodeFrame(opt: CodeFrameOption): void; isSame(error: LibuildError): boolean; } export declare interface LibuildErrorInstance { prefixCode?: string; code: string; message: string; reason?: string; stack?: string; path?: string; /** * @default`'Error'` */ level?: keyof typeof ErrorLevel; hint?: string; referenceUrl?: string; setControllerOption: (opt: ControllerOption) => void; setCodeFrame: (opt: CodeFrameOption) => void; } export declare type LibuildErrorParams = Omit<LibuildErrorInstance, 'code' | 'message' | 'path' | 'setControllerOption' | 'setCodeFrame' | 'toOverlayPayload'> & { code?: string; controller?: ControllerOption; codeFrame?: CodeFrameOption; }; export declare class LibuildFailure extends Error { readonly errors: LibuildErrorInstance[]; readonly warnings: LibuildErrorInstance[]; readonly logLevel: string; constructor(errors: LibuildErrorInstance[], warnings: LibuildErrorInstance[], logLevel: string); toString(): string; } export declare type LibuildManifest = { metafile: Metafile; config: BuildOptions; }; export declare interface LibuildPlugin<T extends ExtraContext = ExtraContext> { name: string; apply: (compiler: SafeMerge<ILibuilder, T>) => void; } export declare type LoadArgs = Pick<OnLoadArgs, 'path'> & Pick<OnResolveResult, 'pluginData'>; declare class Loader { finalSource?: string | undefined; constructor(root: string, plugins: Plugin_2[]); fetch(file: string, relativeTo: string, depTrace: string): Promise<{ [key: string]: string; }>; } export declare type LoadResult = Pick<OnLoadResult, 'contents' | 'loader' | 'resolveDir'> & { map?: SourceMap; }; declare type LoadSvgrResult = { contents: string; loader: Loader_2; }; declare type LocalsConventionFunction = (originalClassName: string, generatedClassName: string, inputFile: string) => string; /** * Options for log level. */ export declare type LogLevel = 'silent' | 'error' | 'warning' | 'info' | 'debug' | 'verbose'; declare type Measure<T extends number> = T extends 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 ? T : never; declare type Minify = 'esbuild' | 'terser' | false | MinifyOptions; declare type Platform = 'node' | 'browser'; export declare type PostcssOptions = { processOptions?: ProcessOptions; plugins?: AcceptedPlugin[]; }; /** * @experimental */ export declare type Redirect = { alias?: boolean; style?: boolean; asset?: boolean; }; /** * Options for the resolver. */ export declare type Resolve = { /** * This is only valid for enhanced-resolve */ alias?: Record<string, string>; mainFields?: string[]; /** * @internal This is only valid for enhanced-resolve */ mainFiles?: string[]; /** * @internal This is only valid for enhanced-resolve */ preferRelative?: boolean; }; export declare type ResolveArgs = Pick<OnResolveArgs, 'importer' | 'path' | 'resolveDir' | 'kind'>; export declare type ResolveNormalized = Required<Resolve>; export declare type ResolveResult = Pick<OnResolveResult, 'path' | 'external' | 'namespace' | 'sideEffects' | 'suffix'>; /** * Only merge additional fields from U to T. */ export declare type SafeMerge<T, U> = T & { [K in keyof U as Exclude<K, keyof T>]: U[K]; }; export { sassOptions } export declare type SideEffects = RegExp[] | boolean | ((id: string, external: boolean) => boolean); export declare type Source = { code: string; map?: SourceMap; path: string; loader?: string; /** * Whether enable cache. * @default true */ cache?: boolean; }; export declare interface SourceMap { mappings: string; names: string[]; sources: (string | null)[]; version: number; sourcesContent?: (string | null)[]; } declare type SourceMap_2 = boolean | 'inline' | 'external'; declare class SourcemapContext implements ISourcemapContext { private enableSourceMap?; private sourceMapChain; private sourceMapDirty; private cachedInlineSourceMap; private cachedSourceMap; private pluginIdMap; constructor(enableSourceMap?: boolean | undefined); private markSourceMapStatus; addSourceMap(pluginId: number, map?: SourceMap): void; getInlineSourceMap(): string; getSourceMap(): SourceMap | undefined; getSourceMapChain(): SourceMap[]; genPluginId(name: string): number; } export declare interface Style { inject?: boolean; sass?: { additionalData?: AdditionalData; implementation?: object | string; sassOptions?: sassOptions; }; less?: { additionalData?: AdditionalData; implementation?: object | string; lessOptions?: Less.Options; }; postcss?: PostcssOptions; autoModules?: boolean | RegExp; modules?: { localsConvention?: 'camelCase' | 'camelCaseOnly' | 'dashes' | 'dashesOnly' | LocalsConventionFunction; scopeBehaviour?: 'global' | 'local'; globalModulePaths?: RegExp[]; generateScopedName?: string | GenerateScopedNameFunction; hashPrefix?: string; exportGlobals?: boolean; root?: string; resolve?: (file: string) => string | Promise<string>; Loader?: typeof Loader; getJSON?: (cssFilename: string, json: { [name: string]: string; }, outputFilename?: string) => void; }; } declare class SyncHook<T, R = void, AdditionalOptions = UnsetAdditionalOptions> extends Hook<T, R, AdditionalOptions> { call(...args: AsArray<T>): R; } declare type Tap = TapOptions & { name: string; }; declare type TapOptions = { before?: string; stage?: number; }; export declare function toLevel(level: keyof typeof ErrorLevel): ErrorLevel; export declare function transform(err: any, opt?: LibuildErrorParams): LibuildError; declare class TransformContext extends SourcemapContext implements ITransformContext { private enableCache?; private cachedTransformResult; constructor(enableCache?: boolean | undefined, enableSourceMap?: boolean); addTransformResult(pluginId: number, result: CacheValue): void; getValidCache(pluginId: number, code: string): CacheValue | undefined; } declare class UnsetAdditionalOptions { _UnsetAdditionalOptions: true } export declare interface UserConfig { /** * @default true */ autoExternal?: boolean | { dependencies?: boolean; peerDependencies?: boolean; }; /** * @default true */ bundle?: boolean; /** * Input to the bundling algorithm. * * Only valid when bundle is 'true' * @default { index: './src/index.ts '} */ input?: Input; /** * The directory for source. * * Only valid when bundle is 'false', it will transform all files in sourceDir * @default 'src' */ sourceDir?: string; /** * The directory for output * @default 'dist' */ outdir?: string; /** * @see https://esbuild.github.io/api/#outbase * @default 'src' */ outbase?: string; /** * Options for esbuild, it may disable some of the functions of libuild * @experimental */ esbuildOptions?: (options: BuildOptions) => BuildOptions; /** * @see https://esbuild.github.io/api/#entry-names */ entryNames?: string; /** * @see https://esbuild.github.io/api/#chunk-names */ chunkNames?: string; /** * Module format * @default 'esm' */ format?: Format; /** * Code splitting * @default false */ splitting?: boolean; /** * Minify JS * @default false */ minify?: Minify; /** * When file changed builder will rebuild under watch mode. * @default false */ watch?: boolean; /** * The level of the console log * @default 'info' */ logLevel?: LogLevel; /** * Options for enhanced-resolve */ resolve?: Resolve; /** * Plugins for libuild */ plugins?: LibuildPlugin[]; /** * Compile target * @see https://esbuild.github.io/api/#target * @default 'es2015' */ target?: string; /** * The mode of sourcemap * @default false */ sourceMap?: SourceMap_2; /** * Global variables, only used in umd format * @default {} */ globals?: Globals; /** * Exclude it from your build * Default Excluded your dependencies and peerDependencies */ external?: External_2; /** * @see https://esbuild.github.io/api/#define */ define?: Define; /** * @see https://esbuild.github.io/api/#platform * @default 'node' */ platform?: Platform; /** * Emit esbuild metafile * @see https://esbuild.github.io/api/#metafile * @default false */ metafile?: boolean; /** * Options for style */ style?: Style; /** * Options for asset */ asset?: Asset; /** * @see https://esbuild.github.io/api/#loader */ loader?: Record<string, Loader_2>; /** * @see https://esbuild.github.io/api/#inject */ inject?: string[]; /** * @see https://esbuild.github.io/api/#jsx * @default 'automatic' */ jsx?: 'automatic' | 'preserve' | 'transform'; /** * Module sideEffects, it will invalidate the sideEffects field in package.json */ sideEffects?: SideEffects; /** * Redirect id when bundle is false */ redirect?: Redirect; /** * Cache for transform hooks, accelerate incremental build * @default true */ transformCache?: boolean; } export declare function warpErrors(libuildErrors: LibuildError[], logLevel?: LogLevel): LibuildFailure; export { }