fix(core): handle optional OpenTelemetry imports in Metro (#11210)

This commit is contained in:
Taesu
2026-09-08 09:26:10 +00:00
committed by GitHub
parent cfedf97dbc
commit 3ff842ab7f
5 changed files with 552 additions and 63 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@better-auth/core": patch
---
Prevent bundlers such as Metro from failing when the optional OpenTelemetry API is not installed.
+3
View File
@@ -7,12 +7,15 @@
"better-auth": "workspace:*"
},
"devDependencies": {
"@babel/core": "^7.29.7",
"@better-auth-test/test-utils": "workspace:*",
"@better-auth/cimd": "workspace:*",
"@better-auth/core": "workspace:*",
"@better-auth/oauth-provider": "workspace:*",
"@better-auth/redis-storage": "workspace:*",
"@better-auth/sso": "workspace:*",
"@expo/metro-config": "57.0.12",
"@types/babel__core": "^7.20.5",
"better-auth": "workspace:*",
"ioredis": "^5.11.1",
"msw": "^2.14.6"
+55
View File
@@ -0,0 +1,55 @@
import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import { createRequire } from "node:module";
import { join } from "node:path";
import { it } from "node:test";
import { fileURLToPath } from "node:url";
import { parseSync } from "@babel/core";
type CollectDependencies =
typeof import("@expo/metro-config/build/transform-worker/collect-dependencies.js").default;
const repositoryRoot = fileURLToPath(new URL("../../..", import.meta.url));
const require = createRequire(import.meta.url);
const { default: collectDependencies } =
require("@expo/metro-config/build/transform-worker/collect-dependencies.js") as {
default: CollectDependencies;
};
/**
* @see https://github.com/better-auth/better-auth/issues/11197
*/
it("marks the OpenTelemetry import as optional for Metro", async () => {
const instrumentationPath = join(
repositoryRoot,
"packages/core/dist/instrumentation/api.mjs",
);
const source = await readFile(instrumentationPath, "utf8");
const ast = parseSync(source, { sourceType: "module" });
assert.ok(ast);
const { dependencies } = collectDependencies(ast, {
allowOptionalDependencies: true,
asyncRequireModulePath: "metro-runtime/src/modules/asyncRequire",
collectOnly: true,
dynamicRequires: "reject",
inlineableCalls: ["require"],
keepRequireNames: false,
unstable_allowRequireContext: false,
unstable_isESMImportAtSource: null,
});
const openTelemetryDependency = dependencies.find(
(dependency) => dependency.name === "@opentelemetry/api",
);
assert.ok(
openTelemetryDependency,
"Metro should discover the OpenTelemetry import",
);
assert.equal(
openTelemetryDependency.data.isOptional,
true,
"Metro should treat the OpenTelemetry import as optional",
);
});
+9 -5
View File
@@ -4,13 +4,17 @@ import { noopOpenTelemetryAPI } from "./noop";
let openTelemetryAPIPromise: Promise<void> | undefined;
let openTelemetryAPI: OpenTelemetryAPI | undefined;
async function loadOpenTelemetryAPI(): Promise<void> {
try {
openTelemetryAPI = await import("@opentelemetry/api");
} catch {
// OpenTelemetry is an optional peer dependency.
}
}
export function getOpenTelemetryAPI(): OpenTelemetryAPI {
if (!openTelemetryAPIPromise) {
openTelemetryAPIPromise = import("@opentelemetry/api")
.then((mod) => {
openTelemetryAPI = mod;
})
.catch(() => /* ignore failures */ undefined);
openTelemetryAPIPromise = loadOpenTelemetryAPI();
}
return openTelemetryAPI ?? noopOpenTelemetryAPI;
+480 -58
View File
File diff suppressed because it is too large Load Diff