first commit

This commit is contained in:
2024-01-19 11:09:11 +01:00
commit b18af7a943
29473 changed files with 4500547 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
import { Polling } from "./polling.js";
import { WS } from "./websocket.js";
import { WT } from "./webtransport.js";
export declare const transports: {
websocket: typeof WS;
webtransport: typeof WT;
polling: typeof Polling;
};

View File

@@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.transports = void 0;
const polling_js_1 = require("./polling.js");
const websocket_js_1 = require("./websocket.js");
const webtransport_js_1 = require("./webtransport.js");
exports.transports = {
websocket: websocket_js_1.WS,
webtransport: webtransport_js_1.WT,
polling: polling_js_1.Polling,
};

View File

@@ -0,0 +1,137 @@
import { Transport } from "../transport.js";
import { RawData } from "engine.io-parser";
import { Emitter } from "@socket.io/component-emitter";
export declare class Polling extends Transport {
private readonly xd;
private polling;
private pollXhr;
private cookieJar?;
/**
* XHR Polling constructor.
*
* @param {Object} opts
* @package
*/
constructor(opts: any);
get name(): string;
/**
* Opens the socket (triggers polling). We write a PING message to determine
* when the transport is open.
*
* @protected
*/
doOpen(): void;
/**
* Pauses polling.
*
* @param {Function} onPause - callback upon buffers are flushed and transport is paused
* @package
*/
pause(onPause: any): void;
/**
* Starts polling cycle.
*
* @private
*/
poll(): void;
/**
* Overloads onData to detect payloads.
*
* @protected
*/
onData(data: any): void;
/**
* For polling, send a close packet.
*
* @protected
*/
doClose(): void;
/**
* Writes a packets payload.
*
* @param {Array} packets - data packets
* @protected
*/
write(packets: any): void;
/**
* Generates uri for connection.
*
* @private
*/
private uri;
/**
* Creates a request.
*
* @param {String} method
* @private
*/
request(opts?: {}): Request;
/**
* Sends data.
*
* @param {String} data to send.
* @param {Function} called upon flush.
* @private
*/
private doWrite;
/**
* Starts a poll cycle.
*
* @private
*/
private doPoll;
}
interface RequestReservedEvents {
success: () => void;
data: (data: RawData) => void;
error: (err: number | Error, context: unknown) => void;
}
export declare class Request extends Emitter<{}, {}, RequestReservedEvents> {
private readonly opts;
private readonly method;
private readonly uri;
private readonly data;
private xhr;
private setTimeoutFn;
private index;
static requestsCount: number;
static requests: {};
/**
* Request constructor
*
* @param {Object} options
* @package
*/
constructor(uri: any, opts: any);
/**
* Creates the XHR object and sends the request.
*
* @private
*/
private create;
/**
* Called upon error.
*
* @private
*/
private onError;
/**
* Cleans up house.
*
* @private
*/
private cleanup;
/**
* Called upon load.
*
* @private
*/
private onLoad;
/**
* Aborts the request.
*
* @package
*/
abort(): void;
}
export {};

View File

