mirror of
https://github.com/moltbot/moltbot.git
synced 2026-05-13 15:47:28 +00:00
fix: quiet extension unresolved import warnings
This commit is contained in:
@@ -48,6 +48,29 @@ type MSTeamsProcessContext = MSTeamsSendContext & {
|
||||
) => Promise<unknown[]>;
|
||||
};
|
||||
|
||||
type AzureAccessToken = {
|
||||
token?: string;
|
||||
} | null;
|
||||
|
||||
type AzureTokenCredential = {
|
||||
getToken: (scope: string | string[]) => Promise<AzureAccessToken>;
|
||||
};
|
||||
|
||||
type AzureIdentityModule = {
|
||||
ClientCertificateCredential: new (
|
||||
tenantId: string,
|
||||
clientId: string,
|
||||
options: { certificate: string },
|
||||
) => AzureTokenCredential;
|
||||
ManagedIdentityCredential: new (clientId?: string) => AzureTokenCredential;
|
||||
};
|
||||
|
||||
const AZURE_IDENTITY_MODULE = "@azure/identity";
|
||||
|
||||
async function loadAzureIdentity(): Promise<AzureIdentityModule> {
|
||||
return (await import(AZURE_IDENTITY_MODULE)) as AzureIdentityModule;
|
||||
}
|
||||
|
||||
export async function loadMSTeamsSdk(): Promise<MSTeamsTeamsSdk> {
|
||||
const [appsModule, apiModule] = await Promise.all([
|
||||
import("@microsoft/teams.apps"),
|
||||
@@ -129,13 +152,11 @@ function createCertificateApp(
|
||||
sdk: MSTeamsTeamsSdk,
|
||||
): MSTeamsApp {
|
||||
// Lazily create and cache the credential so the token cache is reused.
|
||||
let credentialPromise: Promise<
|
||||
InstanceType<typeof import("@azure/identity").ClientCertificateCredential>
|
||||
> | null = null;
|
||||
let credentialPromise: Promise<AzureTokenCredential> | null = null;
|
||||
|
||||
const getCredential = async () => {
|
||||
if (!credentialPromise) {
|
||||
credentialPromise = import("@azure/identity").then(
|
||||
credentialPromise = loadAzureIdentity().then(
|
||||
(az) =>
|
||||
new az.ClientCertificateCredential(creds.tenantId, creds.appId, {
|
||||
certificate: privateKey,
|
||||
@@ -170,13 +191,11 @@ function createManagedIdentityApp(
|
||||
): MSTeamsApp {
|
||||
// Lazily create and cache the credential instance so the token cache is
|
||||
// reused across calls instead of hitting IMDS/AAD on every message.
|
||||
let credentialPromise: Promise<
|
||||
InstanceType<typeof import("@azure/identity").ManagedIdentityCredential>
|
||||
> | null = null;
|
||||
let credentialPromise: Promise<AzureTokenCredential> | null = null;
|
||||
|
||||
const getCredential = async () => {
|
||||
if (!credentialPromise) {
|
||||
credentialPromise = import("@azure/identity").then((az) =>
|
||||
credentialPromise = loadAzureIdentity().then((az) =>
|
||||
creds.managedIdentityClientId
|
||||
? new az.ManagedIdentityCredential(creds.managedIdentityClientId)
|
||||
: new az.ManagedIdentityCredential(),
|
||||
|
||||
@@ -7,9 +7,29 @@ type TsdownConfigEntry = {
|
||||
neverBundle?: string[] | ((id: string) => boolean);
|
||||
};
|
||||
entry?: Record<string, string> | string[];
|
||||
inputOptions?: TsdownInputOptions;
|
||||
outDir?: string;
|
||||
};
|
||||
|
||||
type TsdownLog = {
|
||||
code?: string;
|
||||
message?: string;
|
||||
id?: string;
|
||||
importer?: string;
|
||||
};
|
||||
|
||||
type TsdownOnLog = (
|
||||
level: string,
|
||||
log: TsdownLog,
|
||||
defaultHandler: (level: string, log: TsdownLog) => void,
|
||||
) => void;
|
||||
|
||||
type TsdownInputOptions = (
|
||||
options: { onLog?: TsdownOnLog },
|
||||
format?: unknown,
|
||||
context?: unknown,
|
||||
) => { onLog?: TsdownOnLog } | undefined;
|
||||
|
||||
function asConfigArray(config: unknown): TsdownConfigEntry[] {
|
||||
return Array.isArray(config) ? (config as TsdownConfigEntry[]) : [config as TsdownConfigEntry];
|
||||
}
|
||||
@@ -25,6 +45,10 @@ function bundledEntry(pluginId: string): string {
|
||||
return `${bundledPluginRoot(pluginId)}/index`;
|
||||
}
|
||||
|
||||
function unifiedDistGraph(): TsdownConfigEntry | undefined {
|
||||
return asConfigArray(tsdownConfig).find((config) => entryKeys(config).includes("index"));
|
||||
}
|
||||
|
||||
describe("tsdown config", () => {
|
||||
it("keeps core, plugin runtime, plugin-sdk, bundled plugins, and bundled hooks in one dist graph", () => {
|
||||
const configs = asConfigArray(tsdownConfig);
|
||||
@@ -76,8 +100,7 @@ describe("tsdown config", () => {
|
||||
});
|
||||
|
||||
it("externalizes staged bundled plugin runtime dependencies", () => {
|
||||
const configs = asConfigArray(tsdownConfig);
|
||||
const unifiedGraph = configs.find((config) => entryKeys(config).includes("index"));
|
||||
const unifiedGraph = unifiedDistGraph();
|
||||
const neverBundle = unifiedGraph?.deps?.neverBundle;
|
||||
|
||||
if (typeof neverBundle === "function") {
|
||||
@@ -89,4 +112,33 @@ describe("tsdown config", () => {
|
||||
expect(neverBundle).toEqual(expect.arrayContaining(["silk-wasm", "ws"]));
|
||||
}
|
||||
});
|
||||
|
||||
it("suppresses unresolved imports from extension source", () => {
|
||||
const configured = unifiedDistGraph()?.inputOptions?.({})?.onLog;
|
||||
const handled: TsdownLog[] = [];
|
||||
|
||||
configured?.(
|
||||
"warn",
|
||||
{
|
||||
code: "UNRESOLVED_IMPORT",
|
||||
message: "Could not resolve '@azure/identity' in extensions/msteams/src/sdk.ts",
|
||||
},
|
||||
(_level, log) => handled.push(log),
|
||||
);
|
||||
|
||||
expect(handled).toEqual([]);
|
||||
});
|
||||
|
||||
it("keeps unresolved imports outside extension source visible", () => {
|
||||
const configured = unifiedDistGraph()?.inputOptions?.({})?.onLog;
|
||||
const handled: TsdownLog[] = [];
|
||||
const log = {
|
||||
code: "UNRESOLVED_IMPORT",
|
||||
message: "Could not resolve 'missing-dependency' in src/index.ts",
|
||||
};
|
||||
|
||||
configured?.("warn", log, (_level, forwardedLog) => handled.push(forwardedLog));
|
||||
|
||||
expect(handled).toEqual([log]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -34,6 +34,10 @@ const SUPPRESSED_EVAL_WARNING_PATHS = [
|
||||
"bottleneck/lib/RedisConnection.js",
|
||||
] as const;
|
||||
|
||||
function normalizedLogHaystack(log: { message?: string; id?: string; importer?: string }): string {
|
||||
return [log.message, log.id, log.importer].filter(Boolean).join("\n").replaceAll("\\", "/");
|
||||
}
|
||||
|
||||
function buildInputOptions(options: InputOptionsArg): InputOptionsReturn {
|
||||
if (process.env.OPENCLAW_BUILD_VERBOSE === "1") {
|
||||
return undefined;
|
||||
@@ -50,10 +54,13 @@ function buildInputOptions(options: InputOptionsArg): InputOptionsReturn {
|
||||
if (log.code === "PLUGIN_TIMINGS") {
|
||||
return true;
|
||||
}
|
||||
if (log.code === "UNRESOLVED_IMPORT") {
|
||||
return normalizedLogHaystack(log).includes("extensions/");
|
||||
}
|
||||
if (log.code !== "EVAL") {
|
||||
return false;
|
||||
}
|
||||
const haystack = [log.message, log.id, log.importer].filter(Boolean).join("\n");
|
||||
const haystack = normalizedLogHaystack(log);
|
||||
return SUPPRESSED_EVAL_WARNING_PATHS.some((path) => haystack.includes(path));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user