@ledgerhq/live-common
Version:
Common ground for the Ledger Live apps
93 lines (82 loc) • 3.15 kB
text/typescript
import { EnvName } from "@ledgerhq/live-env";
import { Feature, FeatureId } from "@ledgerhq/types-live";
import { getFeature, DEFAULT_FEATURES } from "../featureFlags";
import axios, { AxiosError } from "axios";
export const getAllFeatureFlags = (
appLanguage?: string,
localOverrides?: { [key in FeatureId]?: Feature | undefined },
): Partial<{ [key in FeatureId]: Feature }> => {
const res: Partial<{ [key in FeatureId]: Feature }> = {};
Object.keys(DEFAULT_FEATURES).forEach(k => {
const key = k as keyof typeof DEFAULT_FEATURES;
const value = getFeature({ key, appLanguage, localOverrides });
if (value !== null) res[key] = value;
});
return res;
};
export const formatFlagsData = (data: Partial<{ [key in FeatureId]: Feature }>) => {
let allureData = "";
for (const [key, value] of Object.entries(data)) {
if (!value) continue;
if (!value.enabled) continue;
allureData += `FF.${key} = ${value.enabled}\n`;
const entries = {
desktop_version: value.desktop_version,
mobile_version: value.mobile_version,
enabledOverriddenForCurrentVersion: value.enabledOverriddenForCurrentVersion,
languages_whitelisted: value.languages_whitelisted?.join(", "),
languages_blacklisted: value.languages_blacklisted?.join(", "),
enabledOverriddenForCurrentLanguage: value.enabledOverriddenForCurrentLanguage,
overridesRemote: value.overridesRemote,
overriddenByEnv: value.overriddenByEnv,
params: value.params ? JSON.stringify(value.params) : undefined,
};
for (const [field, fieldValue] of Object.entries(entries)) {
if (fieldValue !== undefined) {
allureData += `FF.${key}.${field} = ${fieldValue
.toString()
.replace(/^\{|\}$/g, "")
.replace(/"/g, " ")}\n`;
}
}
}
return allureData;
};
const SENSITIVE_ENV_KEYS: Set<string> = new Set(["SEED"]);
export const formatEnvData = (data: { [key in EnvName]: unknown }) => {
let allureData = "";
for (const [key, value] of Object.entries(data)) {
if (SENSITIVE_ENV_KEYS.has(key)) continue;
allureData += `ENV.${key} = ${value}\n`;
}
return allureData;
};
/**
* Sanitizes an error to remove circular references (e.g., from AxiosError objects).
* This prevents Jest serialization failures when processing test results.
* Always returns a clean Error object with only serializable properties.
*/
export const sanitizeError = (error: unknown): Error => {
if (!axios.isAxiosError(error)) {
if (error instanceof Error) {
// Create a new clean error to avoid any circular references
const sanitized = new Error(error.message);
sanitized.name = error.name;
if (error.stack) {
sanitized.stack = error.stack;
}
return sanitized;
}
return new Error(String(error ?? "Unknown error"));
}
const err = error as AxiosError;
const sanitized = new Error(err.message || "Axios request failed");
Object.assign(sanitized, {
name: err.name,
code: err.code,
url: err.config?.url,
method: err.config?.method,
status: err.response?.status,
});
return sanitized;
};