@@ -0,0 +1,414 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Request = exports.Polling = void 0;
const transport_js_1 = require("../transport.js");
const debug_1 = __importDefault(require("debug")); // debug()
const yeast_js_1 = require("../contrib/yeast.js");
const engine_io_parser_1 = require("engine.io-parser");
const xmlhttprequest_js_1 = require("./xmlhttprequest.js");
const component_emitter_1 = require("@socket.io/component-emitter");
const util_js_1 = require("../util.js");
const globalThis_js_1 = require("../globalThis.js");
const debug = (0, debug_1.default)("engine.io-client:polling"); // debug()
function empty() { }
const hasXHR2 = (function () {
const xhr = new xmlhttprequest_js_1.XHR({
xdomain: false,
});
return null != xhr.responseType;
})();
class Polling extends transport_js_1.Transport {
/**
* XHR Polling constructor.
*
* @param {Object} opts
* @package
*/
constructor(opts) {
super(opts);
this.polling = false;
if (typeof location !== "undefined") {
const isSSL = "https:" === location.protocol;
let port = location.port;
// some user agents have empty `location.port`
if (!port) {
port = isSSL ? "443" : "80";
}
this.xd =
(typeof location !== "undefined" &&
opts.hostname !== location.hostname) ||
port !== opts.port;
}
/**
* XHR supports binary
*/
const forceBase64 = opts && opts.forceBase64;
this.supportsBinary = hasXHR2 && !forceBase64;
if (this.opts.withCredentials) {
this.cookieJar = (0, xmlhttprequest_js_1.createCookieJar)();
}
}
get name() {
return "polling";
}
/**
* Opens the socket (triggers polling). We write a PING message to determine
* when the transport is open.
*
* @protected
*/
doOpen() {
this.poll();
}
/**
* Pauses polling.
*
* @param {Function} onPause - callback upon buffers are flushed and transport is paused
* @package
*/
pause(onPause) {
this.readyState = "pausing";
const pause = () => {
debug("paused");
this.readyState = "paused";
onPause();
};
if (this.polling || !this.writable) {
let total = 0;
if (this.polling) {
debug("we are currently polling - waiting to pause");
total++;
this.once("pollComplete", function () {
debug("pre-pause polling complete");
--total || pause();
});
}
if (!this.writable) {
debug("we are currently writing - waiting to pause");
total++;
this.once("drain", function () {
debug("pre-pause writing complete");
--total || pause();
});
}
}
else {
pause();
}
}
/**
* Starts polling cycle.
*
* @private
*/
poll() {
debug("polling");
this.polling = true;
this.doPoll();
this.emitReserved("poll");
}
/**
* Overloads onData to detect payloads.
*
* @protected
*/
onData(data) {
debug("polling got data %s", data);
const callback = (packet) => {
// if its the first message we consider the transport open
if ("opening" === this.readyState && packet.type === "open") {
this.onOpen();
}
// if its a close packet, we close the ongoing requests
if ("close" === packet.type) {
this.onClose({ description: "transport closed by the server" });
return false;
}
// otherwise bypass onData and handle the message
this.onPacket(packet);
};
// decode payload
(0, engine_io_parser_1.decodePayload)(data, this.socket.binaryType).forEach(callback);
// if an event did not trigger closing
if ("closed" !== this.readyState) {
// if we got data we're not polling
this.polling = false;
this.emitReserved("pollComplete");
if ("open" === this.readyState) {
this.poll();
}
else {
debug('ignoring poll - transport state "%s"', this.readyState);
}
}
}
/**
* For polling, send a close packet.
*
* @protected
*/
doClose() {
const close = () => {
debug("writing close packet");
this.write([{ type: "close" }]);
};
if ("open" === this.readyState) {
debug("transport open - closing");
close();
}
else {
// in case we're trying to close while
// handshaking is in progress (GH-164)
debug("transport not open - deferring close");
this.once("open", close);
}
}
/**
* Writes a packets payload.
*
* @param {Array} packets - data packets
* @protected
*/
write(packets) {
this.writable = false;
(0, engine_io_parser_1.encodePayload)(packets, (data) => {
this.doWrite(data, () => {
this.writable = true;
this.emitReserved("drain");
});
});
}
/**
* Generates uri for connection.
*
* @private
*/
uri() {
const schema = this.opts.secure ? "https" : "http";
const query = this.query || {};
// cache busting is forced
if (false !== this.opts.timestampRequests) {
query[this.opts.timestampParam] = (0, yeast_js_1.yeast)();
}
if (!this.supportsBinary && !query.sid) {
query.b64 = 1;
}
return this.createUri(schema, query);
}
/**
* Creates a request.
*
* @param {String} method
* @private
*/
request(opts = {}) {
Object.assign(opts, { xd: this.xd, cookieJar: this.cookieJar }, this.opts);
return new Request(this.uri(), opts);
}
/**
* Sends data.
*
* @param {String} data to send.
* @param {Function} called upon flush.
* @private
*/
doWrite(data, fn) {
const req = this.request({
method: "POST",
data: data,
});
req.on("success", fn);
req.on("error", (xhrStatus, context) => {
this.onError("xhr post error", xhrStatus, context);
});
}
/**
* Starts a poll cycle.
*
* @private
*/
doPoll() {
debug("xhr poll");
const req = this.request();
req.on("data", this.onData.bind(this));
req.on("error", (xhrStatus, context) => {
this.onError("xhr poll error", xhrStatus, context);
});
this.pollXhr = req;
}
}
exports.Polling = Polling;
class Request extends component_emitter_1.Emitter {
/**
* Request constructor
*
* @param {Object} options
* @package
*/
constructor(uri, opts) {
super();
(0, util_js_1.installTimerFunctions)(this, opts);
this.opts = opts;
this.method = opts.method || "GET";
this.uri = uri;
this.data = undefined !== opts.data ? opts.data : null;
this.create();
}
/**
* Creates the XHR object and sends the request.
*
* @private
*/
create() {
var _a;
const opts = (0, util_js_1.pick)(this.opts, "agent", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "rejectUnauthorized", "autoUnref");
opts.xdomain = !!this.opts.xd;
const xhr = (this.xhr = new xmlhttprequest_js_1.XHR(opts));
try {
debug("xhr open %s: %s", this.method, this.uri);
xhr.open(this.method, this.uri, true);
try {
if (this.opts.extraHeaders) {
xhr.setDisableHeaderCheck && xhr.setDisableHeaderCheck(true);
for (let i in this.opts.extraHeaders) {
if (this.opts.extraHeaders.hasOwnProperty(i)) {
xhr.setRequestHeader(i, this.opts.extraHeaders[i]);
}
}
}
}
catch (e) { }
if ("POST" === this.method) {
try {
xhr.setRequestHeader("Content-type", "text/plain;charset=UTF-8");
}
catch (e) { }
}
try {
xhr.setRequestHeader("Accept", "*/*");
}
catch (e) { }
(_a = this.opts.cookieJar) === null || _a === void 0 ? void 0 : _a.addCookies(xhr);
// ie6 check
if ("withCredentials" in xhr) {
xhr.withCredentials = this.opts.withCredentials;
}
if (this.opts.requestTimeout) {
xhr.timeout = this.opts.requestTimeout;
}
xhr.onreadystatechange = () => {
var _a;
if (xhr.readyState === 3) {
(_a = this.opts.cookieJar) === null || _a === void 0 ? void 0 : _a.parseCookies(xhr);
}
if (4 !== xhr.readyState)
return;
if (200 === xhr.status || 1223 === xhr.status) {
this.onLoad();
}
else {
// make sure the `error` event handler that's user-set
// does not throw in the same tick and gets caught here
this.setTimeoutFn(() => {
this.onError(typeof xhr.status === "number" ? xhr.status : 0);
}, 0);
}
};
debug("xhr data %s", this.data);
xhr.send(this.data);
}
catch (e) {
// Need to defer since .create() is called directly from the constructor
// and thus the 'error' event can only be only bound *after* this exception
// occurs. Therefore, also, we cannot throw here at all.
this.setTimeoutFn(() => {
this.onError(e);
}, 0);
return;
}
if (typeof document !== "undefined") {
this.index = Request.requestsCount++;
Request.requests[this.index] = this;
}
}
/**
* Called upon error.
*
* @private
*/
onError(err) {
this.emitReserved("error", err, this.xhr);
this.cleanup(true);
}
/**
* Cleans up house.
*
* @private
*/
cleanup(fromError) {
if ("undefined" === typeof this.xhr || null === this.xhr) {
return;
}
this.xhr.onreadystatechange = empty;
if (fromError) {
try {
this.xhr.abort();
}
catch (e) { }
}
if (typeof document !== "undefined") {
delete Request.requests[this.index];
}
this.xhr = null;
}
/**
* Called upon load.
*
* @private
*/
onLoad() {
const data = this.xhr.responseText;
if (data !== null) {
this.emitReserved("data", data);
this.emitReserved("success");
this.cleanup();
}
}
/**
* Aborts the request.
*
* @package
*/
abort() {
this.cleanup();
}
}
exports.Request = Request;
Request.requestsCount = 0;
Request.requests = {};
/**
* Aborts pending requests when unloading the window. This is needed to prevent
* memory leaks (e.g. when using IE) and to ensure that no spurious error is
* emitted.
*/
if (typeof document !== "undefined") {
// @ts-ignore
if (typeof attachEvent === "function") {
// @ts-ignore
attachEvent("onunload", unloadHandler);
}
else if (typeof addEventListener === "function") {
const terminationEvent = "onpagehide" in globalThis_js_1.globalThisShim ? "pagehide" : "unload";
addEventListener(terminationEvent, unloadHandler, false);
}
}
function unloadHandler() {
for (let i in Request.requests) {
if (Request.requests.hasOwnProperty(i)) {
Request.requests[i].abort();
}
}
}

