mirror of
https://github.com/oxc-project/oxc.git
synced 2026-09-14 19:36:11 +08:00
1ccaf767d6
Final clean up. - Share `isObject()` function - Clean up directory structure - Use `Error.cause` for TS hint error
40 lines
1.5 KiB
TypeScript
40 lines
1.5 KiB
TypeScript
import { isObject } from "./utils.ts";
|
|
|
|
// Cache the in-flight `Promise` rather than the resolved module,
|
|
// so concurrent callers share one `import("vite-plus")` invocation
|
|
// instead of each kicking off their own before the first `await` completes.
|
|
// (e.g. oxlint's `Promise.allSettled` over multiple paths)
|
|
let vitePlusCache: Promise<typeof import("vite-plus")> | null = null;
|
|
|
|
/**
|
|
* Resolve a Vite+ config via `vite-plus`'s `resolveConfig` and extract the given field.
|
|
*
|
|
* `vite-plus` is loaded lazily and memoized for the process.
|
|
* Consumers declare it as an optional peer dependency; tsdown leaves the specifier external
|
|
* so the user-installed copy is used at runtime.
|
|
*
|
|
* @param path - Absolute path to the Vite config file
|
|
* @param fieldName - Field name to extract from the resolved config (e.g. `"fmt"`, `"lint"`)
|
|
* @returns The field as an object, or `null` when the field is missing (signals "skip")
|
|
* @throws When the field exists but is not a plain object
|
|
*/
|
|
export async function loadViteConfigField(
|
|
path: string,
|
|
fieldName: "lint" | "fmt",
|
|
): Promise<object | null> {
|
|
vitePlusCache ??= import("vite-plus");
|
|
const { resolveConfig } = await vitePlusCache;
|
|
|
|
const config = (await resolveConfig({ configFile: path }, "build")) as Record<string, unknown>;
|
|
|
|
// Signal "skip" when the field is missing
|
|
if (!(fieldName in config)) return null;
|
|
|
|
const fieldValue = config[fieldName];
|
|
if (!isObject(fieldValue)) {
|
|
throw new Error(`The \`${fieldName}\` field in the default export must be an object.`);
|
|
}
|
|
|
|
return fieldValue as object;
|
|
}
|