@segment/analytics-react-native
Version:
The hassle-free way to add Segment analytics to your React-Native app.
160 lines (153 loc) • 6.95 kB
JavaScript
import { defaultHttpConfig } from './constants';
export const validateRateLimitConfig = (config, logger) => {
const validated = {
...config
};
if (validated.maxRetryInterval < 0.1) {
logger?.warn(`maxRetryInterval ${validated.maxRetryInterval}s clamped to 0.1s`);
validated.maxRetryInterval = 0.1;
} else if (validated.maxRetryInterval > 86400) {
logger?.warn(`maxRetryInterval ${validated.maxRetryInterval}s clamped to 86400s`);
validated.maxRetryInterval = 86400;
}
if (validated.maxRateLimitDuration < 60) {
logger?.warn(`maxRateLimitDuration ${validated.maxRateLimitDuration}s clamped to 60s`);
validated.maxRateLimitDuration = 60;
} else if (validated.maxRateLimitDuration > 604800) {
logger?.warn(`maxRateLimitDuration ${validated.maxRateLimitDuration}s clamped to 604800s`);
validated.maxRateLimitDuration = 604800;
}
if (validated.maxRetryCount < 1) {
logger?.warn(`maxRetryCount ${validated.maxRetryCount} clamped to 1`);
validated.maxRetryCount = 1;
} else if (validated.maxRetryCount > 100) {
logger?.warn(`maxRetryCount ${validated.maxRetryCount} clamped to 100`);
validated.maxRetryCount = 100;
}
// Relational: maxRateLimitDuration >= 2x maxRetryInterval
const minRateLimitDuration = validated.maxRetryInterval * 2;
if (validated.maxRateLimitDuration < minRateLimitDuration) {
logger?.warn(`maxRateLimitDuration ${validated.maxRateLimitDuration}s clamped to ${minRateLimitDuration}s (2x maxRetryInterval)`);
validated.maxRateLimitDuration = minRateLimitDuration;
}
return validated;
};
export const validateBackoffConfig = (config, logger, rateLimitConfig) => {
const validated = {
...config
};
if (validated.maxBackoffInterval < 0.1) {
logger?.warn(`maxBackoffInterval ${validated.maxBackoffInterval}s clamped to 0.1s`);
validated.maxBackoffInterval = 0.1;
} else if (validated.maxBackoffInterval > 86400) {
logger?.warn(`maxBackoffInterval ${validated.maxBackoffInterval}s clamped to 86400s`);
validated.maxBackoffInterval = 86400;
}
if (validated.baseBackoffInterval < 0.1) {
logger?.warn(`baseBackoffInterval ${validated.baseBackoffInterval}s clamped to 0.1s`);
validated.baseBackoffInterval = 0.1;
} else if (validated.baseBackoffInterval > 300) {
logger?.warn(`baseBackoffInterval ${validated.baseBackoffInterval}s clamped to 300s`);
validated.baseBackoffInterval = 300;
}
if (validated.maxTotalBackoffDuration < 60) {
logger?.warn(`maxTotalBackoffDuration ${validated.maxTotalBackoffDuration}s clamped to 60s`);
validated.maxTotalBackoffDuration = 60;
} else if (validated.maxTotalBackoffDuration > 604800) {
logger?.warn(`maxTotalBackoffDuration ${validated.maxTotalBackoffDuration}s clamped to 604800s`);
validated.maxTotalBackoffDuration = 604800;
}
if (validated.jitterPercent < 0) {
logger?.warn(`jitterPercent ${validated.jitterPercent} clamped to 0`);
validated.jitterPercent = 0;
} else if (validated.jitterPercent > 100) {
logger?.warn(`jitterPercent ${validated.jitterPercent} clamped to 100`);
validated.jitterPercent = 100;
}
if (validated.maxRetryCount < 1) {
logger?.warn(`maxRetryCount ${validated.maxRetryCount} clamped to 1`);
validated.maxRetryCount = 1;
} else if (validated.maxRetryCount > 100) {
logger?.warn(`maxRetryCount ${validated.maxRetryCount} clamped to 100`);
validated.maxRetryCount = 100;
}
// Relational: baseBackoffInterval <= maxBackoffInterval
if (validated.baseBackoffInterval > validated.maxBackoffInterval) {
logger?.warn(`baseBackoffInterval ${validated.baseBackoffInterval}s clamped to maxBackoffInterval ${validated.maxBackoffInterval}s`);
validated.baseBackoffInterval = validated.maxBackoffInterval;
}
// Relational: maxTotalBackoffDuration >= 2x max(maxBackoffInterval, rateLimitConfig.maxRetryInterval)
const maxInterval = Math.max(validated.maxBackoffInterval, rateLimitConfig?.maxRetryInterval ?? 0);
const minTotalDuration = maxInterval * 2;
if (validated.maxTotalBackoffDuration < minTotalDuration) {
logger?.warn(`maxTotalBackoffDuration ${validated.maxTotalBackoffDuration}s clamped to ${minTotalDuration}s (2x max interval)`);
validated.maxTotalBackoffDuration = minTotalDuration;
}
return validated;
};
/**
* Validates and normalizes integrations from CDN response.
* Returns null if integrations are malformed (triggers fallback to defaults).
*/
export const validateIntegrations = (settings, logger) => {
// A valid 200 with missing integrations means "no integrations configured"
if (settings.integrations == null) {
return {};
}
// Only fall back to defaults for truly malformed types (non-object or array)
if (typeof settings.integrations !== 'object' || Array.isArray(settings.integrations)) {
logger?.warn('CDN response has invalid integrations, falling back to defaults');
return null;
}
return settings.integrations;
};
/**
* Extracts, merges, and validates httpConfig from CDN response.
* Deep-merges with defaults and validates all values.
*/
export const extractHttpConfig = (serverConfig, logger) => {
const mergedRateLimit = serverConfig.rateLimitConfig ? {
...defaultHttpConfig.rateLimitConfig,
...serverConfig.rateLimitConfig
} : defaultHttpConfig.rateLimitConfig;
const mergedBackoff = serverConfig.backoffConfig ? {
...defaultHttpConfig.backoffConfig,
...serverConfig.backoffConfig,
statusCodeOverrides: {
...defaultHttpConfig.backoffConfig.statusCodeOverrides,
...serverConfig.backoffConfig.statusCodeOverrides
}
} : defaultHttpConfig.backoffConfig;
const validatedRateLimit = validateRateLimitConfig(mergedRateLimit, logger);
return {
rateLimitConfig: validatedRateLimit,
backoffConfig: validateBackoffConfig(mergedBackoff, logger, validatedRateLimit)
};
};
/**
* Merge httpConfig from 3 sources with priority: default < CDN < client overrides
* Used during settings initialization to combine default, CDN, and user configs.
*/
export const mergeHttpConfig = (cdnConfig, clientConfig, logger) => {
const mergedRateLimit = {
...defaultHttpConfig.rateLimitConfig,
...(cdnConfig?.rateLimitConfig ?? {}),
...(clientConfig?.rateLimitConfig ?? {})
};
const mergedBackoff = {
...defaultHttpConfig.backoffConfig,
...(cdnConfig?.backoffConfig ?? {}),
...(clientConfig?.backoffConfig ?? {}),
statusCodeOverrides: {
...defaultHttpConfig.backoffConfig.statusCodeOverrides,
...(cdnConfig?.backoffConfig?.statusCodeOverrides ?? {}),
...(clientConfig?.backoffConfig?.statusCodeOverrides ?? {})
}
};
const validatedRateLimit = validateRateLimitConfig(mergedRateLimit, logger);
return {
rateLimitConfig: validatedRateLimit,
backoffConfig: validateBackoffConfig(mergedBackoff, logger, validatedRateLimit)
};
};
//# sourceMappingURL=config-validation.js.map