View File

@@ -0,0 +1,4 @@
export declare const nextTick: (cb: any, setTimeoutFn: any) => any;
export declare const WebSocket: any;
export declare const usingBrowserWebSocket = true;
export declare const defaultBinaryType = "arraybuffer";

View File

@@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultBinaryType = exports.usingBrowserWebSocket = exports.WebSocket = exports.nextTick = void 0;
const globalThis_js_1 = require("../globalThis.js");
exports.nextTick = (() => {
const isPromiseAvailable = typeof Promise === "function" && typeof Promise.resolve === "function";
if (isPromiseAvailable) {
return (cb) => Promise.resolve().then(cb);
}
else {
return (cb, setTimeoutFn) => setTimeoutFn(cb, 0);
}
})();
exports.WebSocket = globalThis_js_1.globalThisShim.WebSocket || globalThis_js_1.globalThisShim.MozWebSocket;
exports.usingBrowserWebSocket = true;
exports.defaultBinaryType = "arraybuffer";

View File

@@ -0,0 +1,4 @@
export declare const WebSocket: any;
export declare const usingBrowserWebSocket = false;
export declare const defaultBinaryType = "nodebuffer";
export declare const nextTick: (callback: Function, ...args: any[]) => void;

View File

@@ -0,0 +1,11 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.nextTick = exports.defaultBinaryType = exports.usingBrowserWebSocket = exports.WebSocket = void 0;
const ws_1 = __importDefault(require("ws"));
exports.WebSocket = ws_1.default;
exports.usingBrowserWebSocket = false;
exports.defaultBinaryType = "nodebuffer";
exports.nextTick = process.nextTick;

