feat: Reinitialize frontend with SvelteKit and TypeScript

- Delete old Vite+Svelte frontend
- Initialize new SvelteKit project with TypeScript
- Configure Tailwind CSS v4 + DaisyUI
- Implement JWT authentication with auto-refresh
- Create login page with form validation (Zod)
- Add protected route guards
- Update Docker configuration for single-stage build
- Add E2E tests with Playwright (6/11 passing)
- Fix Svelte 5 reactivity with $state() runes

Known issues:
- 5 E2E tests failing (timing/async issues)
- Token refresh implementation needs debugging
- Validation error display timing
This commit is contained in:
2026-02-17 16:19:59 -05:00
parent 54df6018f5
commit de2d83092e
28274 changed files with 3816354 additions and 90 deletions

View File

@@ -0,0 +1,55 @@
"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 () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
const PropertySymbol = __importStar(require("../PropertySymbol.cjs"));
/**
* AbortController.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/AbortController
*/
class AbortController {
// Public properties
signal = new this[PropertySymbol.window].AbortSignal();
/**
* Aborts the signal.
*
* @param [reason] Reason.
*/
abort(reason) {
this.signal[PropertySymbol.abort](reason);
}
}
exports.default = AbortController;
//# sourceMappingURL=AbortController.cjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"AbortController.cjs","sourceRoot":"","sources":["../../src/fetch/AbortController.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,qEAAuD;AAGvD;;;;GAIG;AACH,MAAqB,eAAe;IAInC,oBAAoB;IACJ,MAAM,GAAgB,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;IAEpF;;;;OAIG;IACI,KAAK,CAAC,MAAY;QACxB,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC;IAC3C,CAAC;CACD;AAfD,kCAeC"}

View File

@@ -0,0 +1,19 @@
import AbortSignal from './AbortSignal.cjs';
import * as PropertySymbol from '../PropertySymbol.cjs';
import BrowserWindow from '../window/BrowserWindow.cjs';
/**
* AbortController.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/AbortController
*/
export default class AbortController {
protected [PropertySymbol.window]: BrowserWindow;
readonly signal: AbortSignal;
/**
* Aborts the signal.
*
* @param [reason] Reason.
*/
abort(reason?: any): void;
}
//# sourceMappingURL=AbortController.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"AbortController.d.ts","sourceRoot":"","sources":["../../src/fetch/AbortController.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,kBAAkB,CAAC;AAC3C,OAAO,KAAK,cAAc,MAAM,sBAAsB,CAAC;AACvD,OAAO,aAAa,MAAM,4BAA4B,CAAC;AAEvD;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,eAAe;IAEnC,UAAkB,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAGzD,SAAgB,MAAM,EAAE,WAAW,CAAiD;IAEpF;;;;OAIG;IACI,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,GAAG,IAAI;CAGhC"}

View File

@@ -0,0 +1,191 @@
"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 () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const EventTarget_js_1 = __importDefault(require("../event/EventTarget.cjs"));
const PropertySymbol = __importStar(require("../PropertySymbol.cjs"));
const Event_js_1 = __importDefault(require("../event/Event.cjs"));
const DOMExceptionNameEnum_js_1 = __importDefault(require("../exception/DOMExceptionNameEnum.cjs"));
/**
* AbortSignal.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal
*/
class AbortSignal extends EventTarget_js_1.default {
// Internal properties
[PropertySymbol.aborted] = false;
[PropertySymbol.reason] = undefined;
// Events
onabort = null;
/**
* Constructor.
*/
constructor() {
super();
if (!this[PropertySymbol.window]) {
throw new TypeError(`Failed to construct 'AbortSignal': Illegal constructor`);
}
}
/**
* Return a default description for the AbortSignal class.
*/
get [Symbol.toStringTag]() {
return 'AbortSignal';
}
/**
* Returns true if the signal has been aborted.
*
* @returns True if the signal has been aborted.
*/
get aborted() {
return this[PropertySymbol.aborted];
}
/**
* Setter for aborted. Value will be ignored as the property is read-only.
*
* @param _value Aborted.
*/
set aborted(_value) {
// Do nothing
}
/**
* Returns the reason the signal was aborted.
*
* @returns Reason.
*/
get reason() {
return this[PropertySymbol.reason];
}
/**
* Setter for reason. Value will be ignored as the property is read-only.
*
* @param _value Reason.
*/
set reason(_value) {
// Do nothing
}
/**
* Aborts the signal.
*
* @param [reason] Reason.
*/
[PropertySymbol.abort](reason) {
if (this.aborted) {
return;
}
this[PropertySymbol.reason] =
reason !== undefined
? reason
: new this[PropertySymbol.window].DOMException('signal is aborted without reason', DOMExceptionNameEnum_js_1.default.abortError);
this[PropertySymbol.aborted] = true;
this.dispatchEvent(new Event_js_1.default('abort'));
}
/**
* Throws an "AbortError" if the signal has been aborted.
*/
throwIfAborted() {
if (this.aborted) {
throw this.reason;
}
}
/**
* Returns an AbortSignal instance that has been set as aborted.
*
* @param [reason] Reason.
* @returns AbortSignal instance.
*/
static abort(reason) {
const signal = new this();
signal[PropertySymbol.reason] =
reason !== undefined
? reason
: new this[PropertySymbol.window].DOMException('signal is aborted without reason', DOMExceptionNameEnum_js_1.default.abortError);
signal[PropertySymbol.aborted] = true;
return signal;
}
/**
* Returns an AbortSignal that will automatically abort after a specified
* time.
*
* @param [time] Time in milliseconds.
* @returns AbortSignal instance.
*/
static timeout(time) {
const window = this[PropertySymbol.window];
const signal = new this();
window.setTimeout(() => {
signal[PropertySymbol.abort](new window.DOMException('signal timed out', DOMExceptionNameEnum_js_1.default.timeoutError));
}, time);
return signal;
}
/**
* Takes an iterable of abort signals and returns an AbortSignal that is
* aborted when any of the input iterable abort signals are aborted.
*
* The abort reason will be set to the reason of the first signal that is
* aborted. If any of the given abort signals are already aborted then so will
* be the returned AbortSignal.
*
* @param [signals] Iterable of abort signals.
* @returns AbortSignal instance.
*/
static any(signals) {
for (const signal of signals) {
if (signal[PropertySymbol.aborted]) {
return this.abort(signal[PropertySymbol.reason]);
}
}
const anySignal = new this();
const handlers = new Map();
const stopListening = () => {
for (const signal of signals) {
signal.removeEventListener('abort', handlers.get(signal));
}
};
for (const signal of signals) {
const handler = () => {
stopListening();
anySignal[PropertySymbol.abort](signal[PropertySymbol.reason]);
};
handlers.set(signal, handler);
signal.addEventListener('abort', handler);
}
return anySignal;
}
}
exports.default = AbortSignal;
//# sourceMappingURL=AbortSignal.cjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"AbortSignal.cjs","sourceRoot":"","sources":["../../src/fetch/AbortSignal.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,86 @@
import EventTarget from '../event/EventTarget.cjs';
import * as PropertySymbol from '../PropertySymbol.cjs';
import Event from '../event/Event.cjs';
import BrowserWindow from '../window/BrowserWindow.cjs';
/**
* AbortSignal.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal
*/
export default class AbortSignal extends EventTarget {
protected static [PropertySymbol.window]: BrowserWindow;
protected [PropertySymbol.window]: BrowserWindow;
[PropertySymbol.aborted]: boolean;
[PropertySymbol.reason]: any;
onabort: ((this: AbortSignal, event: Event) => void) | null;
/**
* Constructor.
*/
constructor();
/**
* Return a default description for the AbortSignal class.
*/
get [Symbol.toStringTag](): string;
/**
* Returns true if the signal has been aborted.
*
* @returns True if the signal has been aborted.
*/
get aborted(): boolean;
/**
* Setter for aborted. Value will be ignored as the property is read-only.
*
* @param _value Aborted.
*/
set aborted(_value: boolean);
/**
* Returns the reason the signal was aborted.
*
* @returns Reason.
*/
get reason(): any;
/**
* Setter for reason. Value will be ignored as the property is read-only.
*
* @param _value Reason.
*/
set reason(_value: any);
/**
* Aborts the signal.
*
* @param [reason] Reason.
*/
[PropertySymbol.abort](reason?: any): void;
/**
* Throws an "AbortError" if the signal has been aborted.
*/
throwIfAborted(): void;
/**
* Returns an AbortSignal instance that has been set as aborted.
*
* @param [reason] Reason.
* @returns AbortSignal instance.
*/
static abort(reason?: any): AbortSignal;
/**
* Returns an AbortSignal that will automatically abort after a specified
* time.
*
* @param [time] Time in milliseconds.
* @returns AbortSignal instance.
*/
static timeout(time: number): AbortSignal;
/**
* Takes an iterable of abort signals and returns an AbortSignal that is
* aborted when any of the input iterable abort signals are aborted.
*
* The abort reason will be set to the reason of the first signal that is
* aborted. If any of the given abort signals are already aborted then so will
* be the returned AbortSignal.
*
* @param [signals] Iterable of abort signals.
* @returns AbortSignal instance.
*/
static any(signals: AbortSignal[]): AbortSignal;
}
//# sourceMappingURL=AbortSignal.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"AbortSignal.d.ts","sourceRoot":"","sources":["../../src/fetch/AbortSignal.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,yBAAyB,CAAC;AAClD,OAAO,KAAK,cAAc,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,MAAM,mBAAmB,CAAC;AAEtC,OAAO,aAAa,MAAM,4BAA4B,CAAC;AAEvD;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,WAAW;IAEnD,iBAAyB,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAChE,UAAkB,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAGlD,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,OAAO,CAAS;IAC1C,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,GAAG,CAAa;IAGzC,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IAE1E;;OAEG;;IASH;;OAEG;IACH,IAAW,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,MAAM,CAExC;IAED;;;;OAIG;IACH,IAAW,OAAO,IAAI,OAAO,CAE5B;IAED;;;;OAIG;IACH,IAAW,OAAO,CAAC,MAAM,EAAE,OAAO,EAEjC;IAED;;;;OAIG;IACH,IAAW,MAAM,IAAI,GAAG,CAEvB;IAED;;;;OAIG;IACH,IAAW,MAAM,CAAC,MAAM,EAAE,GAAG,EAE5B;IAED;;;;OAIG;IACI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,GAAG,IAAI;IAejD;;OAEG;IACI,cAAc,IAAI,IAAI;IAM7B;;;;;OAKG;WACW,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,GAAG,WAAW;IAa9C;;;;;;OAMG;WACW,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW;IAWhD;;;;;;;;;;OAUG;WACW,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,WAAW;CA2BtD"}

838
frontend/node_modules/happy-dom/cjs/fetch/Fetch.cjs generated vendored Normal file
View File

