// https://github.com/nihalgonsalves/esbuild-plugin-browserslist // MIT License. Copyright (c) 2021 Nihal Gonsalves import { z } from "zod" import browserslist from "browserslist" export function getDefaultTarget() { return getTarget( ["Chrome", "Firefox", "Edge", "Safari"].map(browser => `last 2 ${browser} versions`), ) } enum BrowserslistKind { Edge = "edge", Firefox = "firefox", Chrome = "chrome", Safari = "safari", iOS = "ios_saf", Android = "android", AndroidChrome = "and_chr", AndroidFirefox = "and_ff", AndroidUC = "and_uc", AndroidQQ = "and_qq", Samsung = "samsung", Opera = "opera", OperaMini = "op_mini", OperaMobile = "op_mob", IE = "ie", IEMobile = "ie_mob", BlackBerry = "bb", Baidu = "baidu", Kaios = "kaios", Node = "node", } const enum EsbuildEngine { Chrome = "chrome", Edge = "edge", ES = "es", Firefox = "firefox", Hermes = "hermes", IE = "ie", IOS = "ios", Node = "node", Opera = "opera", Rhino = "rhino", Safari = "safari", } const BrowserslistEsbuildMapping: Partial> = { // exact map [BrowserslistKind.Edge]: EsbuildEngine.Edge, [BrowserslistKind.Firefox]: EsbuildEngine.Firefox, [BrowserslistKind.Chrome]: EsbuildEngine.Chrome, [BrowserslistKind.Safari]: EsbuildEngine.Safari, [BrowserslistKind.iOS]: EsbuildEngine.IOS, [BrowserslistKind.Node]: EsbuildEngine.Node, [BrowserslistKind.IE]: EsbuildEngine.IE, [BrowserslistKind.Opera]: EsbuildEngine.Opera, // approximate mapping [BrowserslistKind.Android]: EsbuildEngine.Chrome, [BrowserslistKind.AndroidChrome]: EsbuildEngine.Chrome, [BrowserslistKind.AndroidFirefox]: EsbuildEngine.Firefox, // the rest have no equivalent for esbuild } const BrowserSchema = z.nativeEnum(BrowserslistKind) /** 123 or 123.456 or 123.456.789 */ const VersionSchema = z.string().regex(/^(\d+\.\d+\.\d+|\d+\.\d+|\d+)$/) export function getTarget(targets: string[]): string[] { const result = browserslist(targets) .map(entry => { const [rawBrowser, rawVersionOrRange] = entry.split(" ") const rawVersionNormalized = rawVersionOrRange // e.g. 13.4-13.7, take the lower range ?.replace(/-[\d.]+$/, "") // all => replace with 1 ?.replace("all", "1") const browserResult = BrowserSchema.safeParse(rawBrowser) const versionResult = VersionSchema.safeParse(rawVersionNormalized) if (!browserResult.success || !versionResult.success) { return } const { data: browser } = browserResult const { data: version } = versionResult const esbuildTarget = BrowserslistEsbuildMapping[browser] if (!esbuildTarget) { return } return { target: esbuildTarget, version } }) .filter(Boolean) .map(({ target, version }) => `${target}${version}`) if (result.length === 0) { throw new Error("Could not resolve any esbuild targets") } return result }