View File

@@ -0,0 +1,34 @@
import { Transport } from "../transport.js";
export declare class WS extends Transport {
private ws;
/**
* WebSocket transport constructor.
*
* @param {Object} opts - connection options
* @protected
*/
constructor(opts: any);
get name(): string;
doOpen(): this;
/**
* Adds event listeners to the socket
*
* @private
*/
private addEventListeners;
write(packets: any): void;
doClose(): void;
/**
* Generates uri for connection.
*
* @private
*/
private uri;
/**
* Feature detection for WebSocket.
*
* @return {Boolean} whether this transport is available.
* @private
*/
private check;
}

View File

@@ -0,0 +1,162 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WS = void 0;
const transport_js_1 = require("../transport.js");
const yeast_js_1 = require("../contrib/yeast.js");
const util_js_1 = require("../util.js");
const websocket_constructor_js_1 = require("./websocket-constructor.js");
const debug_1 = __importDefault(require("debug")); // debug()
const engine_io_parser_1 = require("engine.io-parser");
const debug = (0, debug_1.default)("engine.io-client:websocket"); // debug()
// detect ReactNative environment
const isReactNative = typeof navigator !== "undefined" &&
typeof navigator.product === "string" &&
navigator.product.toLowerCase() === "reactnative";
class WS extends transport_js_1.Transport {
/**
* WebSocket transport constructor.
*
* @param {Object} opts - connection options
* @protected
*/
constructor(opts) {
super(opts);
this.supportsBinary = !opts.forceBase64;
}
get name() {
return "websocket";
}
doOpen() {
if (!this.check()) {
// let probe timeout
return;
}
const uri = this.uri();
const protocols = this.opts.protocols;
// React Native only supports the 'headers' option, and will print a warning if anything else is passed
const opts = isReactNative
? {}
: (0, util_js_1.pick)(this.opts, "agent", "perMessageDeflate", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "rejectUnauthorized", "localAddress", "protocolVersion", "origin", "maxPayload", "family", "checkServerIdentity");
if (this.opts.extraHeaders) {
opts.headers = this.opts.extraHeaders;
}
try {
this.ws =
websocket_constructor_js_1.usingBrowserWebSocket && !isReactNative
? protocols
? new websocket_constructor_js_1.WebSocket(uri, protocols)
: new websocket_constructor_js_1.WebSocket(uri)
: new websocket_constructor_js_1.WebSocket(uri, protocols, opts);
}
catch (err) {
return this.emitReserved("error", err);
}
this.ws.binaryType = this.socket.binaryType;
this.addEventListeners();
}
/**
* Adds event listeners to the socket
*
* @private
*/
addEventListeners() {
this.ws.onopen = () => {
if (this.opts.autoUnref) {
this.ws._socket.unref();
}
this.onOpen();
};
this.ws.onclose = (closeEvent) => this.onClose({
description: "websocket connection closed",
context: closeEvent,
});
this.ws.onmessage = (ev) => this.onData(ev.data);
this.ws.onerror = (e) => this.onError("websocket error", e);
}
write(packets) {
this.writable = false;
// encodePacket efficient as it uses WS framing
// no need for encodePayload
for (let i = 0; i < packets.length; i++) {
const packet = packets[i];
const lastPacket = i === packets.length - 1;
(0, engine_io_parser_1.encodePacket)(packet, this.supportsBinary, (data) => {
// always create a new object (GH-437)
const opts = {};
if (!websocket_constructor_js_1.usingBrowserWebSocket) {
if (packet.options) {
opts.compress = packet.options.compress;
}
if (this.opts.perMessageDeflate) {
const len =
// @ts-ignore
"string" === typeof data ? Buffer.byteLength(data) : data.length;
if (len < this.opts.perMessageDeflate.threshold) {
opts.compress = false;
}
}
}
// Sometimes the websocket has already been closed but the browser didn't
// have a chance of informing us about it yet, in that case send will
// throw an error
try {
if (websocket_constructor_js_1.usingBrowserWebSocket) {
// TypeError is thrown when passing the second argument on Safari
this.ws.send(data);
}
else {
this.ws.send(data, opts);
}
}
catch (e) {
debug("websocket closed before onclose event");
}
if (lastPacket) {
// fake drain
// defer to next tick to allow Socket to clear writeBuffer
(0, websocket_constructor_js_1.nextTick)(() => {
this.writable = true;
this.emitReserved("drain");
}, this.setTimeoutFn);
}
});
}
}
doClose() {
if (typeof this.ws !== "undefined") {
this.ws.close();
this.ws = null;
}
}
/**
* Generates uri for connection.
*
* @private
*/
uri() {
const schema = this.opts.secure ? "wss" : "ws";
const query = this.query || {};
// append timestamp to URI
if (this.opts.timestampRequests) {
query[this.opts.timestampParam] = (0, yeast_js_1.yeast)();
}
// communicate binary support capabilities
if (!this.supportsBinary) {
query.b64 = 1;
}
return this.createUri(schema, query);
}
/**
* Feature detection for WebSocket.
*
* @return {Boolean} whether this transport is available.
* @private
*/
check() {
return !!websocket_constructor_js_1.WebSocket;
}
}
exports.WS = WS;

