Next.js website for Rocky Mountain Vending company featuring: - Product catalog with Stripe integration - Service areas and parts pages - Admin dashboard with Clerk authentication - SEO optimized pages with JSON-LD structured data Co-authored-by: Cursor <cursoragent@cursor.com>
149 lines
No EOL
6.7 KiB
Text
149 lines
No EOL
6.7 KiB
Text
/*
|
|
* Copyright 2025 Google LLC.
|
|
* Copyright (c) Microsoft Corporation.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
import { InvalidArgumentException, NoSuchNetworkCollectorException, UnsupportedOperationException, } from '../../../protocol/ErrorResponse.js';
|
|
import { LogType } from '../../../utils/log.js';
|
|
import { uuidv4 } from '../../../utils/uuid.js';
|
|
export class CollectorsStorage {
|
|
#collectors = new Map();
|
|
#responseCollectors = new Map();
|
|
#requestBodyCollectors = new Map();
|
|
#maxEncodedDataSize;
|
|
#logger;
|
|
constructor(maxEncodedDataSize, logger) {
|
|
this.#maxEncodedDataSize = maxEncodedDataSize;
|
|
this.#logger = logger;
|
|
}
|
|
addDataCollector(params) {
|
|
if (params.maxEncodedDataSize < 1 ||
|
|
params.maxEncodedDataSize > this.#maxEncodedDataSize) {
|
|
// 200 MB is the default limit in CDP:
|
|
// https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/inspector/inspector_network_agent.cc;drc=da1f749634c9a401cc756f36c2e6ce233e1c9b4d;l=133
|
|
throw new InvalidArgumentException(`Max encoded data size should be between 1 and ${this.#maxEncodedDataSize}`);
|
|
}
|
|
const collectorId = uuidv4();
|
|
this.#collectors.set(collectorId, params);
|
|
return collectorId;
|
|
}
|
|
isCollected(requestId, dataType, collectorId) {
|
|
if (collectorId !== undefined && !this.#collectors.has(collectorId)) {
|
|
throw new NoSuchNetworkCollectorException(`Unknown collector ${collectorId}`);
|
|
}
|
|
if (dataType === undefined) {
|
|
return (this.isCollected(requestId, "response" /* Network.DataType.Response */, collectorId) ||
|
|
this.isCollected(requestId, "request" /* Network.DataType.Request */, collectorId));
|
|
}
|
|
const requestToCollectorsMap = this.#getRequestToCollectorMap(dataType).get(requestId);
|
|
if (requestToCollectorsMap === undefined ||
|
|
requestToCollectorsMap.size === 0) {
|
|
return false;
|
|
}
|
|
if (collectorId === undefined) {
|
|
// There is at least 1 collector for the data.
|
|
return true;
|
|
}
|
|
if (!requestToCollectorsMap.has(collectorId)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
#getRequestToCollectorMap(dataType) {
|
|
switch (dataType) {
|
|
case "response" /* Network.DataType.Response */:
|
|
return this.#responseCollectors;
|
|
case "request" /* Network.DataType.Request */:
|
|
return this.#requestBodyCollectors;
|
|
default:
|
|
throw new UnsupportedOperationException(`Unsupported data type ${dataType}`);
|
|
}
|
|
}
|
|
disownData(requestId, dataType, collectorId) {
|
|
const requestToCollectorsMap = this.#getRequestToCollectorMap(dataType);
|
|
if (collectorId !== undefined) {
|
|
requestToCollectorsMap.get(requestId)?.delete(collectorId);
|
|
}
|
|
if (collectorId === undefined ||
|
|
requestToCollectorsMap.get(requestId)?.size === 0) {
|
|
requestToCollectorsMap.delete(requestId);
|
|
}
|
|
}
|
|
#shouldCollectRequest(collectorId, request, dataType, topLevelBrowsingContext, userContext) {
|
|
const collector = this.#collectors.get(collectorId);
|
|
if (collector === undefined) {
|
|
throw new NoSuchNetworkCollectorException(`Unknown collector ${collectorId}`);
|
|
}
|
|
if (collector.userContexts &&
|
|
!collector.userContexts.includes(userContext)) {
|
|
// Collector is aimed for a different user context.
|
|
return false;
|
|
}
|
|
if (collector.contexts &&
|
|
!collector.contexts.includes(topLevelBrowsingContext)) {
|
|
// Collector is aimed for a different top-level browsing context.
|
|
return false;
|
|
}
|
|
if (!collector.dataTypes.includes(dataType)) {
|
|
// Collector is aimed for a different data type.
|
|
return false;
|
|
}
|
|
if (dataType === "request" /* Network.DataType.Request */ &&
|
|
request.bodySize > collector.maxEncodedDataSize) {
|
|
this.#logger?.(LogType.debug, `Request's ${request.id} body size is too big for the collector ${collectorId}`);
|
|
return false;
|
|
}
|
|
if (dataType === "response" /* Network.DataType.Response */ &&
|
|
request.bytesReceived > collector.maxEncodedDataSize) {
|
|
this.#logger?.(LogType.debug, `Request's ${request.id} response is too big for the collector ${collectorId}`);
|
|
return false;
|
|
}
|
|
this.#logger?.(LogType.debug, `Collector ${collectorId} collected ${dataType} of ${request.id}`);
|
|
return true;
|
|
}
|
|
collectIfNeeded(request, dataType, topLevelBrowsingContext, userContext) {
|
|
const collectorIds = [...this.#collectors.keys()].filter((collectorId) => this.#shouldCollectRequest(collectorId, request, dataType, topLevelBrowsingContext, userContext));
|
|
if (collectorIds.length > 0) {
|
|
this.#getRequestToCollectorMap(dataType).set(request.id, new Set(collectorIds));
|
|
}
|
|
}
|
|
removeDataCollector(collectorId) {
|
|
if (!this.#collectors.has(collectorId)) {
|
|
throw new NoSuchNetworkCollectorException(`Collector ${collectorId} does not exist`);
|
|
}
|
|
this.#collectors.delete(collectorId);
|
|
const affectedRequests = [];
|
|
// Clean up collected responses.
|
|
for (const [requestId, collectorIds] of this.#responseCollectors) {
|
|
if (collectorIds.has(collectorId)) {
|
|
collectorIds.delete(collectorId);
|
|
if (collectorIds.size === 0) {
|
|
this.#responseCollectors.delete(requestId);
|
|
affectedRequests.push(requestId);
|
|
}
|
|
}
|
|
}
|
|
for (const [requestId, collectorIds] of this.#requestBodyCollectors) {
|
|
if (collectorIds.has(collectorId)) {
|
|
collectorIds.delete(collectorId);
|
|
if (collectorIds.size === 0) {
|
|
this.#requestBodyCollectors.delete(requestId);
|
|
affectedRequests.push(requestId);
|
|
}
|
|
}
|
|
}
|
|
return affectedRequests;
|
|
}
|
|
}
|
|
//# sourceMappingURL=CollectorsStorage.js.map |