@segment/analytics-react-native
Version:
The hassle-free way to add Segment analytics to your React-Native app.
172 lines (165 loc) • 6.55 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.translateHTTPError = exports.parseRetryAfter = exports.classifyError = exports.checkResponseForErrors = exports.SegmentError = exports.NetworkError = exports.JSONError = exports.ErrorType = void 0;
var _types = require("./types");
/**
* Error types reported through the errorHandler in the client
*/
let ErrorType = exports.ErrorType = /*#__PURE__*/function (ErrorType) {
ErrorType[ErrorType["NetworkUnexpectedHTTPCode"] = 0] = "NetworkUnexpectedHTTPCode";
ErrorType[ErrorType["NetworkServerLimited"] = 1] = "NetworkServerLimited";
ErrorType[ErrorType["NetworkServerRejected"] = 2] = "NetworkServerRejected";
ErrorType[ErrorType["NetworkUnknown"] = 3] = "NetworkUnknown";
ErrorType[ErrorType["JsonUnableToSerialize"] = 4] = "JsonUnableToSerialize";
ErrorType[ErrorType["JsonUnableToDeserialize"] = 5] = "JsonUnableToDeserialize";
ErrorType[ErrorType["JsonUnknown"] = 6] = "JsonUnknown";
ErrorType[ErrorType["PluginError"] = 7] = "PluginError";
ErrorType[ErrorType["InitializationError"] = 8] = "InitializationError";
ErrorType[ErrorType["ResetError"] = 9] = "ResetError";
ErrorType[ErrorType["FlushError"] = 10] = "FlushError";
ErrorType[ErrorType["EventsDropped"] = 11] = "EventsDropped";
return ErrorType;
}({});
/**
* Segment Error object for ErrorHandler option
*/
class SegmentError extends Error {
constructor(type, message, innerError, metadata) {
super(message);
Object.setPrototypeOf(this, SegmentError.prototype);
this.type = type;
this.message = message;
this.innerError = innerError;
this.metadata = metadata;
}
}
/**
* Custom Error type for Segment HTTP Error responses
*/
exports.SegmentError = SegmentError;
class NetworkError extends SegmentError {
constructor(statusCode, message, innerError) {
let type;
if (statusCode === 429) {
type = ErrorType.NetworkServerLimited;
} else if (statusCode > 300 && statusCode < 400) {
type = ErrorType.NetworkUnexpectedHTTPCode;
} else if (statusCode >= 400) {
type = ErrorType.NetworkServerRejected;
} else {
type = ErrorType.NetworkUnknown;
}
super(type, message, innerError);
Object.setPrototypeOf(this, NetworkError.prototype);
this.statusCode = statusCode;
this.type = type;
}
}
/**
* Error type for JSON Serialization errors
*/
exports.NetworkError = NetworkError;
class JSONError extends SegmentError {
constructor(type, message, innerError) {
super(type, message, innerError);
Object.setPrototypeOf(this, JSONError.prototype);
}
}
/**
* Utility method for handling HTTP fetch errors
* @param response Fetch Response
* @returns response if status OK, throws NetworkError for everything else
*/
exports.JSONError = JSONError;
const checkResponseForErrors = response => {
if (!response.ok) {
throw new NetworkError(response.status, response.statusText);
}
return response;
};
/**
* Converts a .fetch() error to a SegmentError object for reporting to the error handler
* @param error any JS error instance
* @returns a SegmentError object
*/
exports.checkResponseForErrors = checkResponseForErrors;
const translateHTTPError = error => {
// SegmentError already
if (error instanceof SegmentError) {
return error;
// JSON Deserialization Errors
} else if (error instanceof SyntaxError) {
return new JSONError(ErrorType.JsonUnableToDeserialize, error.message, error);
// HTTP Errors
} else {
const message = error instanceof Error ? error.message : typeof error === 'string' ? error : 'Unknown error';
return new NetworkError(-1, message, error);
}
};
/**
* Classify an HTTP status code into rate_limit, transient, or permanent.
*
* Precedence:
* 1. statusCodeOverrides — explicit per-code overrides
* 2. 429 — rate limiting (if rateLimitEnabled !== false)
* 3. default4xxBehavior / default5xxBehavior — range defaults
* 4. Fallback — permanent (non-retryable)
*/
exports.translateHTTPError = translateHTTPError;
const classifyError = (statusCode, config) => {
const override = config?.statusCodeOverrides?.[statusCode.toString()];
if (override !== undefined) {
if (override === 'retry') {
// If the relevant config is disabled, treat retry overrides as permanent
if (statusCode === 429 && config?.rateLimitEnabled === false) {
return new _types.ErrorClassification('permanent');
}
if (statusCode !== 429 && config?.backoffEnabled === false) {
return new _types.ErrorClassification('permanent');
}
return statusCode === 429 ? new _types.ErrorClassification('rate_limit') : new _types.ErrorClassification('transient');
}
return new _types.ErrorClassification('permanent');
}
if (statusCode === 429) {
return config?.rateLimitEnabled !== false ? new _types.ErrorClassification('rate_limit') : new _types.ErrorClassification('permanent');
}
if (statusCode >= 400 && statusCode < 500) {
const behavior = config?.default4xxBehavior ?? 'drop';
if (behavior === 'retry' && config?.backoffEnabled === false) {
return new _types.ErrorClassification('permanent');
}
return new _types.ErrorClassification(behavior === 'retry' ? 'transient' : 'permanent');
}
if (statusCode >= 500 && statusCode < 600) {
const behavior = config?.default5xxBehavior ?? 'retry';
if (behavior === 'retry' && config?.backoffEnabled === false) {
return new _types.ErrorClassification('permanent');
}
return new _types.ErrorClassification(behavior === 'retry' ? 'transient' : 'permanent');
}
return new _types.ErrorClassification('permanent');
};
/**
* Parse Retry-After header value (seconds or HTTP-date format).
* Returns delay in seconds clamped to maxRetryInterval, or undefined if invalid.
*/
exports.classifyError = classifyError;
const parseRetryAfter = (retryAfterValue, maxRetryInterval = 300) => {
if (retryAfterValue === null || retryAfterValue === '') return undefined;
const asNumber = Number(retryAfterValue);
if (Number.isFinite(asNumber)) {
if (asNumber < 0) return undefined;
return Math.min(asNumber, maxRetryInterval);
}
const retryDate = new Date(retryAfterValue);
if (!isNaN(retryDate.getTime())) {
const secondsUntil = Math.ceil((retryDate.getTime() - Date.now()) / 1000);
return Math.min(Math.max(secondsUntil, 0), maxRetryInterval);
}
return undefined;
};
exports.parseRetryAfter = parseRetryAfter;
//# sourceMappingURL=errors.js.map