Object.defineProperty(exports, "__esModule", { value: true });
exports.NetTransport = void 0;
var tslib_1 = require("tslib");
var node_1 = require("@sentry/node");
var types_1 = require("@sentry/types");
var utils_1 = require("@sentry/utils");
var electron_1 = require("electron");
var stream_1 = require("stream");
var url = require("url");
var zlib_1 = require("zlib");
var backend_1 = require("../backend");
// Estimated maximum size for reasonable standalone event
var GZIP_THRESHOLD = 1024 * 32;
/**
 * Gets a stream from a Buffer or string
 * We don't have Readable.from in earlier versions of node
 */
function streamFromBody(body) {
    return new stream_1.Readable({
        read: function () {
            this.push(body);
            this.push(null);
        },
    });
}
/** Using net module of electron */
var NetTransport = /** @class */ (function (_super) {
    tslib_1.__extends(NetTransport, _super);
    /** Create a new instance and set this.agent */
    function NetTransport(options) {
        var _this = _super.call(this, options) || this;
        _this.options = options;
        /** A simple buffer holding all requests. */
        _this._buffer = new utils_1.PromiseBuffer(30);
        return _this;
    }
    /**
     * @inheritDoc
     */
    NetTransport.prototype.sendEvent = function (event) {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var envelopeHeaders, type, itemHeaders, eventPayload, bodyBuffer;
            return tslib_1.__generator(this, function (_a) {
                envelopeHeaders = JSON.stringify({
                    event_id: event.event_id,
                    // Internal helper that uses `perf_hooks` to get clock reading
                    sent_at: new Date(utils_1.timestampWithMs() * 1000).toISOString(),
                });
                type = event.type === 'transaction' ? 'transaction' : 'event';
                itemHeaders = JSON.stringify({
                    content_type: 'application/json',
                    // Internal helper that uses `perf_hooks` to get clock reading
                    type: event.type === 'transaction' ? 'transaction' : 'event',
                });
                if (this._isRateLimited(type)) {
                    return [2 /*return*/, Promise.reject(new utils_1.SentryError("Transport locked till " + JSON.stringify(this._rateLimits, null, 2) + " due to too many requests."))];
                }
                eventPayload = JSON.stringify(event);
                bodyBuffer = Buffer.from(envelopeHeaders + "\n" + itemHeaders + "\n" + eventPayload + "\n");
                return [2 /*return*/, this.sendRequest({
                        body: bodyBuffer,
                        url: this._api.getEnvelopeEndpointWithUrlEncodedAuth(),
                        type: type,
                    })];
            });
        });
    };
    /**
     * Checks if a category is rate-limited
     */
    NetTransport.prototype.isRateLimited = function (category) {
        return this._isRateLimited(category);
    };
    /**
     * Dispatches a Request to Sentry. Only handles SentryRequest
     */
    NetTransport.prototype.sendRequest = function (request) {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var options, bodyStream;
            var _this = this;
            return tslib_1.__generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!this._buffer.isReady()) {
                            return [2 /*return*/, Promise.reject(new utils_1.SentryError('Not adding Promise due to buffer limit reached.'))];
                        }
                        return [4 /*yield*/, backend_1.isAppReady()];
                    case 1:
                        _a.sent();
                        options = this._getRequestOptions(new url.URL(request.url));
                        options.headers = tslib_1.__assign(tslib_1.__assign({}, options.headers), { 'Content-Type': 'application/x-sentry-envelope' });
                        bodyStream = streamFromBody(request.body);
                        if (request.body.length > GZIP_THRESHOLD) {
                            options.headers['Content-Encoding'] = 'gzip';
                            bodyStream = bodyStream.pipe(zlib_1.createGzip());
                        }
                        return [2 /*return*/, this._buffer.add(new Promise(function (resolve, reject) {
                                var req = electron_1.net.request(options);
                                req.on('error', reject);
                                req.on('response', function (res) {
                                    res.on('error', reject);
                                    var status = types_1.Status.fromHttpCode(res.statusCode);
                                    if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
                                        resolve({ status: status });
                                    }
                                    else {
                                        if (status === types_1.Status.RateLimit) {
                                            var retryAfterHeader = res.headers ? res.headers['retry-after'] : '';
                                            retryAfterHeader = (Array.isArray(retryAfterHeader) ? retryAfterHeader[0] : retryAfterHeader);
                                            var rlHeader = res.headers ? res.headers['x-sentry-rate-limits'] : '';
                                            rlHeader = (Array.isArray(rlHeader) ? rlHeader[0] : rlHeader);
                                            var headers = {
                                                'x-sentry-rate-limits': rlHeader,
                                                'retry-after': retryAfterHeader,
                                            };
                                            var limited = _this._handleRateLimit(headers);
                                            if (limited)
                                                utils_1.logger.warn("Too many requests, backing off until: " + _this._disabledUntil(request.type));
                                        }
                                        // tslint:disable:no-unsafe-any
                                        if (res.headers && res.headers['x-sentry-error']) {
                                            var reason = res.headers['x-sentry-error'];
                                            if (Array.isArray(reason)) {
                                                reason = reason.join(', ');
                                            }
                                            // tslint:enable:no-unsafe-any
                                            reject(new utils_1.SentryError("HTTP Error (" + res.statusCode + "): " + reason));
                                        }
                                        else {
                                            reject(new utils_1.SentryError("HTTP Error (" + res.statusCode + ")"));
                                        }
                                    }
                                    // force the socket to drain
                                    res.on('data', function () {
                                        // Drain
                                    });
                                    res.on('end', function () {
                                        // Drain
                                    });
                                });
                                // The docs say that ClientRequest is Writable but the types don't match exactly
                                bodyStream.pipe(req);
                            }))];
                }
            });
        });
    };
    return NetTransport;
}(node_1.Transports.BaseTransport));
exports.NetTransport = NetTransport;
//# sourceMappingURL=net.js.map