@@ -0,0 +1,838 @@
"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 () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const PropertySymbol = __importStar(require("../PropertySymbol.cjs"));
const Headers_js_1 = __importDefault(require("./Headers.cjs"));
const FetchRequestReferrerUtility_js_1 = __importDefault(require("./utilities/FetchRequestReferrerUtility.cjs"));
const DOMExceptionNameEnum_js_1 = __importDefault(require("../exception/DOMExceptionNameEnum.cjs"));
const http_1 = __importDefault(require("http"));
const https_1 = __importDefault(require("https"));
const zlib_1 = __importDefault(require("zlib"));
const url_1 = require("url");
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const stream_1 = __importDefault(require("stream"));
const DataURIParser_js_1 = __importDefault(require("./data-uri/DataURIParser.cjs"));
const FetchCORSUtility_js_1 = __importDefault(require("./utilities/FetchCORSUtility.cjs"));
const Response_js_1 = __importDefault(require("./Response.cjs"));
const CachedResponseStateEnum_js_1 = __importDefault(require("./cache/response/CachedResponseStateEnum.cjs"));
const FetchRequestHeaderUtility_js_1 = __importDefault(require("./utilities/FetchRequestHeaderUtility.cjs"));
const FetchRequestValidationUtility_js_1 = __importDefault(require("./utilities/FetchRequestValidationUtility.cjs"));
const FetchResponseRedirectUtility_js_1 = __importDefault(require("./utilities/FetchResponseRedirectUtility.cjs"));
const FetchResponseHeaderUtility_js_1 = __importDefault(require("./utilities/FetchResponseHeaderUtility.cjs"));
const FetchHTTPSCertificate_js_1 = __importDefault(require("./certificate/FetchHTTPSCertificate.cjs"));
const buffer_1 = require("buffer");
const FetchBodyUtility_js_1 = __importDefault(require("./utilities/FetchBodyUtility.cjs"));
const VirtualServerUtility_js_1 = __importDefault(require("./utilities/VirtualServerUtility.cjs"));
const PreloadUtility_js_1 = __importDefault(require("./preload/PreloadUtility.cjs"));
const LAST_CHUNK = buffer_1.Buffer.from('0\r\n\r\n');
/**
* Handles fetch requests.
*
* Based on:
* https://github.com/node-fetch/node-fetch/blob/main/src/index.js
*
* @see https://fetch.spec.whatwg.org/#http-network-fetch
*/
class Fetch {
reject = null;
resolve = null;
listeners = {
onSignalAbort: this.onSignalAbort.bind(this)
};
isChunkedTransfer = false;
isProperLastChunkReceived = false;
previousChunk = null;
nodeRequest = null;
nodeResponse = null;
response = null;
responseHeaders = null;
interceptor;
request;
redirectCount = 0;
disableCache;
disableSameOriginPolicy;
disablePreload;
#browserFrame;
#window;
#unfilteredHeaders = null;
/**
* Constructor.
*
* @param options Options.
* @param options.browserFrame Browser frame.
* @param options.window Window.
* @param options.url URL.
* @param [options.init] Init.
* @param [options.redirectCount] Redirect count.
* @param [options.contentType] Content Type.
* @param [options.disableCache] Disables the use of cached responses. It will still store the response in the cache.
* @param [options.disableSameOriginPolicy] Disables the Same-Origin policy.
* @param [options.unfilteredHeaders] Unfiltered headers - necessary for preflight requests.
* @param [options.disablePreload] Disables the use of preloaded responses.
*/
constructor(options) {
this.#browserFrame = options.browserFrame;
this.#window = options.window;
this.#unfilteredHeaders = options.unfilteredHeaders ?? null;
this.request =
typeof options.url === 'string' || options.url instanceof url_1.URL
? new options.window.Request(options.url, options.init)
: options.url;
if (options.contentType) {
this.request[PropertySymbol.contentType] = options.contentType;
}
this.redirectCount = options.redirectCount ?? 0;
this.disableCache = options.disableCache ?? false;
this.disableSameOriginPolicy =
options.disableSameOriginPolicy ??
this.#browserFrame.page.context.browser.settings.fetch.disableSameOriginPolicy ??
false;
this.interceptor = this.#browserFrame.page.context.browser.settings.fetch.interceptor;
this.disablePreload = options.disablePreload ?? false;
}
/**
* Sends request.
*
* @returns Response.
*/
async send() {
FetchRequestReferrerUtility_js_1.default.prepareRequest(new url_1.URL(this.#window.location.href), this.request);
if (this.interceptor?.beforeAsyncRequest) {
const taskID = this.#browserFrame[PropertySymbol.asyncTaskManager].startTask();
const response = await this.interceptor.beforeAsyncRequest({
request: this.request,
window: this.#window
});
this.#browserFrame[PropertySymbol.asyncTaskManager].endTask(taskID);
if (response instanceof Response_js_1.default) {
return response;
}
}
FetchRequestValidationUtility_js_1.default.validateSchema(this.request);
if (this.request.signal[PropertySymbol.aborted]) {
if (this.request.signal[PropertySymbol.reason] !== undefined) {
throw this.request.signal[PropertySymbol.reason];
}
throw new this[PropertySymbol.window].DOMException('signal is aborted without reason', DOMExceptionNameEnum_js_1.default.abortError);
}
if (this.request[PropertySymbol.url].protocol === 'data:') {
const result = DataURIParser_js_1.default.parse(this.request.url);
this.response = new this.#window.Response(result.buffer, {
headers: { 'Content-Type': result.type }
});
const interceptedResponse = this.interceptor?.afterAsyncResponse
? await this.interceptor.afterAsyncResponse({
window: this.#window,
response: this.response,
request: this.request
})
: undefined;
return interceptedResponse instanceof Response_js_1.default ? interceptedResponse : this.response;
}
// Security check for "https" to "http" requests.
if (this.request[PropertySymbol.url].protocol === 'http:' &&
this.#window.location.protocol === 'https:') {
throw new this.#window.DOMException(`Mixed Content: The page at '${this.#window.location.href}' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint '${this.request.url}'. This request has been blocked; the content must be served over HTTPS.`, DOMExceptionNameEnum_js_1.default.securityError);
}
if (!this.disableCache) {
const cachedResponse = await this.getCachedResponse();
if (cachedResponse) {
return cachedResponse;
}
}
if (!this.disablePreload) {
const preloadKey = PreloadUtility_js_1.default.getKey({
url: this.request.url,
destination: 'fetch',
mode: this.request.mode,
credentialsMode: this.request.credentials
});
const preloadEntry = this.#window.document[PropertySymbol.preloads].get(preloadKey);
if (preloadEntry) {
this.#window.document[PropertySymbol.preloads].delete(preloadKey);
if (preloadEntry.response) {
return preloadEntry.response;
}
const taskID = this.#browserFrame[PropertySymbol.asyncTaskManager].startTask();
const response = await preloadEntry.onResponseAvailable();
this.#browserFrame[PropertySymbol.asyncTaskManager].endTask(taskID);
return response;
}
}
const virtualServerResponse = await this.getVirtualServerResponse();
if (virtualServerResponse) {
return virtualServerResponse;
}
if (!this.disableSameOriginPolicy) {
const compliesWithCrossOriginPolicy = await this.compliesWithCrossOriginPolicy();
if (!compliesWithCrossOriginPolicy) {
this.#browserFrame?.page?.console.warn(`Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at "${this.request.url}".`);
throw new this.#window.DOMException(`Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at "${this.request.url}".`, DOMExceptionNameEnum_js_1.default.networkError);
}
}
return await this.sendRequest();
}
/**
* Returns cached response.
*
* @returns Response.
*/
async getCachedResponse() {
if (this.disableCache) {
return null;
}
let cachedResponse = this.#browserFrame.page.context.responseCache.get(this.request);
if (!cachedResponse || cachedResponse.response.waitingForBody) {
return null;
}
if (cachedResponse.state === CachedResponseStateEnum_js_1.default.stale) {
const headers = new Headers_js_1.default(cachedResponse.request.headers);
if (cachedResponse.etag) {
headers.set('If-None-Match', cachedResponse.etag);
}
else {
if (!cachedResponse.lastModified) {
return null;
}
headers.set('If-Modified-Since', new Date(cachedResponse.lastModified).toUTCString());
}
const fetch = new Fetch({
browserFrame: this.#browserFrame,
window: this.#window,
url: this.request.url,
init: { headers, method: cachedResponse.request.method },
disableCache: true,
disableSameOriginPolicy: true
});
if (cachedResponse.etag || !cachedResponse.staleWhileRevalidate) {
const validateResponse = await fetch.send();
const body = validateResponse.status !== 304 ? await validateResponse.buffer() : null;
cachedResponse = this.#browserFrame.page.context.responseCache.add(this.request, {
...validateResponse,
body,
waitingForBody: false
});
if (validateResponse.status !== 304) {
const response = new this.#window.Response(body, {
status: validateResponse.status,
statusText: validateResponse.statusText,
headers: validateResponse.headers
});
response.url = validateResponse.url;
response[PropertySymbol.cachedResponse] = cachedResponse;
return response;
}
}
else {
fetch.send().then((response) => {
response.buffer().then((body) => {
this.#browserFrame.page.context.responseCache.add(this.request, {
...response,
body,
waitingForBody: false
});
});
});
}
}
if (!cachedResponse || cachedResponse.response.waitingForBody) {
return null;
}
const response = new this.#window.Response(cachedResponse.response.body, {
status: cachedResponse.response.status,
statusText: cachedResponse.response.statusText,
headers: cachedResponse.response.headers
});
response.url = cachedResponse.response.url;
response[PropertySymbol.cachedResponse] = cachedResponse;
return response;
}
/**
* Returns virtual server response.
*
* @returns Response.
*/
async getVirtualServerResponse() {
const filePath = VirtualServerUtility_js_1.default.getFilepath(this.#window, this.request.url);
if (!filePath) {
return null;
}
const taskID = this.#browserFrame[PropertySymbol.asyncTaskManager].startTask();
if (this.request.method !== 'GET') {
this.#browserFrame?.page?.console.error(`${this.request.method} ${this.request.url} 404 (Not Found)`);
const response = VirtualServerUtility_js_1.default.getNotFoundResponse(this.#window);
const interceptedResponse = this.interceptor?.afterAsyncResponse
? await this.interceptor.afterAsyncResponse({
window: this.#window,
response: await response,
request: this.request
})
: undefined;
this.#browserFrame[PropertySymbol.asyncTaskManager].endTask(taskID);
return interceptedResponse instanceof Response_js_1.default ? interceptedResponse : response;
}
let buffer;
try {
const stat = await fs_1.default.promises.stat(filePath);
buffer = await fs_1.default.promises.readFile(stat.isDirectory() ? path_1.default.join(filePath, 'index.html') : filePath);
}
catch (error) {
this.#browserFrame?.page?.console.error(`${this.request.method} ${this.request.url} 404 (Not Found)`);
const response = VirtualServerUtility_js_1.default.getNotFoundResponse(this.#window);
const interceptedResponse = this.interceptor?.afterAsyncResponse
? await this.interceptor.afterAsyncResponse({
window: this.#window,
response: await response,
request: this.request
})
: undefined;
this.#browserFrame[PropertySymbol.asyncTaskManager].endTask(taskID);
return interceptedResponse instanceof Response_js_1.default ? interceptedResponse : response;
}
const body = new this.#window.ReadableStream({
start(controller) {
setTimeout(() => {
controller.enqueue(buffer);
controller.close();
});
}
});
const response = new this.#window.Response(body);
response[PropertySymbol.buffer] = buffer;
response.url = this.request.url;
const interceptedResponse = this.interceptor?.afterAsyncResponse
? await this.interceptor.afterAsyncResponse({
window: this.#window,
response: await response,
request: this.request
})
: undefined;
this.#browserFrame[PropertySymbol.asyncTaskManager].endTask(taskID);
const returnResponse = interceptedResponse instanceof Response_js_1.default ? interceptedResponse : response;
const cachedResponse = {
...returnResponse,
body: buffer,
waitingForBody: false
};
response[PropertySymbol.cachedResponse] = this.#browserFrame.page?.context?.responseCache.add(this.request, cachedResponse);
return returnResponse;
}
/**
* Checks if the request complies with the Cross-Origin policy.
*
* @returns True if it complies with the policy.
*/
async compliesWithCrossOriginPolicy() {
if (this.disableSameOriginPolicy ||
!FetchCORSUtility_js_1.default.isCORS(this.#window.location.href, this.request[PropertySymbol.url])) {
return true;
}
const cachedPreflightResponse = this.#browserFrame.page.context.preflightResponseCache.get(this.request);
if (cachedPreflightResponse) {
if (cachedPreflightResponse.allowOrigin !== '*' &&
cachedPreflightResponse.allowOrigin !== this.#window.location.origin) {
return false;
}
if (cachedPreflightResponse.allowMethods.length !== 0 &&
!cachedPreflightResponse.allowMethods.includes(this.request.method)) {
return false;
}
return true;
}
const requestHeaders = [];
for (const [header] of this.request.headers) {
requestHeaders.push(header.toLowerCase());
}
const corsHeaders = new Headers_js_1.default({
'Access-Control-Request-Method': this.request.method,
Origin: this.#window.location.origin
});
if (requestHeaders.length > 0) {
// This intentionally does not use "combine" (comma + space), as the spec dictates.
// See https://fetch.spec.whatwg.org/#cors-preflight-fetch for more details.
// Sorting the headers is not required, but can optimize cache hits.
corsHeaders.set('Access-Control-Request-Headers', requestHeaders.slice().sort().join(','));
}
const fetch = new Fetch({
browserFrame: this.#browserFrame,
window: this.#window,
url: this.request.url,
init: { method: 'OPTIONS' },
disableCache: true,
disableSameOriginPolicy: true,
unfilteredHeaders: corsHeaders
});
const response = await fetch.send();
if (!response.ok) {
return false;
}
const allowOrigin = response.headers.get('Access-Control-Allow-Origin');
if (!allowOrigin) {
return false;
}
if (allowOrigin !== '*' && allowOrigin !== this.#window.location.origin) {
return false;
}
const allowMethods = [];
if (response.headers.has('Access-Control-Allow-Methods')) {
const allowMethodsHeader = response.headers.get('Access-Control-Allow-Methods');
if (allowMethodsHeader !== '*') {
for (const method of allowMethodsHeader.split(',')) {
allowMethods.push(method.trim().toUpperCase());
}
}
}
if (allowMethods.length !== 0 && !allowMethods.includes(this.request.method)) {
return false;
}
// TODO: Add support for more Access-Control-Allow-* headers.
return true;
}
/**
* Sends request.
*
* @returns Response.
*/
sendRequest() {
return new Promise((resolve, reject) => {
const taskID = this.#browserFrame[PropertySymbol.asyncTaskManager].startTask(() => this.onAsyncTaskManagerAbort());
if (this.resolve) {
throw new this.#window.Error('Fetch already sent.');
}
this.resolve = async (response) => {
// We can end up here when closing down the browser frame and there is an ongoing request.
// Therefore, we need to check if browserFrame.page.context is still available.
if (!this.disableCache &&
response instanceof Response_js_1.default &&
this.#browserFrame.page &&
this.#browserFrame.page.context) {
response[PropertySymbol.cachedResponse] =
this.#browserFrame.page.context.responseCache.add(this.request, {
...response,
headers: this.responseHeaders,
body: response[PropertySymbol.buffer],
waitingForBody: !response[PropertySymbol.buffer] && !!response.body
});
}
const interceptedResponse = this.interceptor?.afterAsyncResponse
? await this.interceptor.afterAsyncResponse({
window: this.#window,
response: await response,
request: this.request
})
: undefined;
this.#browserFrame[PropertySymbol.asyncTaskManager].endTask(taskID);
const returnResponse = interceptedResponse instanceof Response_js_1.default ? interceptedResponse : response;
// The browser outputs errors to the console when the response is not ok.
if (returnResponse instanceof Response_js_1.default && !returnResponse.ok) {
this.#browserFrame?.page?.console.error(`${this.request.method} ${this.request.url} ${returnResponse.status} (${returnResponse.statusText})`);
}
resolve(returnResponse);
};
this.reject = (error) => {
this.#browserFrame[PropertySymbol.asyncTaskManager].endTask(taskID);
reject(error);
};
this.request.signal.addEventListener('abort', this.listeners.onSignalAbort);
const send = (this.request[PropertySymbol.url].protocol === 'https:' ? https_1.default : http_1.default).request;
this.nodeRequest = send(this.request[PropertySymbol.url].href, {
method: this.request.method,
headers: FetchRequestHeaderUtility_js_1.default.getRequestHeaders({
browserFrame: this.#browserFrame,
window: this.#window,
request: this.request,
baseHeaders: this.#unfilteredHeaders
}),
agent: false,
rejectUnauthorized: !this.#browserFrame.page.context.browser.settings.fetch.disableStrictSSL,
key: this.request[PropertySymbol.url].protocol === 'https:'
? FetchHTTPSCertificate_js_1.default.key
: undefined,
cert: this.request[PropertySymbol.url].protocol === 'https:'
? FetchHTTPSCertificate_js_1.default.cert
: undefined
});
this.nodeRequest.on('error', this.onError.bind(this));
this.nodeRequest.on('socket', this.onSocket.bind(this));
this.nodeRequest.on('response', this.onResponse.bind(this));
if (this.request.body === null) {
this.nodeRequest.end();
}
else {
stream_1.default.pipeline(this.request.body, this.nodeRequest, (error) => {
if (error) {
this.onError(error);
}
});
}
});
}
/**
* Event listener for "socket" event.
*
* @param socket Socket.
*/
onSocket(socket) {
const onSocketClose = () => {
if (this.isChunkedTransfer && !this.isProperLastChunkReceived) {
const error = new this.#window.DOMException('Premature close.', DOMExceptionNameEnum_js_1.default.networkError);
if (this.response && this.response.body) {
this.response.body[PropertySymbol.error] = error;
if (!this.response.body.locked) {
this.response.body.cancel(error);
}
}
}
};
const onData = (buffer) => {
this.isProperLastChunkReceived = buffer_1.Buffer.compare(buffer.slice(-5), LAST_CHUNK) === 0;
// Sometimes final 0-length chunk and end of message code are in separate packets.
if (!this.isProperLastChunkReceived && this.previousChunk) {
this.isProperLastChunkReceived =
buffer_1.Buffer.compare(this.previousChunk.slice(-3), LAST_CHUNK.slice(0, 3)) === 0 &&
buffer_1.Buffer.compare(buffer.slice(-2), LAST_CHUNK.slice(3)) === 0;
}
this.previousChunk = buffer;
};
socket.prependListener('close', onSocketClose);
socket.on('data', onData);
this.nodeRequest.on('close', () => {
socket.removeListener('close', onSocketClose);
socket.removeListener('data', onData);
});
}
/**
* Event listener for signal "abort" event.
*
* @param event Event.
*/
onSignalAbort(event) {
this.finalizeRequest();
this.abort(event.target?.reason);
}
/**
* Event listener for request "error" event.
*
* @param error Error.
*/
onError(error) {
this.finalizeRequest();
this.#browserFrame?.page?.console.error(error);
this.reject(new this.#window.DOMException(`Failed to execute "fetch()" on "Window" with URL "${this.request.url}": ${error.message}`, DOMExceptionNameEnum_js_1.default.networkError));
}
/**
* Triggered when the async task manager aborts.
*/
onAsyncTaskManagerAbort() {
const error = new this.#window.DOMException('The operation was aborted.', DOMExceptionNameEnum_js_1.default.abortError);
this.request[PropertySymbol.aborted] = true;
if (this.request.body) {
this.request.body[PropertySymbol.error] = error;
}
if (this.listeners.onSignalAbort) {
this.request.signal.removeEventListener('abort', this.listeners.onSignalAbort);
}
if (this.nodeRequest && !this.nodeRequest.destroyed) {
this.nodeRequest.destroy(error);
}
if (this.nodeResponse && !this.nodeResponse.destroyed) {
this.nodeResponse.destroy(error);
}
if (this.response && this.response.body) {
this.response.body[PropertySymbol.error] = error;
if (!this.response.body.locked) {
this.response.body.cancel(error);
}
}
}
/**
* Event listener for request "response" event.
*
* @param nodeResponse Node response.
*/
onResponse(nodeResponse) {
// Needed for handling bad endings of chunked transfer.
this.isChunkedTransfer =
nodeResponse.headers['transfer-encoding'] === 'chunked' &&
!nodeResponse.headers['content-length'];
this.nodeRequest.setTimeout(0);
this.responseHeaders = FetchResponseHeaderUtility_js_1.default.parseResponseHeaders({
browserFrame: this.#browserFrame,
requestURL: this.request[PropertySymbol.url],
rawHeaders: nodeResponse.rawHeaders
});
if (this.handleRedirectResponse(nodeResponse, this.responseHeaders)) {
return;
}
nodeResponse.once('end', () => this.request.signal.removeEventListener('abort', this.listeners.onSignalAbort));
let body = stream_1.default.pipeline(nodeResponse, new stream_1.default.PassThrough(), (error) => {
if (error) {
// Ignore error as it is forwarded to the response body.
}
});
const responseOptions = {
status: nodeResponse.statusCode,
statusText: nodeResponse.statusMessage,
headers: this.responseHeaders
};
const contentEncodingHeader = this.responseHeaders.get('Content-Encoding');
if (this.request.method === 'HEAD' ||
contentEncodingHeader === null ||
nodeResponse.statusCode === 204 ||
nodeResponse.statusCode === 304) {
this.response = new this.#window.Response(FetchBodyUtility_js_1.default.nodeToWebStream(body), responseOptions);
this.response.redirected = this.redirectCount > 0;
this.response.url = this.request.url;
this.resolve(this.response);
return;
}
// For GZip
if (contentEncodingHeader === 'gzip' || contentEncodingHeader === 'x-gzip') {
// Be less strict when decoding compressed responses.
// Sometimes servers send slightly invalid responses that are still accepted by common browsers.
// "cURL" always uses Z_SYNC_FLUSH.
const zlibOptions = {
flush: zlib_1.default.constants.Z_SYNC_FLUSH,
finishFlush: zlib_1.default.constants.Z_SYNC_FLUSH
};
body = stream_1.default.pipeline(body, zlib_1.default.createGunzip(zlibOptions), (error) => {
if (error) {
// Ignore error as it is forwarded to the response body.
}
});
this.response = new this.#window.Response(FetchBodyUtility_js_1.default.nodeToWebStream(body), responseOptions);
this.response.redirected = this.redirectCount > 0;
this.response.url = this.request.url;
this.resolve(this.response);
return;
}
// For Deflate
if (contentEncodingHeader === 'deflate' || contentEncodingHeader === 'x-deflate') {
// Handle the infamous raw deflate response from old servers
// A hack for old IIS and Apache servers
const raw = stream_1.default.pipeline(nodeResponse, new stream_1.default.PassThrough(), (error) => {
if (error) {
// Ignore error as it is forwarded to the response body.
}
});
raw.on('data', (chunk) => {
// See http://stackoverflow.com/questions/37519828
if ((chunk[0] & 0x0f) === 0x08) {
body = stream_1.default.pipeline(body, zlib_1.default.createInflate(), (error) => {
if (error) {
// Ignore error as the fetch() promise has already been resolved.
}
});
}
else {
body = stream_1.default.pipeline(body, zlib_1.default.createInflateRaw(), (error) => {
if (error) {
// Ignore error as it is forwarded to the response body.
}
});
}
this.response = new this.#window.Response(FetchBodyUtility_js_1.default.nodeToWebStream(body), responseOptions);
this.response.redirected = this.redirectCount > 0;
this.response.url = this.request.url;
this.resolve(this.response);
});
raw.on('end', () => {
// Some old IIS servers return zero-length OK deflate responses, so 'data' is never emitted.
if (!this.response) {
this.response = new this.#window.Response(FetchBodyUtility_js_1.default.nodeToWebStream(body), responseOptions);
this.response.redirected = this.redirectCount > 0;
this.response.url = this.request.url;
this.resolve(this.response);
}
});
return;
}
// For BR
if (contentEncodingHeader === 'br') {
body = stream_1.default.pipeline(body, zlib_1.default.createBrotliDecompress(), (error) => {
if (error) {
// Ignore error as it is forwarded to the response body.
}
});
this.response = new this.#window.Response(FetchBodyUtility_js_1.default.nodeToWebStream(body), responseOptions);
this.response.redirected = this.redirectCount > 0;
this.response.url = this.request.url;
this.resolve(this.response);
return;
}
// Otherwise, use response as is
this.response = new this.#window.Response(FetchBodyUtility_js_1.default.nodeToWebStream(body), responseOptions);
this.response.redirected = this.redirectCount > 0;
this.response.url = this.request.url;
this.resolve(this.response);
}
/**
* Handles redirect response.
*
* @param nodeResponse Node response.
* @param responseHeaders Headers.
* @returns True if redirect response was handled, false otherwise.
*/
handleRedirectResponse(nodeResponse, responseHeaders) {
if (!FetchResponseRedirectUtility_js_1.default.isRedirect(nodeResponse.statusCode)) {
return false;
}
switch (this.request.redirect) {
case 'error':
this.finalizeRequest();
this.reject(new this.#window.DOMException(`URI requested responds with a redirect, redirect mode is set to "error": ${this.request.url}`, DOMExceptionNameEnum_js_1.default.abortError));
return true;
case 'manual':
// Nothing to do
return false;
case 'follow':
const locationHeader = responseHeaders.get('Location');
const shouldBecomeGetRequest = nodeResponse.statusCode === 303 ||
((nodeResponse.statusCode === 301 || nodeResponse.statusCode === 302) &&
this.request.method === 'POST');
let locationURL = null;
if (locationHeader !== null) {
try {
locationURL = new url_1.URL(locationHeader, this.request.url);
}
catch {
this.finalizeRequest();
this.reject(new this.#window.DOMException(`URI requested responds with an invalid redirect URL: ${locationHeader}`, DOMExceptionNameEnum_js_1.default.uriMismatchError));
return true;
}
}
if (locationURL === null) {
return false;
}
if (FetchResponseRedirectUtility_js_1.default.isMaxRedirectsReached(this.redirectCount)) {
this.finalizeRequest();
this.reject(new this.#window.DOMException(`Maximum redirects reached at: ${this.request.url}`, DOMExceptionNameEnum_js_1.default.networkError));
return true;
}
const headers = new Headers_js_1.default(this.request.headers);
const requestInit = {
method: this.request.method,
signal: this.request.signal,
referrer: this.request.referrer,
referrerPolicy: this.request.referrerPolicy,
credentials: this.request.credentials,
headers,
body: this.request[PropertySymbol.bodyBuffer]
};
if (this.request.credentials === 'omit' ||
(this.request.credentials === 'same-origin' &&
FetchCORSUtility_js_1.default.isCORS(this.#window.location.href, locationURL))) {
headers.delete('authorization');
headers.delete('www-authenticate');
headers.delete('cookie');
headers.delete('cookie2');
}
if (this.request.signal[PropertySymbol.aborted]) {
this.abort(this.request.signal[PropertySymbol.reason]);
return true;
}
if (shouldBecomeGetRequest) {
requestInit.method = 'GET';
requestInit.body = undefined;
headers.delete('Content-Length');
headers.delete('Content-Type');
}
const responseReferrerPolicy = FetchRequestReferrerUtility_js_1.default.getReferrerPolicyFromHeader(headers);
if (responseReferrerPolicy) {
requestInit.referrerPolicy = responseReferrerPolicy;
}
const fetch = new Fetch({
browserFrame: this.#browserFrame,
window: this.#window,
url: locationURL,
init: requestInit,
redirectCount: this.redirectCount + 1,
contentType: !shouldBecomeGetRequest
? this.request[PropertySymbol.contentType]
: undefined
});
this.finalizeRequest();
fetch
.send()
.then((response) => this.resolve(response))
.catch((error) => this.reject(error));
return true;
default:
this.finalizeRequest();
this.reject(new this.#window.DOMException(`Redirect option '${this.request.redirect}' is not a valid value of IRequestRedirect`));
return true;
}
}
/**
* Finalizes the request.
*/
finalizeRequest() {
this.request.signal.removeEventListener('abort', this.listeners.onSignalAbort);
this.nodeRequest.destroy();
}
/**
* Aborts the request.
*
* @param reason Reason.
*/
abort(reason) {
const error = new this.#window.DOMException('The operation was aborted.' + (reason ? ' ' + reason.toString() : ''), DOMExceptionNameEnum_js_1.default.abortError);
this.request[PropertySymbol.aborted] = true;
if (this.request.body) {
this.request.body[PropertySymbol.error] = error;
}
if (this.nodeRequest && !this.nodeRequest.destroyed) {
this.nodeRequest.destroy(error);
}
if (this.nodeResponse && !this.nodeResponse.destroyed) {
this.nodeResponse.destroy(error);
}
if (this.response && this.response.body) {
this.response.body[PropertySymbol.error] = error;
if (!this.response.body.locked) {
this.response.body.cancel(error);
}
}
if (this.reject) {
this.reject(reason !== undefined ? reason : error);
}
}
}
exports.default = Fetch;
//# sourceMappingURL=Fetch.cjs.map

File diff suppressed because one or more lines are too long

137
frontend/node_modules/happy-dom/cjs/fetch/Fetch.d.ts generated vendored Normal file
View File

@@ -0,0 +1,137 @@
import IRequestInit from './types/IRequestInit.cjs';
import IRequestInfo from './types/IRequestInfo.cjs';
import Headers from './Headers.cjs';
import Response from './Response.cjs';
import IBrowserFrame from '../browser/types/IBrowserFrame.cjs';
import BrowserWindow from '../window/BrowserWindow.cjs';
/**
* Handles fetch requests.
*
* Based on:
* https://github.com/node-fetch/node-fetch/blob/main/src/index.js
*
* @see https://fetch.spec.whatwg.org/#http-network-fetch
*/
export default class Fetch {
#private;
private reject;
private resolve;
private listeners;
private isChunkedTransfer;
private isProperLastChunkReceived;
private previousChunk;
private nodeRequest;
private nodeResponse;
private response;
private responseHeaders;
private interceptor;
private request;
private redirectCount;
private disableCache;
private disableSameOriginPolicy;
private disablePreload;
/**
* Constructor.
*
* @param options Options.
* @param options.browserFrame Browser frame.
* @param options.window Window.
* @param options.url URL.
* @param [options.init] Init.
* @param [options.redirectCount] Redirect count.
* @param [options.contentType] Content Type.
* @param [options.disableCache] Disables the use of cached responses. It will still store the response in the cache.
* @param [options.disableSameOriginPolicy] Disables the Same-Origin policy.
* @param [options.unfilteredHeaders] Unfiltered headers - necessary for preflight requests.
* @param [options.disablePreload] Disables the use of preloaded responses.
*/
constructor(options: {
browserFrame: IBrowserFrame;
window: BrowserWindow;
url: IRequestInfo;
init?: IRequestInit;
redirectCount?: number;
contentType?: string;
disableCache?: boolean;
disableSameOriginPolicy?: boolean;
unfilteredHeaders?: Headers;
disablePreload?: boolean;
});
/**
* Sends request.
*
* @returns Response.
*/
send(): Promise<Response>;
/**
* Returns cached response.
*
* @returns Response.
*/
private getCachedResponse;
/**
* Returns virtual server response.
*
* @returns Response.
*/
private getVirtualServerResponse;
/**
* Checks if the request complies with the Cross-Origin policy.
*
* @returns True if it complies with the policy.
*/
private compliesWithCrossOriginPolicy;
/**
* Sends request.
*
* @returns Response.
*/
private sendRequest;
/**
* Event listener for "socket" event.
*
* @param socket Socket.
*/
private onSocket;
/**
* Event listener for signal "abort" event.
*
* @param event Event.
*/
private onSignalAbort;
/**
* Event listener for request "error" event.
*
* @param error Error.
*/
private onError;
/**
* Triggered when the async task manager aborts.
*/
private onAsyncTaskManagerAbort;
/**
* Event listener for request "response" event.
*
* @param nodeResponse Node response.
*/
private onResponse;
/**
* Handles redirect response.
*
* @param nodeResponse Node response.
* @param responseHeaders Headers.
* @returns True if redirect response was handled, false otherwise.
*/
private handleRedirectResponse;
/**
* Finalizes the request.
*/
private finalizeRequest;
/**
* Aborts the request.
*
* @param reason Reason.
*/
private abort;
}
//# sourceMappingURL=Fetch.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Fetch.d.ts","sourceRoot":"","sources":["../../src/fetch/Fetch.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,yBAAyB,CAAC;AAEnD,OAAO,YAAY,MAAM,yBAAyB,CAAC;AACnD,OAAO,OAAO,MAAM,cAAc,CAAC;AAcnC,OAAO,QAAQ,MAAM,eAAe,CAAC;AAGrC,OAAO,aAAa,MAAM,mCAAmC,CAAC;AAC9D,OAAO,aAAa,MAAM,4BAA4B,CAAC;AAevD;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,OAAO,KAAK;;IACzB,OAAO,CAAC,MAAM,CAA0C;IACxD,OAAO,CAAC,OAAO,CAAyE;IACxF,OAAO,CAAC,SAAS,CAEf;IACF,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,yBAAyB,CAAS;IAC1C,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,WAAW,CAAmC;IACtD,OAAO,CAAC,YAAY,CAAgC;IACpD,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,eAAe,CAAwB;IAC/C,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,YAAY,CAAU;IAC9B,OAAO,CAAC,uBAAuB,CAAU;IACzC,OAAO,CAAC,cAAc,CAAU;IAKhC;;;;;;;;;;;;;;OAcG;gBACS,OAAO,EAAE;QACpB,YAAY,EAAE,aAAa,CAAC;QAC5B,MAAM,EAAE,aAAa,CAAC;QACtB,GAAG,EAAE,YAAY,CAAC;QAClB,IAAI,CAAC,EAAE,YAAY,CAAC;QACpB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,uBAAuB,CAAC,EAAE,OAAO,CAAC;QAClC,iBAAiB,CAAC,EAAE,OAAO,CAAC;QAC5B,cAAc,CAAC,EAAE,OAAO,CAAC;KACzB;IAqBD;;;;OAIG;IACU,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC;IAkHtC;;;;OAIG;YACW,iBAAiB;IAiF/B;;;;OAIG;YACW,wBAAwB;IAsFtC;;;;OAIG;YACW,6BAA6B;IA8F3C;;;;OAIG;IACH,OAAO,CAAC,WAAW;IA6FnB;;;;OAIG;IACH,OAAO,CAAC,QAAQ;IAuChB;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAKrB;;;;OAIG;IACH,OAAO,CAAC,OAAO;IAWf;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAgC/B;;;;OAIG;IACH,OAAO,CAAC,UAAU;IAuJlB;;;;;;OAMG;IACH,OAAO,CAAC,sBAAsB;IA4H9B;;OAEG;IACH,OAAO,CAAC,eAAe;IAKvB;;;;OAIG;IACH,OAAO,CAAC,KAAK;CA+Bb"}

194
frontend/node_modules/happy-dom/cjs/fetch/Headers.cjs generated vendored Normal file
View File

@@ -0,0 +1,194 @@
"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 () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const DOMException_js_1 = __importDefault(require("../exception/DOMException.cjs"));
const PropertySymbol = __importStar(require("../PropertySymbol.cjs"));
const DOMExceptionNameEnum_js_1 = __importDefault(require("../exception/DOMExceptionNameEnum.cjs"));
/**
* Fetch headers.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/Headers
*/
class Headers {
[PropertySymbol.entries] = {};
/**
* Constructor.
*
* @param init Headers init.
*/
constructor(init) {
if (init) {
if (init instanceof Headers) {
this[PropertySymbol.entries] = JSON.parse(JSON.stringify(init[PropertySymbol.entries]));
}
else if (Array.isArray(init)) {
for (const entry of init) {
if (entry.length !== 2) {
throw new DOMException_js_1.default('Failed to construct "Headers": The provided init is not a valid array.', DOMExceptionNameEnum_js_1.default.invalidStateError);
}
this.append(entry[0], entry[1]);
}
}
else {
for (const name of Object.keys(init)) {
this.set(name, init[name]);
}
}
}
}
/**
* Appends a new value onto an existing header inside a Headers object, or adds the header if it does not already exist.
*
* @param name Name.
* @param value Value.
*/
append(name, value) {
const lowerName = name.toLowerCase();
if (this[PropertySymbol.entries][lowerName]) {
this[PropertySymbol.entries][lowerName].value.push(value);
}
else {
this[PropertySymbol.entries][lowerName] = {
name,
value: [value]
};
}
}
/**
* Removes an header.
*
* @param name Name.
*/
delete(name) {
delete this[PropertySymbol.entries][name.toLowerCase()];
}
/**
* Returns header value.
*
* @param name Name.
* @returns Value.
*/
get(name) {
return this[PropertySymbol.entries][name.toLowerCase()]?.value.join(', ') ?? null;
}
/**
* Sets a new value for an existing header inside a Headers object, or adds the header if it does not already exist.
*
* @param name Name.
* @param value Value.
*/
set(name, value) {
this[PropertySymbol.entries][name.toLowerCase()] = {
name,
value: [value]
};
}
/**
* Returns an array containing the values of all Set-Cookie headers associated with a response.
*
* @returns An array of strings representing the values of all the different Set-Cookie headers.
*/
getSetCookie() {
const entry = this[PropertySymbol.entries]['set-cookie'];
if (!entry) {
return [];
}
return entry.value;
}
/**
* Returns whether an Headers object contains a certain key.
*
* @param name Name.
* @returns "true" if the Headers object contains the key.
*/
has(name) {
return !!this[PropertySymbol.entries][name.toLowerCase()];
}
/**
* Executes a callback function once per each key/value pair in the Headers object.
*
* @param callback Callback.
*/
forEach(callback) {
for (const header of Object.values(this[PropertySymbol.entries])) {
callback(header.value.join(', '), header.name, this);
}
}
/**
* Returns an iterator, allowing you to go through all keys of the key/value pairs contained in this object.
*
* @returns Iterator.
*/
*keys() {
for (const header of Object.values(this[PropertySymbol.entries])) {
yield header.name;
}
}
/**
* Returns an iterator, allowing you to go through all values of the key/value pairs contained in this object.
*
* @returns Iterator.
*/
*values() {
for (const header of Object.values(this[PropertySymbol.entries])) {
yield header.value.join(', ');
}
}
/**
* Returns an iterator, allowing you to go through all key/value pairs contained in this object.
*
* @returns Iterator.
*/
*entries() {
for (const header of Object.values(this[PropertySymbol.entries])) {
yield [header.name, header.value.join(', ')];
}
}
/**
* Iterator.
*
* @returns Iterator.
*/
*[Symbol.iterator]() {
for (const header of Object.values(this[PropertySymbol.entries])) {
yield [header.name, header.value.join(', ')];
}
}
}
exports.default = Headers;
//# sourceMappingURL=Headers.cjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Headers.cjs","sourceRoot":"","sources":["../../src/fetch/Headers.ts"],"names":[],"mappings":"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"}

92
frontend/node_modules/happy-dom/cjs/fetch/Headers.d.ts generated vendored Normal file
View File

@@ -0,0 +1,92 @@
import * as PropertySymbol from '../PropertySymbol.cjs';
import IHeadersInit from './types/IHeadersInit.cjs';
/**
* Fetch headers.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/Headers
*/
export default class Headers {
[PropertySymbol.entries]: {
[k: string]: {
name: string;
value: string[];
};
};
/**
* Constructor.
*
* @param init Headers init.
*/
constructor(init?: IHeadersInit);
/**
* Appends a new value onto an existing header inside a Headers object, or adds the header if it does not already exist.
*
* @param name Name.
* @param value Value.
*/
append(name: string, value: string): void;
/**
* Removes an header.
*
* @param name Name.
*/
delete(name: string): void;
/**
* Returns header value.
*
* @param name Name.
* @returns Value.
*/
get(name: string): string | null;
/**
* Sets a new value for an existing header inside a Headers object, or adds the header if it does not already exist.
*
* @param name Name.
* @param value Value.
*/
set(name: string, value: string): void;
/**
* Returns an array containing the values of all Set-Cookie headers associated with a response.
*
* @returns An array of strings representing the values of all the different Set-Cookie headers.
*/
getSetCookie(): string[];
/**
* Returns whether an Headers object contains a certain key.
*
* @param name Name.
* @returns "true" if the Headers object contains the key.
*/
has(name: string): boolean;
/**
* Executes a callback function once per each key/value pair in the Headers object.
*
* @param callback Callback.
*/
forEach(callback: (name: string, value: string, thisArg: Headers) => void): void;
/**
* Returns an iterator, allowing you to go through all keys of the key/value pairs contained in this object.
*
* @returns Iterator.
*/
keys(): IterableIterator<string>;
/**
* Returns an iterator, allowing you to go through all values of the key/value pairs contained in this object.
*
* @returns Iterator.
*/
values(): IterableIterator<string>;
/**
* Returns an iterator, allowing you to go through all key/value pairs contained in this object.
*
* @returns Iterator.
*/
entries(): IterableIterator<[string, string]>;
/**
* Iterator.
*
* @returns Iterator.
*/
[Symbol.iterator](): IterableIterator<[string, string]>;
}
//# sourceMappingURL=Headers.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Headers.d.ts","sourceRoot":"","sources":["../../src/fetch/Headers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,cAAc,MAAM,sBAAsB,CAAC;AAEvD,OAAO,YAAY,MAAM,yBAAyB,CAAC;AAEnD;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,OAAO;IACpB,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE;QAAE,CAAC,CAAC,EAAE,MAAM,GAAG;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,EAAE,CAAA;SAAE,CAAA;KAAE,CAAM;IAEzF;;;;OAIG;gBACS,IAAI,CAAC,EAAE,YAAY;IAsB/B;;;;;OAKG;IACI,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAYhD;;;;OAIG;IACI,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIjC;;;;;OAKG;IACI,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAIvC;;;;;OAKG;IACI,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAO7C;;;;OAIG;IACI,YAAY,IAAI,MAAM,EAAE;IAQ/B;;;;;OAKG;IACI,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIjC;;;;OAIG;IACI,OAAO,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI;IAMvF;;;;OAIG;IACK,IAAI,IAAI,gBAAgB,CAAC,MAAM,CAAC;IAMxC;;;;OAIG;IACK,MAAM,IAAI,gBAAgB,CAAC,MAAM,CAAC;IAM1C;;;;OAIG;IACK,OAAO,IAAI,gBAAgB,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAMrD;;;;OAIG;IACK,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,gBAAgB,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAK/D"}

423
frontend/node_modules/happy-dom/cjs/fetch/Request.cjs generated vendored Normal file
View File

@@ -0,0 +1,423 @@
"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 () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const PropertySymbol = __importStar(require("../PropertySymbol.cjs"));
const url_1 = require("url");
const DOMExceptionNameEnum_js_1 = __importDefault(require("../exception/DOMExceptionNameEnum.cjs"));
const Headers_js_1 = __importDefault(require("./Headers.cjs"));
const FetchBodyUtility_js_1 = __importDefault(require("./utilities/FetchBodyUtility.cjs"));
const Blob_js_1 = __importDefault(require("../file/Blob.cjs"));
const FetchRequestValidationUtility_js_1 = __importDefault(require("./utilities/FetchRequestValidationUtility.cjs"));
const FetchRequestReferrerUtility_js_1 = __importDefault(require("./utilities/FetchRequestReferrerUtility.cjs"));
const FetchRequestHeaderUtility_js_1 = __importDefault(require("./utilities/FetchRequestHeaderUtility.cjs"));
const MultipartFormDataParser_js_1 = __importDefault(require("./multipart/MultipartFormDataParser.cjs"));
const WindowBrowserContext_js_1 = __importDefault(require("../window/WindowBrowserContext.cjs"));
/**
* Fetch request.
*
* Based on:
* https://github.com/node-fetch/node-fetch/blob/main/src/request.js
*
* @see https://fetch.spec.whatwg.org/#request-class
*/
class Request {
// Public properties
[PropertySymbol.method];
[PropertySymbol.body];
[PropertySymbol.mode] = 'cors';
[PropertySymbol.headers];
[PropertySymbol.redirect];
[PropertySymbol.referrerPolicy];
[PropertySymbol.signal];
[PropertySymbol.bodyUsed] = false;
[PropertySymbol.credentials];
// Internal properties
[PropertySymbol.aborted] = false;
[PropertySymbol.contentLength] = null;
[PropertySymbol.contentType] = null;
[PropertySymbol.referrer] = 'client';
[PropertySymbol.url];
[PropertySymbol.bodyBuffer];
/**
* Constructor.
*
* @param input Input.
* @param [init] Init.
*/
constructor(input, init) {
const window = this[PropertySymbol.window];
if (!window) {
throw new TypeError(`Failed to construct 'Request': 'Request' was constructed outside a Window context.`);
}
if (typeof input !== `string` && !input) {
throw new window.TypeError(`Failed to contruct 'Request': 1 argument required, only 0 present.`);
}
this[PropertySymbol.method] = (init?.method || input.method || 'GET').toUpperCase();
if (init?.mode) {
switch (init.mode) {
case 'navigate':
case 'websocket':
throw new window.DOMException(`Failed to construct 'Request': Cannot construct a Request with a RequestInit whose mode member is set as '${init.mode}'.`, DOMExceptionNameEnum_js_1.default.securityError);
case 'same-origin':
case 'no-cors':
case 'cors':
this[PropertySymbol.mode] = init.mode;
break;
default:
throw new window.DOMException(`Failed to construct 'Request': The provided value '${init.mode}' is not a valid enum value of type RequestMode.`, DOMExceptionNameEnum_js_1.default.syntaxError);
}
}
else if (input instanceof Request) {
this[PropertySymbol.mode] = input.mode;
}
const { stream, buffer, contentType, contentLength } = FetchBodyUtility_js_1.default.getBodyStream(input instanceof Request && (input[PropertySymbol.bodyBuffer] || input.body)
? input[PropertySymbol.bodyBuffer] || FetchBodyUtility_js_1.default.cloneBodyStream(window, input)
: init?.body);
this[PropertySymbol.bodyBuffer] = buffer;
this[PropertySymbol.body] = stream;
this[PropertySymbol.credentials] =
init?.credentials || input.credentials || 'same-origin';
this[PropertySymbol.headers] = new Headers_js_1.default(init?.headers || input.headers || {});
FetchRequestHeaderUtility_js_1.default.removeForbiddenHeaders(this.headers);
if (contentLength) {
this[PropertySymbol.contentLength] = contentLength;
}
else if (!this.body && (this.method === 'POST' || this.method === 'PUT')) {
this[PropertySymbol.contentLength] = 0;
}
if (contentType) {
if (!this.headers.has('Content-Type')) {
this.headers.set('Content-Type', contentType);
}
this[PropertySymbol.contentType] = contentType;
}
else if (input instanceof Request && input[PropertySymbol.contentType]) {
this[PropertySymbol.contentType] = input[PropertySymbol.contentType];
}
this[PropertySymbol.redirect] = init?.redirect || input.redirect || 'follow';
this[PropertySymbol.referrerPolicy] = ((init?.referrerPolicy || input.referrerPolicy || '').toLowerCase());
this[PropertySymbol.signal] =
init?.signal || input.signal || new window.AbortSignal();
this[PropertySymbol.referrer] = FetchRequestReferrerUtility_js_1.default.getInitialReferrer(window, init?.referrer !== null && init?.referrer !== undefined
? init?.referrer
: input.referrer);
if (input instanceof url_1.URL) {
this[PropertySymbol.url] = input;
}
else {
try {
if (input instanceof Request && input.url) {
this[PropertySymbol.url] = new url_1.URL(input.url, window.location.href);
}
else {
this[PropertySymbol.url] = new url_1.URL(input, window.location.href);
}
}
catch (error) {
throw new window.DOMException(`Failed to construct 'Request': Invalid URL "${input}" on document location '${window.location}'.${window.location.origin === 'null'
? ' Relative URLs are not permitted on current document location.'
: ''}`, DOMExceptionNameEnum_js_1.default.notSupportedError);
}
}
FetchRequestValidationUtility_js_1.default.validateMethod(this);
FetchRequestValidationUtility_js_1.default.validateBody(this);
FetchRequestValidationUtility_js_1.default.validateURL(this[PropertySymbol.url]);
FetchRequestValidationUtility_js_1.default.validateReferrerPolicy(this.referrerPolicy);
FetchRequestValidationUtility_js_1.default.validateRedirect(this.redirect);
}
/**
* Returns method.
*
* @returns Method.
*/
get method() {
return this[PropertySymbol.method];
}
/**
* Returns body.
*
* @returns Body.
*/
get body() {
return this[PropertySymbol.body];
}
/**
* Returns mode.
*
* @returns Mode.
*/
get mode() {
return this[PropertySymbol.mode];
}
/**
* Returns headers.
*
* @returns Headers.
*/
get headers() {
return this[PropertySymbol.headers];
}
/**
* Returns redirect.
*
* @returns Redirect.
*/
get redirect() {
return this[PropertySymbol.redirect];
}
/**
* Returns referrer policy.
*
* @returns Referrer policy.
*/
get referrerPolicy() {
return this[PropertySymbol.referrerPolicy];
}
/**
* Returns signal.
*
* @returns Signal.
*/
get signal() {
return this[PropertySymbol.signal];
}
/**
* Returns body used.
*
* @returns Body used.
*/
get bodyUsed() {
return this[PropertySymbol.bodyUsed];
}
/**
* Returns credentials.
*
* @returns Credentials.
*/
get credentials() {
return this[PropertySymbol.credentials];
}
/**
* Returns referrer.
*
* @returns Referrer.
*/
get referrer() {
if (!this[PropertySymbol.referrer] || this[PropertySymbol.referrer] === 'no-referrer') {
return '';
}
if (this[PropertySymbol.referrer] === 'client') {
return 'about:client';
}
return this[PropertySymbol.referrer].toString();
}
/**
* Returns URL.
*
* @returns URL.
*/
get url() {
return this[PropertySymbol.url].href;
}
/**
* Returns string tag.
*
* @returns String tag.
*/
get [Symbol.toStringTag]() {
return 'Request';
}
/**
* Returns array buffer.
*
* @returns Array buffer.
*/
async arrayBuffer() {
const window = this[PropertySymbol.window];
if (this[PropertySymbol.bodyUsed]) {
throw new window.DOMException(`Body has already been used for "${this.url}".`, DOMExceptionNameEnum_js_1.default.invalidStateError);
}
const asyncTaskManager = new WindowBrowserContext_js_1.default(window).getAsyncTaskManager();
this[PropertySymbol.bodyUsed] = true;
const taskID = asyncTaskManager.startTask(() => {
if (this.body) {
this.body[PropertySymbol.aborted] = true;
}
this.signal[PropertySymbol.abort]();
});
let buffer;
try {
buffer = await FetchBodyUtility_js_1.default.consumeBodyStream(window, this.body);
}
catch (error) {
asyncTaskManager.endTask(taskID);
throw error;
}
asyncTaskManager.endTask(taskID);
return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
}
/**
* Returns blob.
*
* @returns Blob.
*/
async blob() {
const type = this.headers.get('Content-Type') || '';
const buffer = await this.arrayBuffer();
return new Blob_js_1.default([buffer], { type });
}
/**
* Returns buffer.
*
* @returns Buffer.
*/
async buffer() {
const window = this[PropertySymbol.window];
if (this[PropertySymbol.bodyUsed]) {
throw new window.DOMException(`Body has already been used for "${this.url}".`, DOMExceptionNameEnum_js_1.default.invalidStateError);
}
const asyncTaskManager = new WindowBrowserContext_js_1.default(window).getAsyncTaskManager();
this[PropertySymbol.bodyUsed] = true;
const taskID = asyncTaskManager.startTask(() => {
if (this.body) {
this.body[PropertySymbol.aborted] = true;
}
this.signal[PropertySymbol.abort]();
});
let buffer;
try {
buffer = await FetchBodyUtility_js_1.default.consumeBodyStream(window, this.body);
}
catch (error) {
asyncTaskManager.endTask(taskID);
throw error;
}
asyncTaskManager.endTask(taskID);
return buffer;
}
/**
* Returns text.
*
* @returns Text.
*/
async text() {
const window = this[PropertySymbol.window];
if (this[PropertySymbol.bodyUsed]) {
throw new window.DOMException(`Body has already been used for "${this.url}".`, DOMExceptionNameEnum_js_1.default.invalidStateError);
}
const asyncTaskManager = new WindowBrowserContext_js_1.default(window).getAsyncTaskManager();
this[PropertySymbol.bodyUsed] = true;
const taskID = asyncTaskManager.startTask(() => {
if (this.body) {
this.body[PropertySymbol.aborted] = true;
}
this.signal[PropertySymbol.abort]();
});
let buffer;
try {
buffer = await FetchBodyUtility_js_1.default.consumeBodyStream(window, this.body);
}
catch (error) {
asyncTaskManager.endTask(taskID);
throw error;
}
asyncTaskManager.endTask(taskID);
return new TextDecoder().decode(buffer);
}
/**
* Returns json.
*
* @returns JSON.
*/
async json() {
const text = await this.text();
return JSON.parse(text);
}
/**
* Returns FormData.
*
* @returns FormData.
*/
async formData() {
const window = this[PropertySymbol.window];
const asyncTaskManager = new WindowBrowserContext_js_1.default(window).getAsyncTaskManager();
const contentType = this[PropertySymbol.contentType];
if (/multipart/i.test(contentType)) {
if (this[PropertySymbol.bodyUsed]) {
throw new window.DOMException(`Body has already been used for "${this.url}".`, DOMExceptionNameEnum_js_1.default.invalidStateError);
}
this[PropertySymbol.bodyUsed] = true;
const taskID = asyncTaskManager.startTask(() => {
if (this.body) {
this.body[PropertySymbol.aborted] = true;
}
this.signal[PropertySymbol.abort]();
});
let formData;
try {
const result = await MultipartFormDataParser_js_1.default.streamToFormData(window, this.body, contentType);
formData = result.formData;
}
catch (error) {
asyncTaskManager.endTask(taskID);
throw error;
}
asyncTaskManager.endTask(taskID);
return formData;
}
if (contentType?.startsWith('application/x-www-form-urlencoded')) {
const parameters = new URLSearchParams(await this.text());
const formData = new window.FormData();
for (const [key, value] of parameters) {
formData.append(key, value);
}
return formData;
}
throw new window.DOMException(`Failed to construct FormData object: The "content-type" header is neither "application/x-www-form-urlencoded" nor "multipart/form-data".`, DOMExceptionNameEnum_js_1.default.invalidStateError);
}
/**
* Clones request.
*
* @returns Clone.
*/
clone() {
return new this[PropertySymbol.window].Request(this);
}
}
exports.default = Request;
//# sourceMappingURL=Request.cjs.map

File diff suppressed because one or more lines are too long

162
frontend/node_modules/happy-dom/cjs/fetch/Request.d.ts generated vendored Normal file
View File

@@ -0,0 +1,162 @@
import * as PropertySymbol from '../PropertySymbol.cjs';
import IRequestInit from './types/IRequestInit.cjs';
import { URL } from 'url';
import IRequestInfo from './types/IRequestInfo.cjs';
import Headers from './Headers.cjs';
import AbortSignal from './AbortSignal.cjs';
import { ReadableStream } from 'stream/web';
import Blob from '../file/Blob.cjs';
import IRequestReferrerPolicy from './types/IRequestReferrerPolicy.cjs';
import IRequestRedirect from './types/IRequestRedirect.cjs';
import IRequestCredentials from './types/IRequestCredentials.cjs';
import FormData from '../form-data/FormData.cjs';
import BrowserWindow from '../window/BrowserWindow.cjs';
import IRequestMode from './types/IRequestMode.cjs';
/**
* Fetch request.
*
* Based on:
* https://github.com/node-fetch/node-fetch/blob/main/src/request.js
*
* @see https://fetch.spec.whatwg.org/#request-class
*/
export default class Request implements Request {
protected [PropertySymbol.window]: BrowserWindow;
[PropertySymbol.method]: string;
[PropertySymbol.body]: ReadableStream | null;
[PropertySymbol.mode]: IRequestMode;
[PropertySymbol.headers]: Headers;
[PropertySymbol.redirect]: IRequestRedirect;
[PropertySymbol.referrerPolicy]: IRequestReferrerPolicy;
[PropertySymbol.signal]: AbortSignal;
[PropertySymbol.bodyUsed]: boolean;
[PropertySymbol.credentials]: IRequestCredentials;
[PropertySymbol.aborted]: boolean;
[PropertySymbol.contentLength]: number | null;
[PropertySymbol.contentType]: string | null;
[PropertySymbol.referrer]: '' | 'no-referrer' | 'client' | URL;
[PropertySymbol.url]: URL;
[PropertySymbol.bodyBuffer]: Buffer | null;
/**
* Constructor.
*
* @param input Input.
* @param [init] Init.
*/
constructor(input: IRequestInfo, init?: IRequestInit);
/**
* Returns method.
*
* @returns Method.
*/
get method(): string;
/**
* Returns body.
*
* @returns Body.
*/
get body(): ReadableStream | null;
/**
* Returns mode.
*
* @returns Mode.
*/
get mode(): IRequestMode;
/**
* Returns headers.
*
* @returns Headers.
*/
get headers(): Headers;
/**
* Returns redirect.
*
* @returns Redirect.
*/
get redirect(): IRequestRedirect;
/**
* Returns referrer policy.
*
* @returns Referrer policy.
*/
get referrerPolicy(): IRequestReferrerPolicy;
/**
* Returns signal.
*
* @returns Signal.
*/
get signal(): AbortSignal;
/**
* Returns body used.
*
* @returns Body used.
*/
get bodyUsed(): boolean;
/**
* Returns credentials.
*
* @returns Credentials.
*/
get credentials(): IRequestCredentials;
/**
* Returns referrer.
*
* @returns Referrer.
*/
get referrer(): string;
/**
* Returns URL.
*
* @returns URL.
*/
get url(): string;
/**
* Returns string tag.
*
* @returns String tag.
*/
get [Symbol.toStringTag](): string;
/**
* Returns array buffer.
*
* @returns Array buffer.
*/
arrayBuffer(): Promise<ArrayBuffer>;
/**
* Returns blob.
*
* @returns Blob.
*/
blob(): Promise<Blob>;
/**
* Returns buffer.
*
* @returns Buffer.
*/
buffer(): Promise<Buffer>;
/**
* Returns text.
*
* @returns Text.
*/
text(): Promise<string>;
/**
* Returns json.
*
* @returns JSON.
*/
json(): Promise<string>;
/**
* Returns FormData.
*
* @returns FormData.
*/
formData(): Promise<FormData>;
/**
* Clones request.
*
* @returns Clone.
*/
clone(): Request;
}
//# sourceMappingURL=Request.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Request.d.ts","sourceRoot":"","sources":["../../src/fetch/Request.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,154 @@
"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 () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const URL_js_1 = __importDefault(require("../url/URL.cjs"));
const Fetch_js_1 = __importDefault(require("./Fetch.cjs"));
const SyncFetch_js_1 = __importDefault(require("./SyncFetch.cjs"));
const WindowBrowserContext_js_1 = __importDefault(require("../window/WindowBrowserContext.cjs"));
const PreloadUtility_js_1 = __importDefault(require("./preload/PreloadUtility.cjs"));
const PropertySymbol = __importStar(require("../PropertySymbol.cjs"));
/**
* Helper class for performing fetch of resources.
*/
class ResourceFetch {
window;
/**
* Constructor.
*
* @param window Window.
*/
constructor(window) {
this.window = window;
}
/**
* Returns resource data asynchronously.
*
* @param url URL.
* @param destination Destination.
* @param [options]
* @param [options.credentials] Credentials.
* @param options.referrerPolicy
* @returns Response.
*/
async fetch(url, destination, options) {
const browserFrame = new WindowBrowserContext_js_1.default(this.window).getBrowserFrame();
// Preloaded resource
if (destination === 'script' || destination === 'style') {
const preloadKey = PreloadUtility_js_1.default.getKey({
url: String(url),
destination,
mode: 'cors',
credentialsMode: options.credentials || 'same-origin'
});
const preloadEntry = this.window.document[PropertySymbol.preloads].get(preloadKey);
if (preloadEntry) {
this.window.document[PropertySymbol.preloads].delete(preloadKey);
const response = preloadEntry.response || (await preloadEntry.onResponseAvailable());
if (!response.ok) {
throw new this.window.DOMException(`Failed to perform request to "${new URL_js_1.default(url, this.window.location.href).href}". Status ${preloadEntry.response.status} ${preloadEntry.response.statusText}.`);
}
return preloadEntry.response[PropertySymbol.buffer].toString();
}
}
const fetch = new Fetch_js_1.default({
browserFrame,
window: this.window,
url,
disableSameOriginPolicy: destination === 'script' || destination === 'style',
disablePreload: true,
init: {
credentials: options?.credentials,
referrerPolicy: options?.referrerPolicy
}
});
const response = await fetch.send();
if (!response.ok) {
throw new this.window.DOMException(`Failed to perform request to "${new URL_js_1.default(url, this.window.location.href).href}". Status ${response.status} ${response.statusText}.`);
}
return await response.text();
}
/**
* Returns resource data synchronously.
*
* @param url URL.
* @param destination Destination.
* @param [options] Options.
* @param [options.credentials] Credentials.
* @param [options.referrerPolicy] Referrer policy.
* @returns Response.
*/
fetchSync(url, destination, options) {
const browserFrame = new WindowBrowserContext_js_1.default(this.window).getBrowserFrame();
// Preloaded resource
if (destination === 'script' || destination === 'style') {
const preloadKey = PreloadUtility_js_1.default.getKey({
url: String(url),
destination,
mode: 'cors',
credentialsMode: options.credentials || 'same-origin'
});
const preloadEntry = this.window.document[PropertySymbol.preloads].get(preloadKey);
// We will only use this if the fetch for the resource is complete as it is async and this request is sync.
if (preloadEntry && preloadEntry.response) {
this.window.document[PropertySymbol.preloads].delete(preloadKey);
const response = preloadEntry.response;
if (!response.ok) {
throw new this.window.DOMException(`Failed to perform request to "${new URL_js_1.default(url, this.window.location.href).href}". Status ${preloadEntry.response.status} ${preloadEntry.response.statusText}.`);
}
return preloadEntry.response[PropertySymbol.buffer].toString();
}
}
const fetch = new SyncFetch_js_1.default({
browserFrame,
window: this.window,
url,
disableSameOriginPolicy: true,
init: {
credentials: options?.credentials,
referrerPolicy: options?.referrerPolicy
}
});
const response = fetch.send();
if (!response.ok) {
throw new this.window.DOMException(`Failed to perform request to "${new URL_js_1.default(url, this.window.location.href).href}". Status ${response.status} ${response.statusText}.`);
}
return response.body.toString();
}
}
exports.default = ResourceFetch;
//# sourceMappingURL=ResourceFetch.cjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ResourceFetch.cjs","sourceRoot":"","sources":["../../src/fetch/ResourceFetch.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,45 @@
import BrowserWindow from '../window/BrowserWindow.cjs';
import URL from '../url/URL.cjs';
import IRequestCredentials from './types/IRequestCredentials.cjs';
import IRequestReferrerPolicy from './types/IRequestReferrerPolicy.cjs';
/**
* Helper class for performing fetch of resources.
*/
export default class ResourceFetch {
private window;
/**
* Constructor.
*
* @param window Window.
*/
constructor(window: BrowserWindow);
/**
* Returns resource data asynchronously.
*
* @param url URL.
* @param destination Destination.
* @param [options]
* @param [options.credentials] Credentials.
* @param options.referrerPolicy
* @returns Response.
*/
fetch(url: string | URL, destination: 'script' | 'style' | 'module', options?: {
credentials?: IRequestCredentials;
referrerPolicy?: IRequestReferrerPolicy;
}): Promise<string>;
/**
* Returns resource data synchronously.
*
* @param url URL.
* @param destination Destination.
* @param [options] Options.
* @param [options.credentials] Credentials.
* @param [options.referrerPolicy] Referrer policy.
* @returns Response.
*/
fetchSync(url: string, destination: 'script' | 'style' | 'module', options?: {
credentials?: IRequestCredentials;
referrerPolicy?: IRequestReferrerPolicy;
}): string;
}
//# sourceMappingURL=ResourceFetch.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ResourceFetch.d.ts","sourceRoot":"","sources":["../../src/fetch/ResourceFetch.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,4BAA4B,CAAC;AACvD,OAAO,GAAG,MAAM,eAAe,CAAC;AAGhC,OAAO,mBAAmB,MAAM,gCAAgC,CAAC;AAIjE,OAAO,sBAAsB,MAAM,mCAAmC,CAAC;AAEvE;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,aAAa;IACjC,OAAO,CAAC,MAAM,CAAgB;IAE9B;;;;OAIG;gBACS,MAAM,EAAE,aAAa;IAIjC;;;;;;;;;OASG;IACU,KAAK,CACjB,GAAG,EAAE,MAAM,GAAG,GAAG,EACjB,WAAW,EAAE,QAAQ,GAAG,OAAO,GAAG,QAAQ,EAC1C,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,mBAAmB,CAAC;QAAC,cAAc,CAAC,EAAE,sBAAsB,CAAA;KAAE,GACtF,OAAO,CAAC,MAAM,CAAC;IAuDlB;;;;;;;;;OASG;IACI,SAAS,CACf,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,QAAQ,GAAG,OAAO,GAAG,QAAQ,EAC1C,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,mBAAmB,CAAC;QAAC,cAAc,CAAC,EAAE,sBAAsB,CAAA;KAAE,GACtF,MAAM;CAsDT"}

372
frontend/node_modules/happy-dom/cjs/fetch/Response.cjs generated vendored Normal file
View File

@@ -0,0 +1,372 @@
"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 () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const PropertySymbol = __importStar(require("../PropertySymbol.cjs"));
const Blob_js_1 = __importDefault(require("../file/Blob.cjs"));
const Headers_js_1 = __importDefault(require("./Headers.cjs"));
const url_1 = require("url");
const URL_js_1 = __importDefault(require("../url/URL.cjs"));
const FetchBodyUtility_js_1 = __importDefault(require("./utilities/FetchBodyUtility.cjs"));
const DOMExceptionNameEnum_js_1 = __importDefault(require("../exception/DOMExceptionNameEnum.cjs"));
const MultipartFormDataParser_js_1 = __importDefault(require("./multipart/MultipartFormDataParser.cjs"));
const buffer_1 = require("buffer");
const WindowBrowserContext_js_1 = __importDefault(require("../window/WindowBrowserContext.cjs"));
const REDIRECT_STATUS_CODES = [301, 302, 303, 307, 308];
/**
* Fetch response.
*
* Based on:
* https://github.com/node-fetch/node-fetch/blob/main/src/response.js (MIT)
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/Response/Response
*/
class Response {
// Public properties
body = null;
bodyUsed = false;
redirected = false;
type = 'basic';
url = '';
status;
statusText;
ok;
headers;
[PropertySymbol.cachedResponse] = null;
[PropertySymbol.buffer] = null;
/**
* Constructor.
*
* @param body Body.
* @param [init] Init.
*/
constructor(body, init) {
if (!this[PropertySymbol.window]) {
throw new TypeError(`Failed to construct '${this.constructor.name}': '${this.constructor.name}' was constructed outside a Window context.`);
}
this.status = init?.status !== undefined ? init.status : 200;
this.statusText = init?.statusText || '';
this.ok = this.status >= 200 && this.status < 300;
this.headers = new Headers_js_1.default(init?.headers);
// "Set-Cookie" and "Set-Cookie2" are not allowed in response headers according to spec.
this.headers.delete('Set-Cookie');
this.headers.delete('Set-Cookie2');
if (body) {
const { stream, buffer, contentType } = FetchBodyUtility_js_1.default.getBodyStream(body);
this.body = stream;
if (buffer) {
this[PropertySymbol.buffer] = buffer;
}
if (contentType && !this.headers.has('Content-Type')) {
this.headers.set('Content-Type', contentType);
}
}
}
/**
* Returns string tag.
*
* @returns String tag.
*/
get [Symbol.toStringTag]() {
return 'Response';
}
/**
* Returns array buffer.
*
* @returns Array buffer.
*/
async arrayBuffer() {
const window = this[PropertySymbol.window];
if (this.bodyUsed) {
throw new window.DOMException(`Body has already been used for "${this.url}".`, DOMExceptionNameEnum_js_1.default.invalidStateError);
}
const browserFrame = new WindowBrowserContext_js_1.default(window).getBrowserFrame();
// No browser frame means that the browser is being teared down.
if (!browserFrame) {
return new ArrayBuffer(0);
}
const asyncTaskManager = browserFrame[PropertySymbol.asyncTaskManager];
this.bodyUsed = true;
let buffer = this[PropertySymbol.buffer];
if (!buffer) {
const taskID = asyncTaskManager.startTask(() => {
if (this.body) {
this.body[PropertySymbol.aborted] = true;
}
});
try {
buffer = await FetchBodyUtility_js_1.default.consumeBodyStream(window, this.body);
}
catch (error) {
asyncTaskManager.endTask(taskID);
throw error;
}
asyncTaskManager.endTask(taskID);
}
this.#storeBodyInCache(buffer);
return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
}
/**
* Returns blob.
*
* @returns Blob.
*/
async blob() {
const type = this.headers.get('Content-Type') || '';
const buffer = await this.arrayBuffer();
return new Blob_js_1.default([buffer], { type });
}
/**
* Returns buffer.
*
* @returns Buffer.
*/
async buffer() {
const window = this[PropertySymbol.window];
if (this.bodyUsed) {
throw new window.DOMException(`Body has already been used for "${this.url}".`, DOMExceptionNameEnum_js_1.default.invalidStateError);
}
const browserFrame = new WindowBrowserContext_js_1.default(window).getBrowserFrame();
// No browser frame means that the browser is being teared down.
if (!browserFrame) {
return buffer_1.Buffer.alloc(0);
}
const asyncTaskManager = browserFrame[PropertySymbol.asyncTaskManager];
this.bodyUsed = true;
let buffer = this[PropertySymbol.buffer];
if (!buffer) {
const taskID = asyncTaskManager.startTask(() => {
if (this.body) {
this.body[PropertySymbol.aborted] = true;
}
});
try {
buffer = await FetchBodyUtility_js_1.default.consumeBodyStream(window, this.body);
}
catch (error) {
asyncTaskManager.endTask(taskID);
throw error;
}
asyncTaskManager.endTask(taskID);
}
this.#storeBodyInCache(buffer);
return buffer;
}
/**
* Returns text.
*
* @returns Text.
*/
async text() {
const window = this[PropertySymbol.window];
if (this.bodyUsed) {
throw new window.DOMException(`Body has already been used for "${this.url}".`, DOMExceptionNameEnum_js_1.default.invalidStateError);
}
const browserFrame = new WindowBrowserContext_js_1.default(window).getBrowserFrame();
// No browser frame means that the browser is being teared down.
if (!browserFrame) {
return '';
}
const asyncTaskManager = browserFrame[PropertySymbol.asyncTaskManager];
this.bodyUsed = true;
let buffer = this[PropertySymbol.buffer];
if (!buffer) {
const taskID = asyncTaskManager.startTask(() => {
if (this.body) {
this.body[PropertySymbol.aborted] = true;
}
});
try {
buffer = await FetchBodyUtility_js_1.default.consumeBodyStream(window, this.body);
}
catch (error) {
asyncTaskManager.endTask(taskID);
throw error;
}
asyncTaskManager.endTask(taskID);
}
this.#storeBodyInCache(buffer);
return new TextDecoder().decode(buffer);
}
/**
* Returns json.
*
* @returns JSON.
*/
async json() {
const text = await this.text();
return JSON.parse(text);
}
/**
* Returns form data.
*
* @returns Form data.
*/
async formData() {
const window = this[PropertySymbol.window];
const browserFrame = new WindowBrowserContext_js_1.default(window).getBrowserFrame();
// No browser frame means that the browser is being teared down.
if (!browserFrame) {
return new window.FormData();
}
const asyncTaskManager = browserFrame[PropertySymbol.asyncTaskManager];
const contentType = this.headers.get('Content-Type');
if (/multipart/i.test(contentType)) {
if (this.bodyUsed) {
throw new window.DOMException(`Body has already been used for "${this.url}".`, DOMExceptionNameEnum_js_1.default.invalidStateError);
}
this.bodyUsed = true;
const taskID = browserFrame[PropertySymbol.asyncTaskManager].startTask(() => {
if (this.body) {
this.body[PropertySymbol.aborted] = true;
}
});
let formData;
let buffer;
try {
const result = await MultipartFormDataParser_js_1.default.streamToFormData(window, this.body, contentType);
formData = result.formData;
buffer = result.buffer;
}
catch (error) {
asyncTaskManager.endTask(taskID);
throw error;
}
this.#storeBodyInCache(buffer);
asyncTaskManager.endTask(taskID);
return formData;
}
if (contentType?.startsWith('application/x-www-form-urlencoded')) {
const parameters = new url_1.URLSearchParams(await this.text());
const formData = new window.FormData();
for (const [key, value] of parameters) {
formData.append(key, value);
}
return formData;
}
throw new window.DOMException(`Failed to build FormData object: The "content-type" header is neither "application/x-www-form-urlencoded" nor "multipart/form-data".`, DOMExceptionNameEnum_js_1.default.invalidStateError);
}
/**
* Clones request.
*
* @returns Clone.
*/
clone() {
const window = this[PropertySymbol.window];
const body = FetchBodyUtility_js_1.default.cloneBodyStream(window, this);
const response = new window.Response(body, {
status: this.status,
statusText: this.statusText,
headers: this.headers
});
response[PropertySymbol.cachedResponse] = this[PropertySymbol.cachedResponse];
response[PropertySymbol.buffer] = this[PropertySymbol.buffer];
response.ok = this.ok;
response.redirected = this.redirected;
response.type = this.type;
response.url = this.url;
return response;
}
/**
* Stores body in cache.
*
* @param buffer Buffer.
*/
#storeBodyInCache(buffer) {
if (this[PropertySymbol.cachedResponse]?.response?.waitingForBody) {
this[PropertySymbol.cachedResponse].response.body = buffer;
this[PropertySymbol.cachedResponse].response.waitingForBody = false;
}
}
/**
* Returns a redirect response.
*
* @param url URL.
* @param status Status code.
* @returns Response.
*/
static redirect(url, status = 302) {
const window = this[PropertySymbol.window];
if (!REDIRECT_STATUS_CODES.includes(status)) {
throw new window.DOMException('Failed to create redirect response: Invalid redirect status code.', DOMExceptionNameEnum_js_1.default.invalidStateError);
}
return new window.Response(null, {
headers: {
location: new URL_js_1.default(url).toString()
},
status
});
}
/**
* Returns an error response.
*
* @param url URL.
* @param status Status code.
* @returns Response.
*/
static error() {
const response = new this[PropertySymbol.window].Response(null, { status: 0, statusText: '' });
response.type = 'error';
return response;
}
/**
* Returns an JSON response.
*
* @param injected Injected properties.
* @param data Data.
* @param [init] Init.
* @returns Response.
*/
static json(data, init) {
const window = this[PropertySymbol.window];
const body = JSON.stringify(data);
if (body === undefined) {
throw new window.TypeError('data is not JSON serializable');
}
const headers = new window.Headers(init && init.headers);
if (!headers.has('Content-Type')) {
headers.set('Content-Type', 'application/json');
}
return new window.Response(body, {
status: 200,
...init,
headers
});
}
}
exports.default = Response;
//# sourceMappingURL=Response.cjs.map

File diff suppressed because one or more lines are too long

115
frontend/node_modules/happy-dom/cjs/fetch/Response.d.ts generated vendored Normal file
View File

@@ -0,0 +1,115 @@
import * as PropertySymbol from '../PropertySymbol.cjs';
import Blob from '../file/Blob.cjs';
import IResponseInit from './types/IResponseInit.cjs';
import IResponseBody from './types/IResponseBody.cjs';
import Headers from './Headers.cjs';
import { ReadableStream } from 'stream/web';
import FormData from '../form-data/FormData.cjs';
import BrowserWindow from '../window/BrowserWindow.cjs';
import ICachedResponse from './cache/response/ICachedResponse.cjs';
import { Buffer } from 'buffer';
/**
* Fetch response.
*
* Based on:
* https://github.com/node-fetch/node-fetch/blob/main/src/response.js (MIT)
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/Response/Response
*/
export default class Response implements Response {
#private;
protected static [PropertySymbol.window]: BrowserWindow;
protected [PropertySymbol.window]: BrowserWindow;
readonly body: ReadableStream | null;
readonly bodyUsed = false;
readonly redirected = false;
readonly type: 'basic' | 'cors' | 'default' | 'error' | 'opaque' | 'opaqueredirect';
readonly url: string;
readonly status: number;
readonly statusText: string;
readonly ok: boolean;
readonly headers: Headers;
[PropertySymbol.cachedResponse]: ICachedResponse | null;
[PropertySymbol.buffer]: Buffer | null;
/**
* Constructor.
*
* @param body Body.
* @param [init] Init.
*/
constructor(body?: IResponseBody, init?: IResponseInit);
/**
* Returns string tag.
*
* @returns String tag.
*/
get [Symbol.toStringTag](): string;
/**
* Returns array buffer.
*
* @returns Array buffer.
*/
arrayBuffer(): Promise<ArrayBuffer>;
/**
* Returns blob.
*
* @returns Blob.
*/
blob(): Promise<Blob>;
/**
* Returns buffer.
*
* @returns Buffer.
*/
buffer(): Promise<Buffer>;
/**
* Returns text.
*
* @returns Text.
*/
text(): Promise<string>;
/**
* Returns json.
*
* @returns JSON.
*/
json(): Promise<string>;
/**
* Returns form data.
*
* @returns Form data.
*/
formData(): Promise<FormData>;
/**
* Clones request.
*
* @returns Clone.
*/
clone(): Response;
/**
* Returns a redirect response.
*
* @param url URL.
* @param status Status code.
* @returns Response.
*/
static redirect(url: string, status?: number): Response;
/**
* Returns an error response.
*
* @param url URL.
* @param status Status code.
* @returns Response.
*/
static error(): Response;
/**
* Returns an JSON response.
*
* @param injected Injected properties.
* @param data Data.
* @param [init] Init.
* @returns Response.
*/
static json(data: object, init?: IResponseInit): Response;
}
//# sourceMappingURL=Response.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Response.d.ts","sourceRoot":"","sources":["../../src/fetch/Response.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,cAAc,MAAM,sBAAsB,CAAC;AACvD,OAAO,IAAI,MAAM,iBAAiB,CAAC;AACnC,OAAO,aAAa,MAAM,0BAA0B,CAAC;AACrD,OAAO,aAAa,MAAM,0BAA0B,CAAC;AACrD,OAAO,OAAO,MAAM,cAAc,CAAC;AAGnC,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,QAAQ,MAAM,0BAA0B,CAAC;AAIhD,OAAO,aAAa,MAAM,4BAA4B,CAAC;AACvD,OAAO,eAAe,MAAM,qCAAqC,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAKhC;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,OAAO,QAAS,YAAW,QAAQ;;IAEhD,iBAAyB,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAChE,UAAkB,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAGzD,SAAgB,IAAI,EAAE,cAAc,GAAG,IAAI,CAAQ;IACnD,SAAgB,QAAQ,SAAS;IACjC,SAAgB,UAAU,SAAS;IACnC,SAAgB,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,gBAAgB,CACjF;IACT,SAAgB,GAAG,EAAE,MAAM,CAAM;IACjC,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,SAAgB,UAAU,EAAE,MAAM,CAAC;IACnC,SAAgB,EAAE,EAAE,OAAO,CAAC;IAC5B,SAAgB,OAAO,EAAE,OAAO,CAAC;IAC1B,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,eAAe,GAAG,IAAI,CAAQ;IAC/D,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAQ;IAErD;;;;;OAKG;gBACS,IAAI,CAAC,EAAE,aAAa,EAAE,IAAI,CAAC,EAAE,aAAa;IA8BtD;;;;OAIG;IACH,IAAW,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,MAAM,CAExC;IAED;;;;OAIG;IACU,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC;IA6ChD;;;;OAIG;IACU,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAOlC;;;;OAIG;IACU,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IA2CtC;;;;OAIG;IACU,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IA2CpC;;;;OAIG;IACU,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IAKpC;;;;OAIG;IACU,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC;IAkE1C;;;;OAIG;IACI,KAAK,IAAI,QAAQ;IAgCxB;;;;;;OAMG;WACW,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,SAAM,GAAG,QAAQ;IAkB3D;;;;;;OAMG;WACW,KAAK,IAAI,QAAQ;IAM/B;;;;;;;OAOG;WACW,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,QAAQ;CAoBhE"}

573
frontend/node_modules/happy-dom/cjs/fetch/SyncFetch.cjs generated vendored Normal file
View File

@@ -0,0 +1,573 @@
"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 () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const PropertySymbol = __importStar(require("../PropertySymbol.cjs"));
const DOMExceptionNameEnum_js_1 = __importDefault(require("../exception/DOMExceptionNameEnum.cjs"));
const URL_js_1 = __importDefault(require("../url/URL.cjs"));
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const child_process_1 = __importDefault(require("child_process"));
const Headers_js_1 = __importDefault(require("./Headers.cjs"));
const CachedResponseStateEnum_js_1 = __importDefault(require("./cache/response/CachedResponseStateEnum.cjs"));
const FetchRequestReferrerUtility_js_1 = __importDefault(require("./utilities/FetchRequestReferrerUtility.cjs"));
const FetchRequestValidationUtility_js_1 = __importDefault(require("./utilities/FetchRequestValidationUtility.cjs"));
const DataURIParser_js_1 = __importDefault(require("./data-uri/DataURIParser.cjs"));
const SyncFetchScriptBuilder_js_1 = __importDefault(require("./utilities/SyncFetchScriptBuilder.cjs"));
const FetchRequestHeaderUtility_js_1 = __importDefault(require("./utilities/FetchRequestHeaderUtility.cjs"));
const FetchResponseHeaderUtility_js_1 = __importDefault(require("./utilities/FetchResponseHeaderUtility.cjs"));
const zlib_1 = __importDefault(require("zlib"));
const FetchResponseRedirectUtility_js_1 = __importDefault(require("./utilities/FetchResponseRedirectUtility.cjs"));
const FetchCORSUtility_js_1 = __importDefault(require("./utilities/FetchCORSUtility.cjs"));
const Fetch_js_1 = __importDefault(require("./Fetch.cjs"));
const VirtualServerUtility_js_1 = __importDefault(require("./utilities/VirtualServerUtility.cjs"));
/**
* Handles synchronous fetch requests.
*/
class SyncFetch {
request;
redirectCount = 0;
disableCache;
disableSameOriginPolicy;
interceptor;
#browserFrame;
#window;
#unfilteredHeaders = null;
/**
* Constructor.
*
* @param options Options.
* @param options.browserFrame Browser frame.
* @param options.window Window.
* @param options.url URL.
* @param [options.init] Init.
* @param [options.redirectCount] Redirect count.
* @param [options.contentType] Content Type.
* @param [options.disableCache] Disables the use of cached responses. It will still store the response in the cache.
* @param [options.disableSameOriginPolicy] Disables the Same-Origin policy.
* @param [options.unfilteredHeaders] Unfiltered headers - necessary for preflight requests.
*/
constructor(options) {
this.#browserFrame = options.browserFrame;
this.#window = options.window;
this.#unfilteredHeaders = options.unfilteredHeaders ?? null;
this.request =
typeof options.url === 'string' || options.url instanceof URL_js_1.default
? new options.window.Request(options.url, options.init)
: options.url;
if (options.contentType) {
this.request[PropertySymbol.contentType] = options.contentType;
}
this.redirectCount = options.redirectCount ?? 0;
this.disableCache = options.disableCache ?? false;
this.disableSameOriginPolicy =
options.disableSameOriginPolicy ??
this.#browserFrame.page.context.browser.settings.fetch.disableSameOriginPolicy ??
false;
this.interceptor = this.#browserFrame.page.context.browser.settings.fetch.interceptor;
}
/**
* Sends request.
*
* @returns Response.
*/
send() {
FetchRequestReferrerUtility_js_1.default.prepareRequest(new URL_js_1.default(this.#window.location.href), this.request);
const beforeRequestResponse = this.interceptor?.beforeSyncRequest
? this.interceptor.beforeSyncRequest({
request: this.request,
window: this.#window
})
: undefined;
if (typeof beforeRequestResponse === 'object') {
return beforeRequestResponse;
}
FetchRequestValidationUtility_js_1.default.validateSchema(this.request);
if (this.request.signal[PropertySymbol.aborted]) {
if (this.request.signal[PropertySymbol.reason] !== undefined) {
throw this.request.signal[PropertySymbol.reason];
}
throw new this[PropertySymbol.window].DOMException('signal is aborted without reason', DOMExceptionNameEnum_js_1.default.abortError);
}
if (this.request[PropertySymbol.url].protocol === 'data:') {
const result = DataURIParser_js_1.default.parse(this.request.url);
const response = {
status: 200,
statusText: 'OK',
ok: true,
url: this.request.url,
redirected: false,
headers: new Headers_js_1.default({ 'Content-Type': result.type }),
body: result.buffer
};
const interceptedResponse = this.interceptor?.afterSyncResponse
? this.interceptor.afterSyncResponse({
window: this.#window,
response,
request: this.request
})
: undefined;
return typeof interceptedResponse === 'object' ? interceptedResponse : response;
}
// Security check for "https" to "http" requests.
if (this.request[PropertySymbol.url].protocol === 'http:' &&
this.#window.location.protocol === 'https:') {
throw new this.#window.DOMException(`Mixed Content: The page at '${this.#window.location.href}' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint '${this.request.url}'. This request has been blocked; the content must be served over HTTPS.`, DOMExceptionNameEnum_js_1.default.securityError);
}
const cachedResponse = this.getCachedResponse();
if (cachedResponse) {
return cachedResponse;
}
const virtualServerResponse = this.getVirtualServerResponse();
if (virtualServerResponse) {
return virtualServerResponse;
}
if (!this.compliesWithCrossOriginPolicy()) {
this.#window.console.warn(`Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at "${this.request.url}".`);
throw new this.#window.DOMException(`Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at "${this.request.url}".`, DOMExceptionNameEnum_js_1.default.networkError);
}
return this.sendRequest();
}
/**
* Returns cached response.
*
* @returns Response.
*/
getCachedResponse() {
if (this.disableCache) {
return null;
}
let cachedResponse = this.#browserFrame.page.context.responseCache.get(this.request);
if (!cachedResponse || cachedResponse.response.waitingForBody) {
return null;
}
if (cachedResponse.state === CachedResponseStateEnum_js_1.default.stale) {
const headers = new Headers_js_1.default(cachedResponse.request.headers);
if (cachedResponse.etag) {
headers.set('If-None-Match', cachedResponse.etag);
}
else {
if (!cachedResponse.lastModified) {
return null;
}
headers.set('If-Modified-Since', new Date(cachedResponse.lastModified).toUTCString());
}
if (cachedResponse.etag || !cachedResponse.staleWhileRevalidate) {
const fetch = new SyncFetch({
browserFrame: this.#browserFrame,
window: this.#window,
url: this.request.url,
init: { headers, method: cachedResponse.request.method },
disableCache: true,
disableSameOriginPolicy: true
});
const validateResponse = fetch.send();
const body = validateResponse.status !== 304 ? validateResponse.body : null;
cachedResponse = this.#browserFrame.page.context.responseCache.add(this.request, {
...validateResponse,
body,
waitingForBody: false
});
if (validateResponse.status !== 304) {
return validateResponse;
}
}
else {
const fetch = new Fetch_js_1.default({
browserFrame: this.#browserFrame,
window: this.#window,
url: this.request.url,
init: { headers, method: cachedResponse.request.method },
disableCache: true,
disableSameOriginPolicy: true
});
fetch.send().then((response) => {
response.buffer().then((body) => {
this.#browserFrame.page.context.responseCache.add(this.request, {
...response,
body,
waitingForBody: false
});
});
});
}
}
if (!cachedResponse || cachedResponse.response.waitingForBody) {
return null;
}
return {
status: cachedResponse.response.status,
statusText: cachedResponse.response.statusText,
ok: true,
url: cachedResponse.response.url,
// TODO: Do we need to add support for redirected responses to the cache?
redirected: false,
headers: cachedResponse.response.headers,
body: cachedResponse.response.body
};
}
/**
* Returns virtual server response.
*
* @returns Response.
*/
getVirtualServerResponse() {
const filePath = VirtualServerUtility_js_1.default.getFilepath(this.#window, this.request.url);
if (!filePath) {
return null;
}
if (this.request.method !== 'GET') {
this.#browserFrame?.page?.console.error(`${this.request.method} ${this.request.url} 404 (Not Found)`);
const response = VirtualServerUtility_js_1.default.getNotFoundSyncResponse(this.#window);
const interceptedResponse = this.interceptor?.afterSyncResponse
? this.interceptor.afterSyncResponse({
window: this.#window,
response,
request: this.request
})
: undefined;
return typeof interceptedResponse === 'object' ? interceptedResponse : response;
}
let buffer;
try {
const stat = fs_1.default.statSync(filePath);
buffer = fs_1.default.readFileSync(stat.isDirectory() ? path_1.default.join(filePath, 'index.html') : filePath);
}
catch {
this.#browserFrame?.page?.console.error(`${this.request.method} ${this.request.url} 404 (Not Found)`);
const response = VirtualServerUtility_js_1.default.getNotFoundSyncResponse(this.#window);
const interceptedResponse = this.interceptor?.afterSyncResponse
? this.interceptor.afterSyncResponse({
window: this.#window,
response,
request: this.request
})
: undefined;
return typeof interceptedResponse === 'object' ? interceptedResponse : response;
}
const response = {
status: 200,
statusText: '',
ok: true,
url: this.request.url,
redirected: false,
headers: new this.#window.Headers(),
body: buffer
};
const interceptedResponse = this.interceptor?.afterSyncResponse
? this.interceptor.afterSyncResponse({
window: this.#window,
response,
request: this.request
})
: undefined;
const returnResponse = typeof interceptedResponse === 'object' ? interceptedResponse : response;
this.#browserFrame.page.context.responseCache.add(this.request, {
...returnResponse,
waitingForBody: false
});
return returnResponse;
}
/**
* Checks if the request complies with the Cross-Origin policy.
*
* @returns True if it complies with the policy.
*/
compliesWithCrossOriginPolicy() {
if (this.disableSameOriginPolicy ||
!FetchCORSUtility_js_1.default.isCORS(this.#window.location.href, this.request[PropertySymbol.url])) {
return true;
}
const cachedPreflightResponse = this.#browserFrame.page.context.preflightResponseCache.get(this.request);
if (cachedPreflightResponse) {
if (cachedPreflightResponse.allowOrigin !== '*' &&
cachedPreflightResponse.allowOrigin !== this.#window.location.origin) {
return false;
}
if (cachedPreflightResponse.allowMethods.length !== 0 &&
!cachedPreflightResponse.allowMethods.includes(this.request.method)) {
return false;
}
return true;
}
const requestHeaders = [];
for (const [header] of this.request.headers) {
requestHeaders.push(header.toLowerCase());
}
const corsHeaders = new Headers_js_1.default({
'Access-Control-Request-Method': this.request.method,
Origin: this.#window.location.origin
});
if (requestHeaders.length > 0) {
// This intentionally does not use "combine" (comma + space), as the spec dictates.
// See https://fetch.spec.whatwg.org/#cors-preflight-fetch for more details.
// Sorting the headers is not required, but can optimize cache hits.
corsHeaders.set('Access-Control-Request-Headers', requestHeaders.slice().sort().join(','));
}
const fetch = new SyncFetch({
browserFrame: this.#browserFrame,
window: this.#window,
url: this.request.url,
init: { method: 'OPTIONS' },
disableCache: true,
disableSameOriginPolicy: true,
unfilteredHeaders: corsHeaders
});
const response = fetch.send();
if (!response.ok) {
return false;
}
const allowOrigin = response.headers.get('Access-Control-Allow-Origin');
if (!allowOrigin) {
return false;
}
if (allowOrigin !== '*' && allowOrigin !== this.#window.location.origin) {
return false;
}
const allowMethods = [];
if (response.headers.has('Access-Control-Allow-Methods')) {
const allowMethodsHeader = response.headers.get('Access-Control-Allow-Methods');
if (allowMethodsHeader !== '*') {
for (const method of allowMethodsHeader.split(',')) {
allowMethods.push(method.trim().toUpperCase());
}
}
}
if (allowMethods.length !== 0 && !allowMethods.includes(this.request.method)) {
return false;
}
// TODO: Add support for more Access-Control-Allow-* headers.
return true;
}
/**
* Sends request.
*
* @returns Response.
*/
sendRequest() {
if (!this.request[PropertySymbol.bodyBuffer] && this.request.body) {
throw new this.#window.DOMException(`Streams are not supported as request body for synchronous requests.`, DOMExceptionNameEnum_js_1.default.notSupportedError);
}
const script = SyncFetchScriptBuilder_js_1.default.getScript({
url: this.request[PropertySymbol.url],
method: this.request.method,
headers: FetchRequestHeaderUtility_js_1.default.getRequestHeaders({
browserFrame: this.#browserFrame,
window: this.#window,
request: this.request,
baseHeaders: this.#unfilteredHeaders
}),
disableStrictSSL: this.#browserFrame.page.context.browser.settings.fetch.disableStrictSSL,
body: this.request[PropertySymbol.bodyBuffer]
});
// Start the other Node Process, executing this string
const content = child_process_1.default.execFileSync(process.argv[0], ['-e', script], {
encoding: 'buffer',
maxBuffer: 1024 * 1024 * 1024 // TODO: Consistent buffer size: 1GB.
});
// If content length is 0, then there was an error
if (!content.length) {
throw new this.#window.DOMException(`Synchronous fetch to "${this.request.url}" failed.`, DOMExceptionNameEnum_js_1.default.networkError);
}
const { error, incomingMessage } = JSON.parse(content.toString());
if (error) {
throw new this.#window.DOMException(`Synchronous fetch to "${this.request.url}" failed. Error: ${error}`, DOMExceptionNameEnum_js_1.default.networkError);
}
const headers = FetchResponseHeaderUtility_js_1.default.parseResponseHeaders({
browserFrame: this.#browserFrame,
requestURL: this.request[PropertySymbol.url],
rawHeaders: incomingMessage.rawHeaders
});
const response = {
status: incomingMessage.statusCode,
statusText: incomingMessage.statusMessage,
ok: incomingMessage.statusCode >= 200 && incomingMessage.statusCode < 300,
url: this.request.url,
redirected: this.redirectCount > 0,
headers,
body: this.parseIResponseBody({
headers,
status: incomingMessage.statusCode,
body: Buffer.from(incomingMessage.data, 'base64')
})
};
const redirectedResponse = this.handleRedirectResponse(response) || response;
if (!this.disableCache && !redirectedResponse.redirected) {
this.#browserFrame.page.context.responseCache.add(this.request, {
status: redirectedResponse.status,
statusText: redirectedResponse.statusText,
url: redirectedResponse.url,
headers: redirectedResponse.headers,
body: redirectedResponse.body,
waitingForBody: false
});
}
const interceptedResponse = this.interceptor?.afterSyncResponse
? this.interceptor.afterSyncResponse({
window: this.#window,
response: redirectedResponse,
request: this.request
})
: undefined;
const returnResponse = typeof interceptedResponse === 'object' ? interceptedResponse : redirectedResponse;
if (!returnResponse.ok) {
this.#browserFrame?.page?.console.error(`${this.request.method} ${this.request.url} ${returnResponse.status} (${returnResponse.statusText})`);
}
return returnResponse;
}
/**
* Parses response body.
*
* @param options Options.
* @param options.headers Headers.
* @param options.status Status.
* @param options.body Body.
* @returns Parsed body.
*/
parseIResponseBody(options) {
const contentEncodingHeader = options.headers.get('Content-Encoding');
if (this.request.method === 'HEAD' ||
contentEncodingHeader === null ||
options.status === 204 ||
options.status === 304) {
return options.body;
}
try {
// For GZip
if (contentEncodingHeader === 'gzip' || contentEncodingHeader === 'x-gzip') {
// Be less strict when decoding compressed responses by using Z_SYNC_FLUSH.
// Sometimes servers send slightly invalid responses that are still accepted by common browsers.
// "cURL" always uses Z_SYNC_FLUSH.
return zlib_1.default.gunzipSync(options.body, {
flush: zlib_1.default.constants.Z_SYNC_FLUSH,
finishFlush: zlib_1.default.constants.Z_SYNC_FLUSH
});
}
// For Deflate
if (contentEncodingHeader === 'deflate' || contentEncodingHeader === 'x-deflate') {
return zlib_1.default.inflateSync(options.body);
}
// For BR
if (contentEncodingHeader === 'br') {
return zlib_1.default.brotliDecompressSync(options.body);
}
}
catch (error) {
throw new this.#window.DOMException(`Failed to read response body. Error: ${error.message}.`, DOMExceptionNameEnum_js_1.default.encodingError);
}
return options.body;
}
/**
* Handles redirect response.
*
* @param response Response.
* @returns Redirected response or null.
*/
handleRedirectResponse(response) {
if (!FetchResponseRedirectUtility_js_1.default.isRedirect(response.status)) {
return null;
}
switch (this.request.redirect) {
case 'error':
throw new this.#window.DOMException(`URI requested responds with a redirect, redirect mode is set to "error": ${this.request.url}`, DOMExceptionNameEnum_js_1.default.abortError);
case 'manual':
return null;
case 'follow':
const locationHeader = response.headers.get('Location');
const shouldBecomeGetRequest = response.status === 303 ||
((response.status === 301 || response.status === 302) && this.request.method === 'POST');
let locationURL = null;
if (locationHeader !== null) {
try {
locationURL = new URL_js_1.default(locationHeader, this.request.url);
}
catch {
throw new this.#window.DOMException(`URI requested responds with an invalid redirect URL: ${locationHeader}`, DOMExceptionNameEnum_js_1.default.uriMismatchError);
}
}
if (locationURL === null) {
return null;
}
if (FetchResponseRedirectUtility_js_1.default.isMaxRedirectsReached(this.redirectCount)) {
throw new this.#window.DOMException(`Maximum redirects reached at: ${this.request.url}`, DOMExceptionNameEnum_js_1.default.networkError);
}
const headers = new Headers_js_1.default(this.request.headers);
const requestInit = {
method: this.request.method,
signal: this.request.signal,
referrer: this.request.referrer,
referrerPolicy: this.request.referrerPolicy,
credentials: this.request.credentials,
headers,
body: this.request[PropertySymbol.bodyBuffer]
};
if (this.request.credentials === 'omit' ||
(this.request.credentials === 'same-origin' &&
FetchCORSUtility_js_1.default.isCORS(this.#window.location.href, locationURL))) {
headers.delete('authorization');
headers.delete('www-authenticate');
headers.delete('cookie');
headers.delete('cookie2');
}
if (shouldBecomeGetRequest) {
requestInit.method = 'GET';
requestInit.body = undefined;
headers.delete('Content-Length');
headers.delete('Content-Type');
}
const responseReferrerPolicy = FetchRequestReferrerUtility_js_1.default.getReferrerPolicyFromHeader(headers);
if (responseReferrerPolicy) {
requestInit.referrerPolicy = responseReferrerPolicy;
}
const fetch = new SyncFetch({
browserFrame: this.#browserFrame,
window: this.#window,
url: locationURL,
init: requestInit,
redirectCount: this.redirectCount + 1,
contentType: !shouldBecomeGetRequest
? this.request[PropertySymbol.contentType]
: undefined
});
return fetch.send();
default:
throw new this.#window.DOMException(`Redirect option '${this.request.redirect}' is not a valid value of IRequestRedirect`);
}
}
}
exports.default = SyncFetch;
//# sourceMappingURL=SyncFetch.cjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,90 @@
import IRequestInit from './types/IRequestInit.cjs';
import IRequestInfo from './types/IRequestInfo.cjs';
import IBrowserFrame from '../browser/types/IBrowserFrame.cjs';
import BrowserWindow from '../window/BrowserWindow.cjs';
import ISyncResponse from './types/ISyncResponse.cjs';
import Headers from './Headers.cjs';
/**
* Handles synchronous fetch requests.
*/
export default class SyncFetch {
#private;
private request;
private redirectCount;
private disableCache;
private disableSameOriginPolicy;
private interceptor?;
/**
* Constructor.
*
* @param options Options.
* @param options.browserFrame Browser frame.
* @param options.window Window.
* @param options.url URL.
* @param [options.init] Init.
* @param [options.redirectCount] Redirect count.
* @param [options.contentType] Content Type.
* @param [options.disableCache] Disables the use of cached responses. It will still store the response in the cache.
* @param [options.disableSameOriginPolicy] Disables the Same-Origin policy.
* @param [options.unfilteredHeaders] Unfiltered headers - necessary for preflight requests.
*/
constructor(options: {
browserFrame: IBrowserFrame;
window: BrowserWindow;
url: IRequestInfo;
init?: IRequestInit;
redirectCount?: number;
contentType?: string;
disableCache?: boolean;
disableSameOriginPolicy?: boolean;
unfilteredHeaders?: Headers;
});
/**
* Sends request.
*
* @returns Response.
*/
send(): ISyncResponse;
/**
* Returns cached response.
*
* @returns Response.
*/
getCachedResponse(): ISyncResponse | null;
/**
* Returns virtual server response.
*
* @returns Response.
*/
private getVirtualServerResponse;
/**
* Checks if the request complies with the Cross-Origin policy.
*
* @returns True if it complies with the policy.
*/
private compliesWithCrossOriginPolicy;
/**
* Sends request.
*
* @returns Response.
*/
sendRequest(): ISyncResponse;
/**
* Parses response body.
*
* @param options Options.
* @param options.headers Headers.
* @param options.status Status.
* @param options.body Body.
* @returns Parsed body.
*/
private parseIResponseBody;
/**
* Handles redirect response.
*
* @param response Response.
* @returns Redirected response or null.
*/
private handleRedirectResponse;
}
//# sourceMappingURL=SyncFetch.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"SyncFetch.d.ts","sourceRoot":"","sources":["../../src/fetch/SyncFetch.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,yBAAyB,CAAC;AAEnD,OAAO,YAAY,MAAM,yBAAyB,CAAC;AAMnD,OAAO,aAAa,MAAM,mCAAmC,CAAC;AAC9D,OAAO,aAAa,MAAM,4BAA4B,CAAC;AAEvD,OAAO,aAAa,MAAM,0BAA0B,CAAC;AACrD,OAAO,OAAO,MAAM,cAAc,CAAC;AAyBnC;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,SAAS;;IAC7B,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,YAAY,CAAU;IAC9B,OAAO,CAAC,uBAAuB,CAAU;IACzC,OAAO,CAAC,WAAW,CAAC,CAAoB;IAKxC;;;;;;;;;;;;;OAaG;gBACS,OAAO,EAAE;QACpB,YAAY,EAAE,aAAa,CAAC;QAC5B,MAAM,EAAE,aAAa,CAAC;QACtB,GAAG,EAAE,YAAY,CAAC;QAClB,IAAI,CAAC,EAAE,YAAY,CAAC;QACpB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,uBAAuB,CAAC,EAAE,OAAO,CAAC;QAClC,iBAAiB,CAAC,EAAE,OAAO,CAAC;KAC5B;IAoBD;;;;OAIG;IACI,IAAI,IAAI,aAAa;IAuF5B;;;;OAIG;IACI,iBAAiB,IAAI,aAAa,GAAG,IAAI;IAkFhD;;;;OAIG;IACH,OAAO,CAAC,wBAAwB;IAmEhC;;;;OAIG;IACH,OAAO,CAAC,6BAA6B;IA8FrC;;;;OAIG;IACI,WAAW,IAAI,aAAa;IA8FnC;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;IA2C1B;;;;;OAKG;IACH,OAAO,CAAC,sBAAsB;CA+F9B"}

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=ICachablePreflightRequest.cjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ICachablePreflightRequest.cjs","sourceRoot":"","sources":["../../../../src/fetch/cache/preflight/ICachablePreflightRequest.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,7 @@
import Headers from '../../Headers.cjs';
export default interface ICachablePreflightRequest {
url: string;
method: string;
headers: Headers;
}
//# sourceMappingURL=ICachablePreflightRequest.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ICachablePreflightRequest.d.ts","sourceRoot":"","sources":["../../../../src/fetch/cache/preflight/ICachablePreflightRequest.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,kBAAkB,CAAC;AAEvC,MAAM,CAAC,OAAO,WAAW,yBAAyB;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CACjB"}

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=ICachablePreflightResponse.cjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ICachablePreflightResponse.cjs","sourceRoot":"","sources":["../../../../src/fetch/cache/preflight/ICachablePreflightResponse.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,7 @@
import Headers from '../../Headers.cjs';
export default interface ICachablePreflightResponse {
status: number;
url: string;
headers: Headers;
}
//# sourceMappingURL=ICachablePreflightResponse.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ICachablePreflightResponse.d.ts","sourceRoot":"","sources":["../../../../src/fetch/cache/preflight/ICachablePreflightResponse.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,kBAAkB,CAAC;AAEvC,MAAM,CAAC,OAAO,WAAW,0BAA0B;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,OAAO,CAAC;CACjB"}

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=ICachedPreflightResponse.cjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ICachedPreflightResponse.cjs","sourceRoot":"","sources":["../../../../src/fetch/cache/preflight/ICachedPreflightResponse.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,6 @@
export default interface ICachedPreflightResponse {
allowOrigin: string;
allowMethods: string[];
expires: number;
}
//# sourceMappingURL=ICachedPreflightResponse.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ICachedPreflightResponse.d.ts","sourceRoot":"","sources":["../../../../src/fetch/cache/preflight/ICachedPreflightResponse.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,WAAW,wBAAwB;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CAChB"}

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=IPreflightResponseCache.cjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"IPreflightResponseCache.cjs","sourceRoot":"","sources":["../../../../src/fetch/cache/preflight/IPreflightResponseCache.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,28 @@
import ICachedPreflightResponse from './ICachedPreflightResponse.cjs';
import ICachablePreflightRequest from './ICachablePreflightRequest.cjs';
import ICachablePreflightResponse from './ICachablePreflightResponse.cjs';
/**
* Fetch response cache.
*/
export default interface IPreflightResponseCache {
/**
* Returns cached response.
*
* @param request Request.
* @returns Cached response.
*/
get(request: ICachablePreflightRequest): ICachedPreflightResponse | null;
/**
* Adds a cached response.
*
* @param request Request.
* @param response Response.
* @returns Cached response.
*/
add(request: ICachablePreflightRequest, response: ICachablePreflightResponse): ICachedPreflightResponse | null;
/**
* Clears the cache.
*/
clear(): void;
}
//# sourceMappingURL=IPreflightResponseCache.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"IPreflightResponseCache.d.ts","sourceRoot":"","sources":["../../../../src/fetch/cache/preflight/IPreflightResponseCache.ts"],"names":[],"mappings":"AAAA,OAAO,wBAAwB,MAAM,+BAA+B,CAAC;AACrE,OAAO,yBAAyB,MAAM,gCAAgC,CAAC;AACvE,OAAO,0BAA0B,MAAM,iCAAiC,CAAC;AAEzE;;GAEG;AACH,MAAM,CAAC,OAAO,WAAW,uBAAuB;IAC/C;;;;;OAKG;IACH,GAAG,CAAC,OAAO,EAAE,yBAAyB,GAAG,wBAAwB,GAAG,IAAI,CAAC;IAEzE;;;;;;OAMG;IACH,GAAG,CACF,OAAO,EAAE,yBAAyB,EAClC,QAAQ,EAAE,0BAA0B,GAClC,wBAAwB,GAAG,IAAI,CAAC;IAEnC;;OAEG;IACH,KAAK,IAAI,IAAI,CAAC;CACd"}

View File

@@ -0,0 +1,75 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Fetch preflight response cache.
*
* @see https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request
*/
class PreflightResponseCache {
#entries = {};
/**
* Returns cached response.
*
* @param request Request.
* @returns Cached response.
*/
get(request) {
const cachedResponse = this.#entries[request.url];
if (cachedResponse) {
if (cachedResponse.expires < Date.now()) {
delete this.#entries[request.url];
return null;
}
return cachedResponse;
}
return null;
}
/**
* Adds a cache entity.
*
* @param request Request.
* @param response Response.
* @returns Cached response.
*/
add(request, response) {
delete this.#entries[request.url];
if (request.headers.get('Cache-Control')?.includes('no-cache')) {
return null;
}
if (response.status < 200 || response.status >= 300) {
return null;
}
const maxAge = response.headers.get('Access-Control-Max-Age');
const allowOrigin = response.headers.get('Access-Control-Allow-Origin');
if (!maxAge || !allowOrigin) {
return null;
}
const allowMethods = [];
if (response.headers.has('Access-Control-Allow-Methods')) {
const allowMethodsHeader = response.headers.get('Access-Control-Allow-Methods');
if (allowMethodsHeader !== '*') {
for (const method of response.headers.get('Access-Control-Allow-Methods').split(',')) {
allowMethods.push(method.trim().toUpperCase());
}
}
}
const cachedResponse = {
allowOrigin,
allowMethods,
expires: Date.now() + parseInt(maxAge) * 1000
};
if (isNaN(cachedResponse.expires) || cachedResponse.expires < Date.now()) {
return null;
}
this.#entries[request.url] = cachedResponse;
return cachedResponse;
}
/**
* Clears the cache.
*/
clear() {
this.#entries = {};
}
}
exports.default = PreflightResponseCache;
//# sourceMappingURL=PreflightResponseCache.cjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"PreflightResponseCache.cjs","sourceRoot":"","sources":["../../../../src/fetch/cache/preflight/PreflightResponseCache.ts"],"names":[],"mappings":";;AAKA;;;;GAIG;AACH,MAAqB,sBAAsB;IAC1C,QAAQ,GAAgD,EAAE,CAAC;IAE3D;;;;;OAKG;IACI,GAAG,CAAC,OAAkC;QAC5C,MAAM,cAAc,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAElD,IAAI,cAAc,EAAE,CAAC;YACpB,IAAI,cAAc,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;gBACzC,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAClC,OAAO,IAAI,CAAC;YACb,CAAC;YACD,OAAO,cAAc,CAAC;QACvB,CAAC;QAED,OAAO,IAAI,CAAC;IACb,CAAC;IAED;;;;;;OAMG;IACI,GAAG,CACT,OAAkC,EAClC,QAAoC;QAEpC,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAElC,IAAI,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YAChE,OAAO,IAAI,CAAC;QACb,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;YACrD,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QAC9D,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;QAExE,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;YAC7B,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,YAAY,GAAa,EAAE,CAAC;QAElC,IAAI,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,EAAE,CAAC;YAC1D,MAAM,kBAAkB,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;YAChF,IAAI,kBAAkB,KAAK,GAAG,EAAE,CAAC;gBAChC,KAAK,MAAM,MAAM,IAAI,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;oBACtF,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;gBAChD,CAAC;YACF,CAAC;QACF,CAAC;QAED,MAAM,cAAc,GAA6B;YAChD,WAAW;YACX,YAAY;YACZ,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI;SAC7C,CAAC;QAEF,IAAI,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI,cAAc,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YAC1E,OAAO,IAAI,CAAC;QACb,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC;QAE5C,OAAO,cAAc,CAAC;IACvB,CAAC;IAED;;OAEG;IACI,KAAK;QACX,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;IACpB,CAAC;CACD;AAnFD,yCAmFC"}

View File

@@ -0,0 +1,32 @@
import IPreflightResponseCache from './IPreflightResponseCache.cjs';
import ICachablePreflightRequest from './ICachablePreflightRequest.cjs';
import ICachedPreflightResponse from './ICachedPreflightResponse.cjs';
import ICachablePreflightResponse from './ICachablePreflightResponse.cjs';
/**
* Fetch preflight response cache.
*
* @see https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request
*/
export default class PreflightResponseCache implements IPreflightResponseCache {
#private;
/**
* Returns cached response.
*
* @param request Request.
* @returns Cached response.
*/
get(request: ICachablePreflightRequest): ICachedPreflightResponse | null;
/**
* Adds a cache entity.
*
* @param request Request.
* @param response Response.
* @returns Cached response.
*/
add(request: ICachablePreflightRequest, response: ICachablePreflightResponse): ICachedPreflightResponse;
/**
* Clears the cache.
*/
clear(): void;
}
//# sourceMappingURL=PreflightResponseCache.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"PreflightResponseCache.d.ts","sourceRoot":"","sources":["../../../../src/fetch/cache/preflight/PreflightResponseCache.ts"],"names":[],"mappings":"AAAA,OAAO,uBAAuB,MAAM,8BAA8B,CAAC;AACnE,OAAO,yBAAyB,MAAM,gCAAgC,CAAC;AACvE,OAAO,wBAAwB,MAAM,+BAA+B,CAAC;AACrE,OAAO,0BAA0B,MAAM,iCAAiC,CAAC;AAEzE;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,sBAAuB,YAAW,uBAAuB;;IAG7E;;;;;OAKG;IACI,GAAG,CAAC,OAAO,EAAE,yBAAyB,GAAG,wBAAwB,GAAG,IAAI;IAc/E;;;;;;OAMG;IACI,GAAG,CACT,OAAO,EAAE,yBAAyB,EAClC,QAAQ,EAAE,0BAA0B,GAClC,wBAAwB;IA4C3B;;OAEG;IACI,KAAK,IAAI,IAAI;CAGpB"}

View File

@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var CachedResponseStateEnum;
(function (CachedResponseStateEnum) {
CachedResponseStateEnum["fresh"] = "fresh";
CachedResponseStateEnum["stale"] = "stale";
})(CachedResponseStateEnum || (CachedResponseStateEnum = {}));
exports.default = CachedResponseStateEnum;
//# sourceMappingURL=CachedResponseStateEnum.cjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"CachedResponseStateEnum.cjs","sourceRoot":"","sources":["../../../../src/fetch/cache/response/CachedResponseStateEnum.ts"],"names":[],"mappings":";;AAAA,IAAK,uBAGJ;AAHD,WAAK,uBAAuB;IAC3B,0CAAe,CAAA;IACf,0CAAe,CAAA;AAChB,CAAC,EAHI,uBAAuB,KAAvB,uBAAuB,QAG3B;AACD,kBAAe,uBAAuB,CAAC"}

View File

@@ -0,0 +1,6 @@
declare enum CachedResponseStateEnum {
fresh = "fresh",
stale = "stale"
}
export default CachedResponseStateEnum;
//# sourceMappingURL=CachedResponseStateEnum.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"CachedResponseStateEnum.d.ts","sourceRoot":"","sources":["../../../../src/fetch/cache/response/CachedResponseStateEnum.ts"],"names":[],"mappings":"AAAA,aAAK,uBAAuB;IAC3B,KAAK,UAAU;IACf,KAAK,UAAU;CACf;AACD,eAAe,uBAAuB,CAAC"}

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=ICachableRequest.cjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ICachableRequest.cjs","sourceRoot":"","sources":["../../../../src/fetch/cache/response/ICachableRequest.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,7 @@
import Headers from '../../Headers.cjs';
export default interface ICachableRequest {
url: string;
method: string;
headers: Headers;
}
//# sourceMappingURL=ICachableRequest.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ICachableRequest.d.ts","sourceRoot":"","sources":["../../../../src/fetch/cache/response/ICachableRequest.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,kBAAkB,CAAC;AAEvC,MAAM,CAAC,OAAO,WAAW,gBAAgB;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CACjB"}

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=ICachableResponse.cjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ICachableResponse.cjs","sourceRoot":"","sources":["../../../../src/fetch/cache/response/ICachableResponse.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,10 @@
import Headers from '../../Headers.cjs';
export default interface ICachableResponse {
status: number;
statusText: string;
url: string;
headers: Headers;
body: Buffer | null;
waitingForBody: boolean;
}
//# sourceMappingURL=ICachableResponse.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ICachableResponse.d.ts","sourceRoot":"","sources":["../../../../src/fetch/cache/response/ICachableResponse.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,kBAAkB,CAAC;AAEvC,MAAM,CAAC,OAAO,WAAW,iBAAiB;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,cAAc,EAAE,OAAO,CAAC;CACxB"}

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=ICachedResponse.cjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ICachedResponse.cjs","sourceRoot":"","sources":["../../../../src/fetch/cache/response/ICachedResponse.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,37 @@
import CachedResponseStateEnum from './CachedResponseStateEnum.cjs';
import Headers from '../../Headers.cjs';
export default interface ICachedResponse {
/** Response. */
response: {
status: number;
statusText: string;
url: string;
headers: Headers;
waitingForBody: boolean;
body: Buffer | null;
};
/** Request. */
request: {
headers: Headers;
method: string;
};
/** Cache update time in milliseconds. */
cacheUpdateTime: number;
/** Last modified time in milliseconds. */
lastModified: number | null;
/** Vary headers. */
vary: {
[header: string]: string;
};
/** Expire time in milliseconds. */
expires: number | null;
/** ETag */
etag: string | null;
/** Must revalidate using "If-Modified-Since" request when expired. Not supported yet. */
mustRevalidate: boolean;
/** Stale while revalidate using "If-Modified-Since" request when expired */
staleWhileRevalidate: boolean;
/** Used when "mustRevalidate" or "staleWhileRevalidate" is true. */
state: CachedResponseStateEnum;
}
//# sourceMappingURL=ICachedResponse.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ICachedResponse.d.ts","sourceRoot":"","sources":["../../../../src/fetch/cache/response/ICachedResponse.ts"],"names":[],"mappings":"AAAA,OAAO,uBAAuB,MAAM,8BAA8B,CAAC;AACnE,OAAO,OAAO,MAAM,kBAAkB,CAAC;AAEvC,MAAM,CAAC,OAAO,WAAW,eAAe;IACvC,gBAAgB;IAChB,QAAQ,EAAE;QACT,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;QACnB,GAAG,EAAE,MAAM,CAAC;QACZ,OAAO,EAAE,OAAO,CAAC;QAEjB,cAAc,EAAE,OAAO,CAAC;QACxB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;KACpB,CAAC;IACF,eAAe;IACf,OAAO,EAAE;QACR,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;KACf,CAAC;IACF,yCAAyC;IACzC,eAAe,EAAE,MAAM,CAAC;IACxB,0CAA0C;IAC1C,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,oBAAoB;IACpB,IAAI,EAAE;QAAE,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IACnC,mCAAmC;IACnC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW;IACX,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,yFAAyF;IACzF,cAAc,EAAE,OAAO,CAAC;IACxB,4EAA4E;IAC5E,oBAAoB,EAAE,OAAO,CAAC;IAC9B,oEAAoE;IACpE,KAAK,EAAE,uBAAuB,CAAC;CAC/B"}

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=IResponseCache.cjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"IResponseCache.cjs","sourceRoot":"","sources":["../../../../src/fetch/cache/response/IResponseCache.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,35 @@
import ICachedResponse from './ICachedResponse.cjs';
import ICachableRequest from './ICachableRequest.cjs';
import ICachableResponse from './ICachableResponse.cjs';
/**
* Fetch response cache.
*/
export default interface IResponseCache {
/**
* Returns cached response.
*
* @param request Request.
* @returns Cached response.
*/
get(request: ICachableRequest): ICachedResponse | null;
/**
* Adds a cached response.
*
* @param request Request.
* @param response Response.
* @returns Cached response.
*/
add(request: ICachableRequest, response: ICachableResponse): ICachedResponse | null;
/**
* Clears the cache.
*
* @param [options] Options.
* @param [options.url] URL.
* @param [options.toTime] Time in MS.
*/
clear(options?: {
url?: string;
toTime?: number;
}): void;
}
//# sourceMappingURL=IResponseCache.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"IResponseCache.d.ts","sourceRoot":"","sources":["../../../../src/fetch/cache/response/IResponseCache.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,MAAM,sBAAsB,CAAC;AACnD,OAAO,gBAAgB,MAAM,uBAAuB,CAAC;AACrD,OAAO,iBAAiB,MAAM,wBAAwB,CAAC;AAEvD;;GAEG;AACH,MAAM,CAAC,OAAO,WAAW,cAAc;IACtC;;;;;OAKG;IACH,GAAG,CAAC,OAAO,EAAE,gBAAgB,GAAG,eAAe,GAAG,IAAI,CAAC;IAEvD;;;;;;OAMG;IACH,GAAG,CAAC,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,iBAAiB,GAAG,eAAe,GAAG,IAAI,CAAC;IAEpF;;;;;;OAMG;IACH,KAAK,CAAC,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CACzD"}

View File

@@ -0,0 +1,205 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const CachedResponseStateEnum_js_1 = __importDefault(require("./CachedResponseStateEnum.cjs"));
const Headers_js_1 = __importDefault(require("../../Headers.cjs"));
const UPDATE_RESPONSE_HEADERS = ['Cache-Control', 'Last-Modified', 'Vary', 'ETag'];
/**
* Fetch response cache.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching
* @see https://www.mnot.net/cache_docs/
*/
class ResponseCache {
#entries = {};
/**
* Returns cached response.
*
* @param request Request.
* @returns Cached response.
*/
get(request) {
if (request.headers.get('Cache-Control')?.includes('no-cache')) {
return null;
}
const url = request.url;
if (this.#entries[url]) {
for (let i = 0, max = this.#entries[url].length; i < max; i++) {
const entry = this.#entries[url][i];
let isMatch = entry.request.method === request.method;
if (isMatch) {
for (const header of Object.keys(entry.vary)) {
const requestHeader = request.headers.get(header);
if (requestHeader !== null && entry.vary[header] !== requestHeader) {
isMatch = false;
break;
}
}
}
if (isMatch) {
if (entry.expires && entry.expires < Date.now()) {
if (entry.lastModified) {
entry.state = CachedResponseStateEnum_js_1.default.stale;
}
else if (!entry.etag) {
this.#entries[url].splice(i, 1);
return null;
}
}
return entry;
}
}
}
return null;
}
/**
* Adds a cache entity.
*
* @param request Request.
* @param response Response.
* @returns Cached response.
*/
add(request, response) {
// We should only cache GET and HEAD requests.
if ((request.method !== 'GET' && request.method !== 'HEAD') ||
request.headers.get('Cache-Control')?.includes('no-cache')) {
return null;
}
const url = request.url;
let cachedResponse = this.get(request);
if (response.status === 304) {
if (!cachedResponse) {
throw new Error('ResponseCache: Cached response not found.');
}
for (const name of UPDATE_RESPONSE_HEADERS) {
if (response.headers.has(name)) {
cachedResponse.response.headers.set(name, response.headers.get(name));
}
}
cachedResponse.cacheUpdateTime = Date.now();
cachedResponse.state = CachedResponseStateEnum_js_1.default.fresh;
}
else {
if (cachedResponse) {
const index = this.#entries[url].indexOf(cachedResponse);
if (index !== -1) {
this.#entries[url].splice(index, 1);
}
}
cachedResponse = {
response: {
status: response.status,
statusText: response.statusText,
url: response.url,
headers: new Headers_js_1.default(response.headers),
// We need to wait for the body to be consumed and then populated if set to true (e.g. by using Response.text()).
waitingForBody: response.waitingForBody,
body: response.body ?? null
},
request: {
headers: request.headers,
method: request.method
},
vary: {},
expires: null,
etag: null,
cacheUpdateTime: Date.now(),
lastModified: null,
mustRevalidate: false,
staleWhileRevalidate: false,
state: CachedResponseStateEnum_js_1.default.fresh
};
this.#entries[url] = this.#entries[url] || [];
this.#entries[url].push(cachedResponse);
}
if (response.headers.has('Cache-Control')) {
const age = response.headers.get('Age');
for (const part of response.headers.get('Cache-Control').split(',')) {
const [key, value] = part.trim().split('=');
switch (key) {
case 'max-age':
cachedResponse.expires =
Date.now() + parseInt(value) * 1000 - (age ? parseInt(age) * 1000 : 0);
break;
case 'no-cache':
case 'no-store':
const index = this.#entries[url].indexOf(cachedResponse);
if (index !== -1) {
this.#entries[url].splice(index, 1);
}
return null;
case 'must-revalidate':
cachedResponse.mustRevalidate = true;
break;
case 'stale-while-revalidate':
cachedResponse.staleWhileRevalidate = true;
break;
}
}
}
if (response.headers.has('Last-Modified')) {
cachedResponse.lastModified = Date.parse(response.headers.get('Last-Modified'));
}
if (response.headers.has('Vary')) {
for (const header of response.headers.get('Vary').split(',')) {
const name = header.trim();
const value = request.headers.get(name);
if (value) {
cachedResponse.vary[name] = value;
}
}
}
if (response.headers.has('ETag')) {
cachedResponse.etag = response.headers.get('ETag');
}
if (!cachedResponse.expires) {
const expires = response.headers.get('Expires');
if (expires) {
cachedResponse.expires = Date.parse(expires);
}
}
// Cache is invalid if it has expired and doesn't have an ETag.
if (!cachedResponse.etag && (!cachedResponse.expires || cachedResponse.expires < Date.now())) {
const index = this.#entries[url].indexOf(cachedResponse);
if (index !== -1) {
this.#entries[url].splice(index, 1);
}
return null;
}
return cachedResponse;
}
/**
* Clears the cache.
*
* @param [options] Options.
* @param [options.url] URL.
* @param [options.toTime] Removes all entries that are older than this time. Time in MS.
*/
clear(options) {
if (options) {
if (options.toTime) {
for (const key of options.url ? [options.url] : Object.keys(this.#entries)) {
if (this.#entries[key]) {
for (let i = 0, max = this.#entries[key].length; i < max; i++) {
if (this.#entries[key][i].cacheUpdateTime < options.toTime) {
this.#entries[key].splice(i, 1);
i--;
max--;
}
}
}
}
}
else if (options.url) {
delete this.#entries[options.url];
}
}
else {
this.#entries = {};
}
}
}
exports.default = ResponseCache;
//# sourceMappingURL=ResponseCache.cjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,40 @@
import IResponseCache from './IResponseCache.cjs';
import ICachedResponse from './ICachedResponse.cjs';
import ICachableRequest from './ICachableRequest.cjs';
import ICachableResponse from './ICachableResponse.cjs';
/**
* Fetch response cache.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching
* @see https://www.mnot.net/cache_docs/
*/
export default class ResponseCache implements IResponseCache {
#private;
/**
* Returns cached response.
*
* @param request Request.
* @returns Cached response.
*/
get(request: ICachableRequest): ICachedResponse | null;
/**
* Adds a cache entity.
*
* @param request Request.
* @param response Response.
* @returns Cached response.
*/
add(request: ICachableRequest, response: ICachableResponse): ICachedResponse;
/**
* Clears the cache.
*
* @param [options] Options.
* @param [options.url] URL.
* @param [options.toTime] Removes all entries that are older than this time. Time in MS.
*/
clear(options?: {
url?: string;
toTime?: number;
}): void;
}
//# sourceMappingURL=ResponseCache.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ResponseCache.d.ts","sourceRoot":"","sources":["../../../../src/fetch/cache/response/ResponseCache.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,qBAAqB,CAAC;AACjD,OAAO,eAAe,MAAM,sBAAsB,CAAC;AAEnD,OAAO,gBAAgB,MAAM,uBAAuB,CAAC;AACrD,OAAO,iBAAiB,MAAM,wBAAwB,CAAC;AAKvD;;;;;GAKG;AACH,MAAM,CAAC,OAAO,OAAO,aAAc,YAAW,cAAc;;IAG3D;;;;;OAKG;IACI,GAAG,CAAC,OAAO,EAAE,gBAAgB,GAAG,eAAe,GAAG,IAAI;IAoC7D;;;;;;OAMG;IACI,GAAG,CAAC,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,iBAAiB,GAAG,eAAe;IA6HnF;;;;;;OAMG;IACI,KAAK,CAAC,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;CAqB/D"}

View File

@@ -0,0 +1,55 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// SSL certificate generated for Happy DOM to be able to perform HTTPS requests
exports.default = {
cert: `-----BEGIN CERTIFICATE-----
MIIDYzCCAkugAwIBAgIUJRKB/H66hpet1VfUlm0CiXqePA4wDQYJKoZIhvcNAQEL
BQAwQTELMAkGA1UEBhMCU0UxDjAMBgNVBAgMBVNrYW5lMQ4wDAYDVQQHDAVNYWxt
bzESMBAGA1UECgwJSGFwcHkgRE9NMB4XDTIyMTAxMTIyMDM0OVoXDTMyMTAwODIy
MDM0OVowQTELMAkGA1UEBhMCU0UxDjAMBgNVBAgMBVNrYW5lMQ4wDAYDVQQHDAVN
YWxtbzESMBAGA1UECgwJSGFwcHkgRE9NMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAqerQSQEg/SxVxRiwlItithr5e5EMZo1nsqt/xOxagbmpW3IEmt0j
bpbH7iEF4DDEo7KAOwUCOwVWeFxRoag8lG2ax48wrgjlCna45XDn0Xeg1ARajL04
gs46HZ0VrzIloVGfln0zgt/Vum5BNqs9Oc5fQoBmoP3cAn3dn4ZVcP0AKthtcyPl
q2DuNRN0PV0D2RtMSiAy9l1Ko6N5x+sAeClDyOL+sTDLngZBVeZyOKt9Id15S8Zt
XtA6VMgHnnF3jChn7pag77rsd/y5iANAVNZYqRl+Eg7xaDcsvbgH46UBOrBcB39Q
tTh5Mtjoxep5e3ZDFG+kQ1HUE+iz5O5n0wIDAQABo1MwUTAdBgNVHQ4EFgQU69s9
YSobG/m2SN4L/7zTaF7iDbwwHwYDVR0jBBgwFoAU69s9YSobG/m2SN4L/7zTaF7i
DbwwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAi/WUXx2oal8L
YnPlIuKfh49n/K18wXSYG//oFYwxfVxqpYH8hUiXVm/GUcXCxS++hUkaKLqXmH9q
MKJiCrZr3vS+2nsBKopkICu/TLdROl0sAI9lByfnEbfSAzjxe1IWJdK8NdY0y5m5
9pEr/URVIAp/CxrneyASb4q0Jg5To3FR7vYc+2X6wZn0MundKMg6Dp9/A37jiF3l
Tt/EJp299YZcsUzh+LnRuggRjnoOVu1aLcLFlaUiwZfy9m8mLG6B/mdW/qNzNMh9
Oqvg1zfGdpz/4D/2UUUBn6pq1vbsoAaF3OesoA3mfDcegDf/H9woJlpT0Wql+e68
Y3FblSokcA==
-----END CERTIFICATE-----`,
key: `-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCp6tBJASD9LFXF
GLCUi2K2Gvl7kQxmjWeyq3/E7FqBualbcgSa3SNulsfuIQXgMMSjsoA7BQI7BVZ4
XFGhqDyUbZrHjzCuCOUKdrjlcOfRd6DUBFqMvTiCzjodnRWvMiWhUZ+WfTOC39W6
bkE2qz05zl9CgGag/dwCfd2fhlVw/QAq2G1zI+WrYO41E3Q9XQPZG0xKIDL2XUqj
o3nH6wB4KUPI4v6xMMueBkFV5nI4q30h3XlLxm1e0DpUyAeecXeMKGfulqDvuux3
/LmIA0BU1lipGX4SDvFoNyy9uAfjpQE6sFwHf1C1OHky2OjF6nl7dkMUb6RDUdQT
6LPk7mfTAgMBAAECggEAKkwTkTjAt4UjzK56tl+EMQTB+ep/hb/JgoaChci4Nva6
m9LkJpDJ0yuhlTuPNOGu8XjrxsVWas7HWarRf0Zb3i7yip6wZYI9Ub+AA015x4DZ
/i0fRU2NFbK0cM67qSL4jxG8gj+kZP3HPGNZxHwX/53JxMolwgmvjMc8NgvAlSFd
NnV9h4xtbhUh1NGS5zmP3iU2rwnE8JrIEzwy6axLom7nekAgkdcbAr0UoBs8gcgH
aYNhU4Gz3tGcZZ0IXAfT/bJIH1Ko8AGv4pssWc3BXcmmNdm/+kzvHIxEIV7Qegmo
XG1ZyZCyD/0b4/3e8ySDBEDqwR+HeyTW2isWG2agAQKBgQDp44aTwr3dkIXY30xv
FPfUOipg/B49dWnffYJ9MWc1FT9ijNPAngWSk0EIiEQIazICcUBI4Yji6/KeyqLJ
GdLpDi1CkKqtyh73mjELinYp3EUQgEa77aQogGa2+nMOVfu+O5CtloUrv/A18jX3
+VEyaEASK0fWmnSI0OdlxQHIAQKBgQC5+xOls2F3MlKASvWRLlnW1wHqlDTtVoYg
5Nh8syZH4Ci2UH8tON3A5/7SWNM0t1cgV6Cw4zW8Z2spgIT/W0iYYrQ4hHL1xdCu
+CxL1km4Gy8Uwpsd+KdFahFqF/XTmLzW0HXLxWSK0fTwmdV0SFrKF3MXfTCU2AeZ
jJoMFb6P0wKBgQC3Odw6s0vkYAzLGhuZxfZkVvDOK5RRF0NKpttr0iEFL9EJFkPo
2KKK8jr3QTDy229BBJGUxsJi6u6VwS8HlehpVQbV59kd7oKV/EBBx0XMg1fDlopT
PNbmN7i/zbIG4AsoOyebJZjL7kBzMn1e9vzKHWtcEHXlw/hZGja8vjooAQKBgAeg
xK2HLfg1mCyq5meN/yFQsENu0LzrT5UJzddPgcJw7zqLEqxIKNBAs7Ls8by3yFsL
PQwERa/0jfCl1M6kb9XQNpQa2pw6ANUsWKTDpUJn2wZ+9N3F1RaDwzMWyH5lRVmK
M0qoTfdjpSg5Jwgd75taWt4bxGJWeflSSv8z5R0BAoGAWL8c527AbeBvx2tOYKkD
2TFranvANNcoMrbeviZSkkGvMNDP3p8b6juJwXOIeWNr8q4vFgCzLmq6d1/9gYm2
3XJwwyD0LKlqzkBrrKU47qrnmMosUrIRlrAzd3HbShOptxc6Iz2apSaUDKGKXkaw
gl5OpEjeliU7Mus0BVS858g=
-----END PRIVATE KEY-----`
};
//# sourceMappingURL=FetchHTTPSCertificate.cjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"FetchHTTPSCertificate.cjs","sourceRoot":"","sources":["../../../src/fetch/certificate/FetchHTTPSCertificate.ts"],"names":[],"mappings":";;AAAA,+EAA+E;AAC/E,kBAAe;IACd,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;0BAoBmB;IACzB,GAAG,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;0BA2BoB;CACzB,CAAC"}

View File

@@ -0,0 +1,6 @@
declare const _default: {
cert: string;
key: string;
};
export default _default;
//# sourceMappingURL=FetchHTTPSCertificate.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"FetchHTTPSCertificate.d.ts","sourceRoot":"","sources":["../../../src/fetch/certificate/FetchHTTPSCertificate.ts"],"names":[],"mappings":";;;;AACA,wBAkDE"}

View File

@@ -0,0 +1,60 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Data URI parser.
*
* Based on:
* https://github.com/TooTallNate/node-data-uri-to-buffer/blob/main/src/index.ts (MIT)
*/
class DataURIParser {
/**
* Returns a Buffer instance from the given data URI `uri`.
*
* @param uri Data URI.
* @returns Buffer.
*/
static parse(uri) {
if (!/^data:/i.test(uri)) {
throw new TypeError('`uri` does not appear to be a Data URI (must begin with "data:")');
}
// Strip newlines
uri = uri.replace(/\r?\n/g, '');
// Split the URI up into the "metadata" and the "data" portions
const firstComma = uri.indexOf(',');
if (firstComma === -1 || firstComma <= 4) {
throw new TypeError('malformed data: URI');
}
// Remove the "data:" scheme and parse the metadata
const meta = uri.substring(5, firstComma).split(';');
let charset = '';
let base64 = false;
let type = meta[0] || 'text/plain';
for (let i = 1; i < meta.length; i++) {
if (meta[i] === 'base64') {
base64 = true;
}
else if (meta[i]) {
type += `;${meta[i]}`;
if (meta[i].indexOf('charset=') === 0) {
charset = meta[i].substring(8);
}
}
}
// Defaults to US-ASCII only if type is not provided
if (!meta[0] && !charset.length) {
type += ';charset=US-ASCII';
charset = 'US-ASCII';
}
// Get the encoded data portion and decode URI-encoded chars
const encoding = base64 ? 'base64' : 'ascii';
const data = unescape(uri.substring(firstComma + 1));
const buffer = Buffer.from(data, encoding);
return {
type,
charset,
buffer
};
}
}
exports.default = DataURIParser;
//# sourceMappingURL=DataURIParser.cjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"DataURIParser.cjs","sourceRoot":"","sources":["../../../src/fetch/data-uri/DataURIParser.ts"],"names":[],"mappings":";;AAAA;;;;;GAKG;AACH,MAAqB,aAAa;IACjC;;;;;OAKG;IACI,MAAM,CAAC,KAAK,CAAC,GAAW;QAK9B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,SAAS,CAAC,kEAAkE,CAAC,CAAC;QACzF,CAAC;QAED,iBAAiB;QACjB,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAEhC,+DAA+D;QAC/D,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,UAAU,KAAK,CAAC,CAAC,IAAI,UAAU,IAAI,CAAC,EAAE,CAAC;YAC1C,MAAM,IAAI,SAAS,CAAC,qBAAqB,CAAC,CAAC;QAC5C,CAAC;QAED,mDAAmD;QACnD,MAAM,IAAI,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrD,IAAI,OAAO,GAAG,EAAE,CAAC;QACjB,IAAI,MAAM,GAAG,KAAK,CAAC;QACnB,IAAI,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC;QAEnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;gBAC1B,MAAM,GAAG,IAAI,CAAC;YACf,CAAC;iBAAM,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpB,IAAI,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtB,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;oBACvC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;gBAChC,CAAC;YACF,CAAC;QACF,CAAC;QAED,oDAAoD;QACpD,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YACjC,IAAI,IAAI,mBAAmB,CAAC;YAC5B,OAAO,GAAG,UAAU,CAAC;QACtB,CAAC;QAED,4DAA4D;QAC5D,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC;QAC7C,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC;QACrD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAE3C,OAAO;YACN,IAAI;YACJ,OAAO;YACP,MAAM;SACN,CAAC;IACH,CAAC;CACD;AA3DD,gCA2DC"}

View File

@@ -0,0 +1,20 @@
/**
* Data URI parser.
*
* Based on:
* https://github.com/TooTallNate/node-data-uri-to-buffer/blob/main/src/index.ts (MIT)
*/
export default class DataURIParser {
/**
* Returns a Buffer instance from the given data URI `uri`.
*
* @param uri Data URI.
* @returns Buffer.
*/
static parse(uri: string): {
type: string;
charset: string;
buffer: Buffer;
};
}
//# sourceMappingURL=DataURIParser.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"DataURIParser.d.ts","sourceRoot":"","sources":["../../../src/fetch/data-uri/DataURIParser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,OAAO,OAAO,aAAa;IACjC;;;;;OAKG;WACW,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG;QACjC,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;KACf;CAgDD"}

View File

@@ -0,0 +1,145 @@
"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 () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const web_1 = require("stream/web");
const PropertySymbol = __importStar(require("../../PropertySymbol.cjs"));
const MultipartReader_js_1 = __importDefault(require("./MultipartReader.cjs"));
const DOMExceptionNameEnum_js_1 = __importDefault(require("../../exception/DOMExceptionNameEnum.cjs"));
const buffer_1 = require("buffer");
/**
* Multipart form data factory.
*
* Based on:
* https://github.com/node-fetch/node-fetch/blob/main/src/utils/multipart-parser.js (MIT)
*/
class MultipartFormDataParser {
/**
* Returns form data.
*
* @param window Window.
* @param body Body.
* @param contentType Content type header value.
* @returns Form data.
*/
static async streamToFormData(window, body, contentType) {
if (!/multipart/i.test(contentType)) {
throw new window.DOMException(`Failed to build FormData object: The "content-type" header isn't of type "multipart/form-data".`, DOMExceptionNameEnum_js_1.default.invalidStateError);
}
const match = contentType.match(/boundary=(?:"([^"]+)"|([^;]+))/i);
if (!match) {
throw new window.DOMException(`Failed to build FormData object: The "content-type" header doesn't contain any multipart boundary.`, DOMExceptionNameEnum_js_1.default.invalidStateError);
}
const bodyReader = body.getReader();
const reader = new MultipartReader_js_1.default(window, match[1] || match[2]);
const chunks = [];
let buffer;
const bytes = 0;
let readResult = await bodyReader.read();
while (!readResult.done) {
if (body[PropertySymbol.error]) {
throw body[PropertySymbol.error];
}
if (body[PropertySymbol.aborted]) {
throw new window.DOMException('Failed to read response body: The stream was aborted.', DOMExceptionNameEnum_js_1.default.abortError);
}
reader.write(readResult.value);
readResult = await bodyReader.read();
}
try {
buffer =
typeof chunks[0] === 'string' ? buffer_1.Buffer.from(chunks.join('')) : buffer_1.Buffer.concat(chunks, bytes);
}
catch (error) {
throw new window.DOMException(`Could not create Buffer from response body. Error: ${error.message}.`, DOMExceptionNameEnum_js_1.default.invalidStateError);
}
return {
formData: reader.end(),
buffer
};
}
/**
* Converts a FormData object to a ReadableStream.
*
* @param formData FormData.
* @returns Stream and type.
*/
static formDataToStream(formData) {
const boundary = '----HappyDOMFormDataBoundary' + Math.random().toString(36);
const chunks = [];
const prefix = `--${boundary}\r\nContent-Disposition: form-data; name="`;
for (const [name, value] of formData) {
if (typeof value === 'string') {
chunks.push(buffer_1.Buffer.from(`${prefix}${this.escapeName(name)}"\r\n\r\n${value.replace(/\r(?!\n)|(?<!\r)\n/g, '\r\n')}\r\n`));
}
else {
chunks.push(buffer_1.Buffer.from(`${prefix}${this.escapeName(name)}"; filename="${this.escapeName(value.name, true)}"\r\nContent-Type: ${value.type || 'application/octet-stream'}\r\n\r\n`));
chunks.push(value[PropertySymbol.buffer]);
chunks.push(buffer_1.Buffer.from('\r\n'));
}
}
// add end boundary
chunks.push(buffer_1.Buffer.from(`--${boundary}--\r\n`));
const buffer = buffer_1.Buffer.concat(chunks);
return {
contentType: `multipart/form-data; boundary=${boundary}`,
contentLength: buffer.length,
buffer,
stream: new web_1.ReadableStream({
start(controller) {
controller.enqueue(buffer);
controller.close();
}
})
};
}
/**
* Escapes a form data entry name.
*
* @param name Name.
* @param filename Whether it is a filename.
* @returns Escaped name.
*/
static escapeName(name, filename = false) {
return (filename ? name : name.replace(/\r?\n|\r/g, '\r\n'))
.replace(/\n/g, '%0A')
.replace(/\r/g, '%0D')
.replace(/"/g, '%22');
}
}
exports.default = MultipartFormDataParser;
//# sourceMappingURL=MultipartFormDataParser.cjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"MultipartFormDataParser.cjs","sourceRoot":"","sources":["../../../src/fetch/multipart/MultipartFormDataParser.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,45 @@
import FormData from '../../form-data/FormData.cjs';
import { ReadableStream } from 'stream/web';
import { Buffer } from 'buffer';
import BrowserWindow from '../../window/BrowserWindow.cjs';
/**
* Multipart form data factory.
*
* Based on:
* https://github.com/node-fetch/node-fetch/blob/main/src/utils/multipart-parser.js (MIT)
*/
export default class MultipartFormDataParser {
/**
* Returns form data.
*
* @param window Window.
* @param body Body.
* @param contentType Content type header value.
* @returns Form data.
*/
static streamToFormData(window: BrowserWindow, body: ReadableStream, contentType: string): Promise<{
formData: FormData;
buffer: Buffer;
}>;
/**
* Converts a FormData object to a ReadableStream.
*
* @param formData FormData.
* @returns Stream and type.
*/
static formDataToStream(formData: FormData): {
contentType: string;
contentLength: number;
buffer: Buffer;
stream: ReadableStream;
};
/**
* Escapes a form data entry name.
*
* @param name Name.
* @param filename Whether it is a filename.
* @returns Escaped name.
*/
private static escapeName;
}
//# sourceMappingURL=MultipartFormDataParser.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"MultipartFormDataParser.d.ts","sourceRoot":"","sources":["../../../src/fetch/multipart/MultipartFormDataParser.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,6BAA6B,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAI5C,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,aAAa,MAAM,+BAA+B,CAAC;AAE1D;;;;;GAKG;AACH,MAAM,CAAC,OAAO,OAAO,uBAAuB;IAC3C;;;;;;;OAOG;WACiB,gBAAgB,CACnC,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,cAAc,EACpB,WAAW,EAAE,MAAM,GACjB,OAAO,CAAC;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAuDlD;;;;;OAKG;WACW,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG;QACnD,WAAW,EAAE,MAAM,CAAC;QACpB,aAAa,EAAE,MAAM,CAAC;QACtB,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,cAAc,CAAC;KACvB;IA+CD;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,UAAU;CAMzB"}

View File

@@ -0,0 +1,180 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const File_js_1 = __importDefault(require("../../file/File.cjs"));
var MultipartParserStateEnum;
(function (MultipartParserStateEnum) {
MultipartParserStateEnum[MultipartParserStateEnum["boundary"] = 0] = "boundary";
MultipartParserStateEnum[MultipartParserStateEnum["headerStart"] = 2] = "headerStart";
MultipartParserStateEnum[MultipartParserStateEnum["header"] = 3] = "header";
MultipartParserStateEnum[MultipartParserStateEnum["data"] = 5] = "data";
})(MultipartParserStateEnum || (MultipartParserStateEnum = {}));
const CHARACTER_CODE = {
lf: 10,
cr: 13
};
/**
* Multipart reader.
*
* Based on:
* https://github.com/node-fetch/node-fetch/blob/main/src/utils/multipart-parser.js (MIT)
*/
class MultipartReader {
formData;
boundary;
boundaryIndex = 0;
state = MultipartParserStateEnum.boundary;
data = {
contentDisposition: null,
value: [],
contentType: null,
header: ''
};
/**
* Constructor.
*
* @param window Window.
* @param formData Form data.
* @param boundary Boundary.
*/
constructor(window, boundary) {
const boundaryHeader = `--${boundary}`;
this.boundary = new Uint8Array(boundaryHeader.length);
this.formData = new window.FormData();
for (let i = 0, max = boundaryHeader.length; i < max; i++) {
this.boundary[i] = boundaryHeader.charCodeAt(i);
}
}
/**
* Appends data.
*
* @param data Data.
*/
write(data) {
let char;
let nextChar;
for (let i = 0, max = data.length; i < max; i++) {
char = data[i];
nextChar = data[i + 1];
switch (this.state) {
case MultipartParserStateEnum.boundary:
if (char === this.boundary[this.boundaryIndex]) {
this.boundaryIndex++;
}
else {
this.boundaryIndex = 0;
}
if (this.boundaryIndex === this.boundary.length) {
this.state = MultipartParserStateEnum.headerStart;
this.boundaryIndex = 0;
}
break;
case MultipartParserStateEnum.headerStart:
if (nextChar !== CHARACTER_CODE.cr && nextChar !== CHARACTER_CODE.lf) {
this.data.header = '';
this.state =
data[i - 2] === CHARACTER_CODE.lf
? MultipartParserStateEnum.data
: MultipartParserStateEnum.header;
}
break;
case MultipartParserStateEnum.header:
if (char === CHARACTER_CODE.cr) {
if (this.data.header) {
const headerParts = this.data.header.split(':');
if (headerParts.length > 1) {
const headerName = headerParts[0].toLowerCase();
const headerValue = headerParts[1].trim();
switch (headerName) {
case 'content-disposition':
this.data.contentDisposition = this.getContentDisposition(headerValue);
break;
case 'content-type':
this.data.contentType = headerValue;
break;
}
}
}
this.state = MultipartParserStateEnum.headerStart;
}
else {
this.data.header += String.fromCharCode(char);
}
break;
case MultipartParserStateEnum.data:
if (char === this.boundary[this.boundaryIndex]) {
this.boundaryIndex++;
}
else {
this.boundaryIndex = 0;
}
if (this.boundaryIndex === this.boundary.length) {
this.state = MultipartParserStateEnum.headerStart;
if (this.data.value.length) {
this.appendFormData(this.data.contentDisposition.name, Buffer.from(this.data.value.slice(0, -(this.boundary.length + 1))), this.data.contentDisposition.filename, this.data.contentType);
this.data.value = [];
this.data.contentDisposition = null;
this.data.contentType = null;
}
this.boundaryIndex = 0;
}
else {
this.data.value.push(char);
}
break;
}
}
}
/**
* Ends the stream.
*
* @returns Form data.
*/
end() {
// If we are missing an end boundary, but we have data, we should append it.
if (this.data.contentDisposition && this.data.value.length) {
this.appendFormData(this.data.contentDisposition.name, Buffer.from(this.data.value.slice(0, -2)), this.data.contentDisposition.filename, this.data.contentType);
}
return this.formData;
}
/**
* Appends data.
*
* @param key Key.
* @param value value.
* @param filename Filename.
* @param type Type.
*/
appendFormData(key, value, filename, type) {
if (!value.length) {
return;
}
if (filename) {
this.formData.append(key, new File_js_1.default([value], filename, {
type
}));
}
else {
this.formData.append(key, value.toString());
}
}
/**
* Returns content disposition.
*
* @param headerValue Header value.
* @returns Content disposition.
*/
getContentDisposition(headerValue) {
const regex = /([a-z]+) *= *"([^"]+)"/g;
const contentDisposition = {};
let match;
while ((match = regex.exec(headerValue))) {
contentDisposition[match[1]] = match[2];
}
return contentDisposition;
}
}
exports.default = MultipartReader;
//# sourceMappingURL=MultipartReader.cjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"MultipartReader.cjs","sourceRoot":"","sources":["../../../src/fetch/multipart/MultipartReader.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,52 @@
import FormData from '../../form-data/FormData.cjs';
import BrowserWindow from '../../window/BrowserWindow.cjs';
/**
* Multipart reader.
*
* Based on:
* https://github.com/node-fetch/node-fetch/blob/main/src/utils/multipart-parser.js (MIT)
*/
export default class MultipartReader {
private formData;
private boundary;
private boundaryIndex;
private state;
private data;
/**
* Constructor.
*
* @param window Window.
* @param formData Form data.
* @param boundary Boundary.
*/
constructor(window: BrowserWindow, boundary: string);
/**
* Appends data.
*
* @param data Data.
*/
write(data: Uint8Array): void;
/**
* Ends the stream.
*
* @returns Form data.
*/
end(): FormData;
/**
* Appends data.
*
* @param key Key.
* @param value value.
* @param filename Filename.
* @param type Type.
*/
private appendFormData;
/**
* Returns content disposition.
*
* @param headerValue Header value.
* @returns Content disposition.
*/
private getContentDisposition;
}
//# sourceMappingURL=MultipartReader.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"MultipartReader.d.ts","sourceRoot":"","sources":["../../../src/fetch/multipart/MultipartReader.ts"],"names":[],"mappings":"AACA,OAAO,QAAQ,MAAM,6BAA6B,CAAC;AACnD,OAAO,aAAa,MAAM,+BAA+B,CAAC;AAc1D;;;;;GAKG;AACH,MAAM,CAAC,OAAO,OAAO,eAAe;IACnC,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,QAAQ,CAAa;IAC7B,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,KAAK,CAAqC;IAClD,OAAO,CAAC,IAAI,CAUV;IAEF;;;;;;OAMG;gBACS,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM;IAUnD;;;;OAIG;IACI,KAAK,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI;IA6FpC;;;;OAIG;IACI,GAAG,IAAI,QAAQ;IActB;;;;;;;OAOG;IACH,OAAO,CAAC,cAAc;IAiBtB;;;;;OAKG;IACH,OAAO,CAAC,qBAAqB;CAW7B"}

View File

@@ -0,0 +1,44 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Preload entry.
*
* @see https://html.spec.whatwg.org/multipage/links.html#preload-entry
*/
class PreloadEntry {
integrityMetadata = null;
response = null;
error = null;
#callback = null;
/**
* On response available.
*
* @returns Response.
*/
onResponseAvailable() {
return new Promise((resolve, reject) => {
this.#callback = { resolve, reject };
});
}
/**
* Response available.
*
* @param error
* @param response
*/
responseAvailable(error, response) {
this.response = response;
this.error = error;
if (!this.#callback) {
return;
}
if (error) {
this.#callback.reject(error);
}
else {
this.#callback.resolve(response);
}
}
}
exports.default = PreloadEntry;
//# sourceMappingURL=PreloadEntry.cjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"PreloadEntry.cjs","sourceRoot":"","sources":["../../../src/fetch/preload/PreloadEntry.ts"],"names":[],"mappings":";;AAEA;;;;GAIG;AACH,MAAqB,YAAY;IACzB,iBAAiB,GAAkB,IAAI,CAAC;IACxC,QAAQ,GAAoB,IAAI,CAAC;IACjC,KAAK,GAAiB,IAAI,CAAC;IAClC,SAAS,GACR,IAAI,CAAC;IAEN;;;;OAIG;IACI,mBAAmB;QACzB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACtC,IAAI,CAAC,SAAS,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QACtC,CAAC,CAAC,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACI,iBAAiB,CAAC,KAAmB,EAAE,QAAkB;QAC/D,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QAEnB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACrB,OAAO;QACR,CAAC;QAED,IAAI,KAAK,EAAE,CAAC;YACX,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAClC,CAAC;IACF,CAAC;CACD;AAtCD,+BAsCC"}

View File

@@ -0,0 +1,26 @@
import Response from '../Response.cjs';
/**
* Preload entry.
*
* @see https://html.spec.whatwg.org/multipage/links.html#preload-entry
*/
export default class PreloadEntry {
#private;
integrityMetadata: string | null;
response: Response | null;
error: Error | null;
/**
* On response available.
*
* @returns Response.
*/
onResponseAvailable(): Promise<Response>;
/**
* Response available.
*
* @param error
* @param response
*/
responseAvailable(error: Error | null, response: Response): void;
}
//# sourceMappingURL=PreloadEntry.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"PreloadEntry.d.ts","sourceRoot":"","sources":["../../../src/fetch/preload/PreloadEntry.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,YAAY;;IACzB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAQ;IACxC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAQ;IACjC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAQ;IAIlC;;;;OAIG;IACI,mBAAmB,IAAI,OAAO,CAAC,QAAQ,CAAC;IAM/C;;;;;OAKG;IACI,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI;CAcvE"}

View File

@@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Utility for preloading resources.
*
* @see https://html.spec.whatwg.org/multipage/links.html#link-type-preload
*/
class PreloadUtility {
/**
* Returns a key for a preload entry.
*
* @param options Options.
* @param options.url URL.
* @param options.destination Destination.
* @param options.mode Mode.
* @param options.credentialsMode Credentials mode.
* @returns Key.
*/
static getKey(options) {
return JSON.stringify({
url: options.url,
destination: options.destination,
mode: options.mode,
credentialsMode: options.credentialsMode
});
}
}
exports.default = PreloadUtility;
//# sourceMappingURL=PreloadUtility.cjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"PreloadUtility.cjs","sourceRoot":"","sources":["../../../src/fetch/preload/PreloadUtility.ts"],"names":[],"mappings":";;AAGA;;;;GAIG;AACH,MAAqB,cAAc;IAClC;;;;;;;;;OASG;IACI,MAAM,CAAC,MAAM,CAAC,OAKpB;QACA,OAAO,IAAI,CAAC,SAAS,CAAC;YACrB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,eAAe,EAAE,OAAO,CAAC,eAAe;SACxC,CAAC,CAAC;IACJ,CAAC;CACD;AAxBD,iCAwBC"}

View File

@@ -0,0 +1,26 @@
import IRequestCredentials from '../types/IRequestCredentials.cjs';
import IRequestMode from '../types/IRequestMode.cjs';
/**
* Utility for preloading resources.
*
* @see https://html.spec.whatwg.org/multipage/links.html#link-type-preload
*/
export default class PreloadUtility {
/**
* Returns a key for a preload entry.
*
* @param options Options.
* @param options.url URL.
* @param options.destination Destination.
* @param options.mode Mode.
* @param options.credentialsMode Credentials mode.
* @returns Key.
*/
static getKey(options: {
url: string;
destination: string;
mode: IRequestMode;
credentialsMode: IRequestCredentials;
}): string;
}
//# sourceMappingURL=PreloadUtility.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"PreloadUtility.d.ts","sourceRoot":"","sources":["../../../src/fetch/preload/PreloadUtility.ts"],"names":[],"mappings":"AAAA,OAAO,mBAAmB,MAAM,iCAAiC,CAAC;AAClE,OAAO,YAAY,MAAM,0BAA0B,CAAC;AAEpD;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,cAAc;IAClC;;;;;;;;;OASG;WACW,MAAM,CAAC,OAAO,EAAE;QAC7B,GAAG,EAAE,MAAM,CAAC;QACZ,WAAW,EAAE,MAAM,CAAC;QACpB,IAAI,EAAE,YAAY,CAAC;QACnB,eAAe,EAAE,mBAAmB,CAAC;KACrC,GAAG,MAAM;CAQV"}

Some files were not shown because too many files have changed in this diff Show More