View File

@@ -0,0 +1,10 @@
import { Transport } from "../transport.js";
import { Packet } from "engine.io-parser";
export declare class WT extends Transport {
private transport;
private writer;
get name(): string;
protected doOpen(): void;
protected write(packets: Packet[]): void;
protected doClose(): void;
}

View File

@@ -0,0 +1,85 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WT = void 0;
const transport_js_1 = require("../transport.js");
const websocket_constructor_js_1 = require("./websocket-constructor.js");
const engine_io_parser_1 = require("engine.io-parser");
const debug_1 = __importDefault(require("debug")); // debug()
const debug = (0, debug_1.default)("engine.io-client:webtransport"); // debug()
class WT extends transport_js_1.Transport {
get name() {
return "webtransport";
}
doOpen() {
// @ts-ignore
if (typeof WebTransport !== "function") {
return;
}
// @ts-ignore
this.transport = new WebTransport(this.createUri("https"), this.opts.transportOptions[this.name]);
this.transport.closed
.then(() => {
debug("transport closed gracefully");
this.onClose();
})
.catch((err) => {
debug("transport closed due to %s", err);
this.onError("webtransport error", err);
});
// note: we could have used async/await, but that would require some additional polyfills
this.transport.ready.then(() => {
this.transport.createBidirectionalStream().then((stream) => {
const decoderStream = (0, engine_io_parser_1.createPacketDecoderStream)(Number.MAX_SAFE_INTEGER, this.socket.binaryType);
const reader = stream.readable.pipeThrough(decoderStream).getReader();
const encoderStream = (0, engine_io_parser_1.createPacketEncoderStream)();
encoderStream.readable.pipeTo(stream.writable);
this.writer = encoderStream.writable.getWriter();
const read = () => {
reader
.read()
.then(({ done, value }) => {
if (done) {
debug("session is closed");
return;
}
debug("received chunk: %o", value);
this.onPacket(value);
read();
})
.catch((err) => {
debug("an error occurred while reading: %s", err);
});
};
read();
const packet = { type: "open" };
if (this.query.sid) {
packet.data = `{"sid":"${this.query.sid}"}`;
}
this.writer.write(packet).then(() => this.onOpen());
});
});
}
write(packets) {
this.writable = false;
for (let i = 0; i < packets.length; i++) {
const packet = packets[i];
const lastPacket = i === packets.length - 1;
this.writer.write(packet).then(() => {
if (lastPacket) {
(0, websocket_constructor_js_1.nextTick)(() => {
this.writable = true;
this.emitReserved("drain");
}, this.setTimeoutFn);
}
});
}
}
doClose() {
var _a;
(_a = this.transport) === null || _a === void 0 ? void 0 : _a.close();
}
}
exports.WT = WT;

