mirror of
https://github.com/unjs/unbuild.git
synced 2025-12-08 19:25:11 +00:00
refactor: add explicit return types (#412)
This commit is contained in:
parent
0cabd3c701
commit
6e82b090ad
@ -37,7 +37,7 @@ CLI output also includes output size and exports for quick inspection.
|
||||
|
||||
Create `src/index.ts`:
|
||||
|
||||
```ts
|
||||
```js
|
||||
export const log = (...args) => {
|
||||
console.log(...args);
|
||||
};
|
||||
@ -75,7 +75,7 @@ Configuration is automatically inferred from fields in `package.json` mapped to
|
||||
|
||||
Create `build.config.ts`:
|
||||
|
||||
```ts
|
||||
```js
|
||||
export default {
|
||||
entries: ["./src/index"],
|
||||
};
|
||||
@ -87,7 +87,7 @@ See options [here](./src/types.ts).
|
||||
|
||||
Example:
|
||||
|
||||
```ts
|
||||
```js
|
||||
import { defineBuildConfig } from "unbuild";
|
||||
|
||||
export default defineBuildConfig({
|
||||
@ -113,7 +113,7 @@ export default defineBuildConfig({
|
||||
|
||||
Or with multiple builds you can declare an array of configs:
|
||||
|
||||
```ts
|
||||
```js
|
||||
import { defineBuildConfig } from "unbuild";
|
||||
|
||||
export default defineBuildConfig([
|
||||
|
||||
@ -3,14 +3,20 @@ import unjs from "eslint-config-unjs";
|
||||
// https://github.com/unjs/eslint-config
|
||||
export default unjs({
|
||||
ignores: [
|
||||
".git"
|
||||
],
|
||||
".git",
|
||||
],
|
||||
rules: {
|
||||
"unicorn/no-null": 0,
|
||||
"unicorn/prevent-abbreviations": 0,
|
||||
"unicorn/prefer-module": 0,
|
||||
"unicorn/prefer-top-level-await": 0,
|
||||
"@typescript-eslint/no-non-null-assertion": 0,
|
||||
"@typescript-eslint/no-unused-vars": 0
|
||||
},
|
||||
});
|
||||
"unicorn/no-null": 0,
|
||||
"unicorn/prevent-abbreviations": 0,
|
||||
"unicorn/prefer-module": 0,
|
||||
"unicorn/prefer-top-level-await": 0,
|
||||
"@typescript-eslint/no-non-null-assertion": 0,
|
||||
"@typescript-eslint/no-unused-vars": 0,
|
||||
},
|
||||
}, {
|
||||
files: ["**/*.ts"],
|
||||
rules: {
|
||||
"@typescript-eslint/explicit-function-return-type": "error",
|
||||
"@typescript-eslint/no-inferrable-types": "error",
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
export default function sum(a: number, b: number) {
|
||||
export default function sum(a: number, b: number): number {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@ export const config = {
|
||||
height: 10,
|
||||
},
|
||||
tags: {
|
||||
$resolve: (val?: string[]) => ["tag1", ...(val || [])].filter(Boolean),
|
||||
$resolve: (val?: string[]): string[] =>
|
||||
["tag1", ...(val || [])].filter(Boolean),
|
||||
},
|
||||
};
|
||||
|
||||
@ -16,7 +16,7 @@ type InferEntriesResult = {
|
||||
export const autoPreset = definePreset(() => {
|
||||
return {
|
||||
hooks: {
|
||||
"build:prepare"(ctx) {
|
||||
"build:prepare"(ctx): void {
|
||||
// Disable auto if entries already provided or pkg not available
|
||||
if (!ctx.pkg || ctx.options.entries.length > 0) {
|
||||
return;
|
||||
@ -167,7 +167,7 @@ export function inferEntries(
|
||||
return { entries, cjs, dts, warnings };
|
||||
}
|
||||
|
||||
export const getEntrypointPaths = (path: string) => {
|
||||
export const getEntrypointPaths = (path: string): string[] => {
|
||||
const segments = normalize(path).split("/");
|
||||
return segments
|
||||
.map((_, index) => segments.slice(index).join("/"))
|
||||
|
||||
@ -23,7 +23,7 @@ export async function build(
|
||||
rootDir: string,
|
||||
stub: boolean,
|
||||
inputConfig: BuildConfig = {},
|
||||
) {
|
||||
): Promise<void> {
|
||||
// Determine rootDir
|
||||
rootDir = resolve(process.cwd(), rootDir || ".");
|
||||
|
||||
@ -67,7 +67,7 @@ async function _build(
|
||||
cleanedDirs: string[],
|
||||
_stubMode: boolean,
|
||||
_watchMode: boolean,
|
||||
) {
|
||||
): Promise<void> {
|
||||
// Resolve preset
|
||||
const preset = await resolvePreset(
|
||||
buildConfig.preset ||
|
||||
@ -305,7 +305,7 @@ async function _build(
|
||||
}
|
||||
}
|
||||
|
||||
const rPath = (p: string) =>
|
||||
const rPath = (p: string): string =>
|
||||
relative(process.cwd(), resolve(options.outDir, p));
|
||||
for (const entry of ctx.buildEntries.filter((e) => !e.chunk)) {
|
||||
let totalBytes = entry.bytes || 0;
|
||||
|
||||
@ -7,7 +7,7 @@ import consola from "consola";
|
||||
|
||||
const copy = fsp.cp || fsp.copyFile;
|
||||
|
||||
export async function copyBuild(ctx: BuildContext) {
|
||||
export async function copyBuild(ctx: BuildContext): Promise<void> {
|
||||
const entries = ctx.options.entries.filter(
|
||||
(e) => e.builder === "copy",
|
||||
) as CopyBuildEntry[];
|
||||
|
||||
@ -4,7 +4,7 @@ import { symlink, rmdir } from "../../utils";
|
||||
import type { MkdistBuildEntry, BuildContext } from "../../types";
|
||||
import consola from "consola";
|
||||
|
||||
export async function mkdistBuild(ctx: BuildContext) {
|
||||
export async function mkdistBuild(ctx: BuildContext): Promise<void> {
|
||||
const entries = ctx.options.entries.filter(
|
||||
(e) => e.builder === "mkdist",
|
||||
) as MkdistBuildEntry[];
|
||||
|
||||
@ -10,7 +10,7 @@ import { getChunkFilename } from "./utils";
|
||||
import { rollupStub } from "./stub";
|
||||
import { rollupWatch } from "./watch";
|
||||
|
||||
export async function rollupBuild(ctx: BuildContext) {
|
||||
export async function rollupBuild(ctx: BuildContext): Promise<void> {
|
||||
// Stub mode
|
||||
if (ctx.options.stub) {
|
||||
await rollupStub(ctx);
|
||||
|
||||
@ -133,7 +133,7 @@ export function getRollupOptions(ctx: BuildContext): RollupOptions {
|
||||
}),
|
||||
|
||||
ctx.options.rollup.preserveDynamicImports && {
|
||||
renderDynamicImport() {
|
||||
renderDynamicImport(): { left: string; right: string } {
|
||||
return { left: "import(", right: ")" };
|
||||
},
|
||||
},
|
||||
|
||||
@ -28,7 +28,7 @@ const require = __cjs_mod__.createRequire(import.meta.url);
|
||||
`;
|
||||
|
||||
// Shim __dirname, __filename and require
|
||||
function CJSToESM(code: string) {
|
||||
function CJSToESM(code: string): { code: string; map: any } | null {
|
||||
if (code.includes(CJSShim) || !CJSyntaxRe.test(code)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -52,7 +52,7 @@ export function esbuild(options: EsbuildOptions): Plugin {
|
||||
}
|
||||
}
|
||||
}
|
||||
const getLoader = (id = "") => {
|
||||
const getLoader = (id = ""): Loader | undefined => {
|
||||
return loaders[extname(id)];
|
||||
};
|
||||
|
||||
@ -61,7 +61,7 @@ export function esbuild(options: EsbuildOptions): Plugin {
|
||||
return {
|
||||
name: "esbuild",
|
||||
|
||||
async transform(code, id) {
|
||||
async transform(code, id): Promise<null | { code: string; map: any }> {
|
||||
if (!filter(id)) {
|
||||
return null;
|
||||
}
|
||||
@ -79,15 +79,18 @@ export function esbuild(options: EsbuildOptions): Plugin {
|
||||
|
||||
printWarnings(id, result, this);
|
||||
|
||||
return (
|
||||
result.code && {
|
||||
code: result.code,
|
||||
map: result.map || null,
|
||||
}
|
||||
);
|
||||
return result.code
|
||||
? {
|
||||
code: result.code,
|
||||
map: result.map || null,
|
||||
}
|
||||
: null;
|
||||
},
|
||||
|
||||
async renderChunk(code, { fileName }) {
|
||||
async renderChunk(
|
||||
code,
|
||||
{ fileName },
|
||||
): Promise<null | undefined | { code: string; map: any }> {
|
||||
if (!options.minify) {
|
||||
return null;
|
||||
}
|
||||
@ -118,7 +121,7 @@ function printWarnings(
|
||||
id: string,
|
||||
result: TransformResult,
|
||||
plugin: PluginContext,
|
||||
) {
|
||||
): void {
|
||||
if (result.warnings) {
|
||||
for (const warning of result.warnings) {
|
||||
let message = "[esbuild]";
|
||||
|
||||
@ -17,7 +17,7 @@ export function rawPlugin(opts: RawLoaderOptions = {}): Plugin {
|
||||
const filter = createFilter(opts.include, opts.exclude);
|
||||
return {
|
||||
name: "unbuild-raw",
|
||||
transform(code, id) {
|
||||
transform(code, id): { code: string; map: any } | undefined {
|
||||
if (filter(id)) {
|
||||
return {
|
||||
code: `export default ${JSON.stringify(code)}`,
|
||||
|
||||
@ -9,7 +9,7 @@ const SHEBANG_RE = /^#![^\n]*/;
|
||||
export function shebangPlugin(): Plugin {
|
||||
return {
|
||||
name: "unbuild-shebang",
|
||||
async writeBundle(options, bundle) {
|
||||
async writeBundle(options, bundle): Promise<void> {
|
||||
for (const [fileName, output] of Object.entries(bundle)) {
|
||||
if (output.type !== "chunk") {
|
||||
continue;
|
||||
@ -26,17 +26,17 @@ export function shebangPlugin(): Plugin {
|
||||
export function removeShebangPlugin(): Plugin {
|
||||
return {
|
||||
name: "unbuild-remove-shebang",
|
||||
renderChunk(code) {
|
||||
renderChunk(code): string {
|
||||
return code.replace(SHEBANG_RE, "");
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export async function makeExecutable(filePath: string) {
|
||||
export async function makeExecutable(filePath: string): Promise<void> {
|
||||
await fsp.chmod(filePath, 0o755 /* rwx r-x r-x */).catch(() => {});
|
||||
}
|
||||
|
||||
export function getShebang(code: string, append = "\n") {
|
||||
export function getShebang(code: string, append = "\n"): string {
|
||||
const m = code.match(SHEBANG_RE);
|
||||
return m ? m + append : "";
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ import type { BuildContext } from "../../types";
|
||||
import { makeExecutable, getShebang } from "./plugins/shebang";
|
||||
import { DEFAULT_EXTENSIONS, resolveAliases } from "./utils";
|
||||
|
||||
export async function rollupStub(ctx: BuildContext) {
|
||||
export async function rollupStub(ctx: BuildContext): Promise<void> {
|
||||
const babelPlugins = ctx.options.stubOptions.jiti.transformOptions?.babel
|
||||
?.plugins as any;
|
||||
const importedBabelPlugins: Array<string> = [];
|
||||
|
||||
@ -13,7 +13,7 @@ export const DEFAULT_EXTENSIONS = [
|
||||
".json",
|
||||
];
|
||||
|
||||
export function resolveAliases(ctx: BuildContext) {
|
||||
export function resolveAliases(ctx: BuildContext): Record<string, string> {
|
||||
const aliases: Record<string, string> = {
|
||||
[ctx.pkg.name!]: ctx.options.rootDir,
|
||||
...ctx.options.alias,
|
||||
@ -57,7 +57,7 @@ export function getChunkFilename(
|
||||
ctx: BuildContext,
|
||||
chunk: PreRenderedChunk,
|
||||
ext: string,
|
||||
) {
|
||||
): string {
|
||||
if (chunk.isDynamicEntry) {
|
||||
return `chunks/[name].${ext}`;
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ import type { RollupOptions } from "../../types";
|
||||
import consola from "consola";
|
||||
import chalk from "chalk";
|
||||
|
||||
export function rollupWatch(rollupOptions: RollupOptions) {
|
||||
export function rollupWatch(rollupOptions: RollupOptions): void {
|
||||
const watcher = _rollupWatch(rollupOptions);
|
||||
|
||||
let inputs: string[];
|
||||
|
||||
@ -16,7 +16,7 @@ import type {
|
||||
} from "../../types";
|
||||
import consola from "consola";
|
||||
|
||||
export async function typesBuild(ctx: BuildContext) {
|
||||
export async function typesBuild(ctx: BuildContext): Promise<void> {
|
||||
const entries = ctx.options.entries.filter(
|
||||
(entry) => entry.builder === "untyped",
|
||||
) as UntypedBuildEntry[];
|
||||
|
||||
27
src/utils.ts
27
src/utils.ts
@ -7,11 +7,11 @@ import type { PackageJson } from "pkg-types";
|
||||
import { autoPreset } from "./auto";
|
||||
import type { BuildPreset, BuildConfig, BuildContext } from "./types";
|
||||
|
||||
export async function ensuredir(path: string) {
|
||||
export async function ensuredir(path: string): Promise<void> {
|
||||
await fsp.mkdir(dirname(path), { recursive: true });
|
||||
}
|
||||
|
||||
export function warn(ctx: BuildContext, message: string) {
|
||||
export function warn(ctx: BuildContext, message: string): void {
|
||||
if (ctx.warnings.has(message)) {
|
||||
return;
|
||||
}
|
||||
@ -19,7 +19,11 @@ export function warn(ctx: BuildContext, message: string) {
|
||||
ctx.warnings.add(message);
|
||||
}
|
||||
|
||||
export async function symlink(from: string, to: string, force = true) {
|
||||
export async function symlink(
|
||||
from: string,
|
||||
to: string,
|
||||
force = true,
|
||||
): Promise<void> {
|
||||
await ensuredir(to);
|
||||
if (force) {
|
||||
await fsp.unlink(to).catch(() => {});
|
||||
@ -27,7 +31,7 @@ export async function symlink(from: string, to: string, force = true) {
|
||||
await fsp.symlink(from, to, "junction");
|
||||
}
|
||||
|
||||
export function dumpObject(obj: Record<string, any>) {
|
||||
export function dumpObject(obj: Record<string, any>): string {
|
||||
return (
|
||||
"{ " +
|
||||
Object.keys(obj)
|
||||
@ -37,19 +41,19 @@ export function dumpObject(obj: Record<string, any>) {
|
||||
);
|
||||
}
|
||||
|
||||
export function getpkg(id = "") {
|
||||
export function getpkg(id = ""): string {
|
||||
const s = id.split("/");
|
||||
return s[0][0] === "@" ? `${s[0]}/${s[1]}` : s[0];
|
||||
}
|
||||
|
||||
export async function rmdir(dir: string) {
|
||||
export async function rmdir(dir: string): Promise<void> {
|
||||
await fsp.unlink(dir).catch(() => {});
|
||||
await fsp.rm(dir, { recursive: true, force: true }).catch(() => {});
|
||||
}
|
||||
|
||||
export function listRecursively(path: string) {
|
||||
export function listRecursively(path: string): string[] {
|
||||
const filenames = new Set<string>();
|
||||
const walk = (path: string) => {
|
||||
const walk = (path: string): void => {
|
||||
const files = readdirSync(path);
|
||||
for (const file of files) {
|
||||
const fullPath = resolve(path, file);
|
||||
@ -143,7 +147,10 @@ export function extractExportFilenames(
|
||||
);
|
||||
}
|
||||
|
||||
export function arrayIncludes(arr: (string | RegExp)[], searchElement: string) {
|
||||
export function arrayIncludes(
|
||||
arr: (string | RegExp)[],
|
||||
searchElement: string,
|
||||
): boolean {
|
||||
return arr.some((entry) =>
|
||||
entry instanceof RegExp
|
||||
? entry.test(searchElement)
|
||||
@ -151,6 +158,6 @@ export function arrayIncludes(arr: (string | RegExp)[], searchElement: string) {
|
||||
);
|
||||
}
|
||||
|
||||
export function removeExtension(filename: string) {
|
||||
export function removeExtension(filename: string): string {
|
||||
return filename.replace(/\.(js|mjs|cjs|ts|mts|cts|json|jsx|tsx)$/, "");
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ import { PackageJson } from "pkg-types";
|
||||
import { arrayIncludes, extractExportFilenames, getpkg, warn } from "./utils";
|
||||
import { BuildContext } from "./types";
|
||||
|
||||
export function validateDependencies(ctx: BuildContext) {
|
||||
export function validateDependencies(ctx: BuildContext): void {
|
||||
const usedDependencies = new Set<string>();
|
||||
const unusedDependencies = new Set<string>(
|
||||
Object.keys(ctx.pkg.dependencies || {}),
|
||||
@ -50,7 +50,7 @@ export function validatePackage(
|
||||
pkg: PackageJson,
|
||||
rootDir: string,
|
||||
ctx: BuildContext,
|
||||
) {
|
||||
): void {
|
||||
if (!pkg) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -18,6 +18,7 @@ describe("validatePackage", () => {
|
||||
"./cli": "./dist/cli",
|
||||
},
|
||||
module: "dist/mod",
|
||||
// @ts-expect-error TODO: fix pkg-types
|
||||
exports: {
|
||||
"./runtime/*": "./runtime/*.mjs",
|
||||
".": { node: "./src/index.mts" },
|
||||
@ -60,6 +61,7 @@ describe("validateDependencies", () => {
|
||||
stub: false,
|
||||
alias: {},
|
||||
replace: {},
|
||||
// @ts-expect-error
|
||||
rollup: {
|
||||
replace: false,
|
||||
alias: false,
|
||||
@ -79,7 +81,11 @@ describe("validateDependencies", () => {
|
||||
it("does not print implicit deps warning for peerDependencies", () => {
|
||||
const logs: string[] = [];
|
||||
consola.mockTypes((type) =>
|
||||
type === "warn" ? (str: string) => logs.push(str) : () => {},
|
||||
type === "warn"
|
||||
? (str: string): void => {
|
||||
logs.push(str);
|
||||
}
|
||||
: (): void => {},
|
||||
);
|
||||
|
||||
validateDependencies({
|
||||
@ -99,6 +105,7 @@ describe("validateDependencies", () => {
|
||||
stub: false,
|
||||
alias: {},
|
||||
replace: {},
|
||||
// @ts-expect-error
|
||||
rollup: {
|
||||
replace: false,
|
||||
alias: false,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user