View File

@@ -0,0 +1,2 @@
export declare function XHR(opts: any): any;
export declare function createCookieJar(): void;

View File

@@ -0,0 +1,25 @@
"use strict";
// browser shim for xmlhttprequest module
Object.defineProperty(exports, "__esModule", { value: true });
exports.createCookieJar = exports.XHR = void 0;
const has_cors_js_1 = require("../contrib/has-cors.js");
const globalThis_js_1 = require("../globalThis.js");
function XHR(opts) {
const xdomain = opts.xdomain;
// XMLHttpRequest can be disabled on IE
try {
if ("undefined" !== typeof XMLHttpRequest && (!xdomain || has_cors_js_1.hasCORS)) {
return new XMLHttpRequest();
}
}
catch (e) { }
if (!xdomain) {
try {
return new globalThis_js_1.globalThisShim[["Active"].concat("Object").join("X")]("Microsoft.XMLHTTP");
}
catch (e) { }
}
}
exports.XHR = XHR;
function createCookieJar() { }
exports.createCookieJar = createCookieJar;

View File

@@ -0,0 +1,17 @@
export declare const XHR: any;
export declare function createCookieJar(): CookieJar;
interface Cookie {
name: string;
value: string;
expires?: Date;
}
/**
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
*/
export declare function parse(setCookieString: string): Cookie;
export declare class CookieJar {
private cookies;
parseCookies(xhr: any): void;
addCookies(xhr: any): void;
}
export {};

View File

@@ -0,0 +1,111 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CookieJar = exports.parse = exports.createCookieJar = exports.XHR = void 0;
const XMLHttpRequestModule = __importStar(require("xmlhttprequest-ssl"));
exports.XHR = XMLHttpRequestModule.default || XMLHttpRequestModule;
function createCookieJar() {
return new CookieJar();
}
exports.createCookieJar = createCookieJar;
/**
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
*/
function parse(setCookieString) {
const parts = setCookieString.split("; ");
const i = parts[0].indexOf("=");
if (i === -1) {
return;
}
const name = parts[0].substring(0, i).trim();
if (!name.length) {
return;
}
let value = parts[0].substring(i + 1).trim();
if (value.charCodeAt(0) === 0x22) {
// remove double quotes
value = value.slice(1, -1);
}
const cookie = {
name,
value,
};
for (let j = 1; j < parts.length; j++) {
const subParts = parts[j].split("=");
if (subParts.length !== 2) {
continue;
}
const key = subParts[0].trim();
const value = subParts[1].trim();
switch (key) {
case "Expires":
cookie.expires = new Date(value);
break;
case "Max-Age":
const expiration = new Date();
expiration.setUTCSeconds(expiration.getUTCSeconds() + parseInt(value, 10));
cookie.expires = expiration;
break;
default:
// ignore other keys
}
}
return cookie;
}
exports.parse = parse;
class CookieJar {
constructor() {
this.cookies = new Map();
}
parseCookies(xhr) {
const values = xhr.getResponseHeader("set-cookie");
if (!values) {
return;
}
values.forEach((value) => {
const parsed = parse(value);
if (parsed) {
this.cookies.set(parsed.name, parsed);
}
});
}
addCookies(xhr) {
const cookies = [];
this.cookies.forEach((cookie, name) => {
var _a;
if (((_a = cookie.expires) === null || _a === void 0 ? void 0 : _a.getTime()) < Date.now()) {
this.cookies.delete(name);
}
else {
cookies.push(`${name}=${cookie.value}`);
}
});
if (cookies.length) {
xhr.setDisableHeaderCheck(true);
xhr.setRequestHeader("cookie", cookies.join("; "));
}
}
}
exports.CookieJar = CookieJar;