iframe-connect
Version:
A lightweight, type-safe cross-frame communication library with plugin system and multi-window isolation
322 lines (318 loc) • 10.1 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __objRest = (source, exclude) => {
var target = {};
for (var prop in source)
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
target[prop] = source[prop];
if (source != null && __getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(source)) {
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
target[prop] = source[prop];
}
return target;
};
// src/plugins/logger.ts
var Logger = class {
constructor(bridge, options = {}) {
this.bridge = bridge;
this.options = __spreadValues({
prefix: "[CrossFrame]",
timestamp: true,
colors: true,
level: "debug"
}, options);
this.setupLogging();
}
setupLogging() {
const originalSend = this.bridge.send.bind(this.bridge);
this.bridge.send = (type, payload) => {
this.log("info", "\u53D1\u9001\u6D88\u606F:", { type, payload });
return originalSend(type, payload);
};
const originalRequest = this.bridge.request.bind(this.bridge);
this.bridge.request = async (type, payload) => {
this.log("info", "\u53D1\u9001\u8BF7\u6C42:", { type, payload });
try {
const result = await originalRequest(type, payload);
this.log("info", "\u8BF7\u6C42\u6210\u529F:", { type, result });
return result;
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
this.log("error", "\u8BF7\u6C42\u5931\u8D25:", { type, error: errorMessage });
throw error;
}
};
}
log(level, message, data) {
if (!this.shouldLog(level)) return;
const timestamp = this.options.timestamp ? `[${(/* @__PURE__ */ new Date()).toISOString()}]` : "";
const prefix = this.options.prefix;
const coloredMessage = this.options.colors ? this.colorize(level, message) : message;
console.log(`${timestamp} ${prefix} ${coloredMessage}`, data || "");
}
shouldLog(level) {
const levels = ["debug", "info", "warn", "error"];
const currentLevelIndex = levels.indexOf(this.options.level);
const messageLevelIndex = levels.indexOf(level);
return messageLevelIndex >= currentLevelIndex;
}
colorize(level, message) {
if (!this.options.colors) return message;
const colors = {
debug: "\x1B[36m",
// cyan
info: "\x1B[32m",
// green
warn: "\x1B[33m",
// yellow
error: "\x1B[31m",
// red
reset: "\x1B[0m"
};
return `${colors[level] || ""}${message}${colors.reset}`;
}
};
function createLogger(bridge, options) {
return new Logger(bridge, options);
}
// src/plugins/retry.ts
var RetryManager = class {
constructor(bridge, options = {}) {
this.bridge = bridge;
this.options = __spreadValues({
maxRetries: 3,
baseDelay: 1e3,
maxDelay: 1e4,
backoff: "exponential",
retryCondition: (error) => error.message.includes("timeout")
}, options);
this.setupRetry();
}
setupRetry() {
const originalRequest = this.bridge.request.bind(this.bridge);
this.bridge.request = async (type, payload) => {
return this.requestWithRetry(originalRequest, type, payload);
};
}
async requestWithRetry(originalRequest, type, payload) {
let lastError;
for (let attempt = 0; attempt <= this.options.maxRetries; attempt++) {
try {
return await originalRequest(type, payload);
} catch (error) {
lastError = error instanceof Error ? error : new Error(String(error));
if (!this.options.retryCondition(lastError)) {
throw lastError;
}
if (attempt === this.options.maxRetries) {
throw lastError;
}
const delay = this.calculateDelay(attempt);
console.warn(
`[CrossFrame] \u8BF7\u6C42\u5931\u8D25\uFF0C${delay}ms \u540E\u91CD\u8BD5 (${attempt + 1}/${this.options.maxRetries})`
);
await this.sleep(delay);
}
}
throw lastError;
}
calculateDelay(attempt) {
let delay;
if (this.options.backoff === "linear") {
delay = this.options.baseDelay * (attempt + 1);
} else {
delay = this.options.baseDelay * Math.pow(2, attempt);
}
return Math.min(delay, this.options.maxDelay);
}
sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
// 手动重试方法
async retryRequest(type, payload, customOptions) {
const options = __spreadValues(__spreadValues({}, this.options), customOptions);
for (let attempt = 0; attempt <= options.maxRetries; attempt++) {
try {
return await this.bridge.request(type, payload);
} catch (error) {
const err = error instanceof Error ? error : new Error(String(error));
if (!options.retryCondition(err) || attempt === options.maxRetries) {
throw err;
}
const delay = this.calculateDelayWithOptions(attempt, options);
await this.sleep(delay);
}
}
throw new Error("Retry failed");
}
calculateDelayWithOptions(attempt, options) {
let delay;
if (options.backoff === "linear") {
delay = options.baseDelay * (attempt + 1);
} else {
delay = options.baseDelay * Math.pow(2, attempt);
}
return Math.min(delay, options.maxDelay);
}
};
function createRetryManager(bridge, options) {
return new RetryManager(bridge, options);
}
// src/plugins/queue-manager.ts
var QueueManager = class {
constructor(bridge, options = {}) {
this.messageQueue = [];
this.processing = false;
this.bridge = bridge;
this.options = __spreadValues({
maxSize: 100,
flushInterval: 1e3,
batchSize: 10,
priority: false
}, options);
this.setupQueue();
this.startFlushTimer();
}
setupQueue() {
this.bridge.send.bind(this.bridge);
this.bridge.send = (type, payload) => {
this.enqueue({
type,
payload,
timestamp: Date.now()
});
};
this.bridge.request.bind(this.bridge);
this.bridge.request = (type, payload, requestTimeout) => {
return new Promise((resolve, reject) => {
this.enqueue({
type,
payload,
timestamp: Date.now(),
resolve,
reject,
requestTimeout
});
});
};
}
enqueue(message) {
if (this.messageQueue.length >= this.options.maxSize) {
const error = new Error("\u6D88\u606F\u961F\u5217\u5DF2\u6EE1");
if (message.reject) {
message.reject(error);
} else {
console.warn("[CrossFrame] \u6D88\u606F\u961F\u5217\u5DF2\u6EE1\uFF0C\u4E22\u5F03\u6D88\u606F:", message);
}
return;
}
this.messageQueue.push(message);
if (this.options.priority) {
this.messageQueue.sort((a, b) => (b.priority || 0) - (a.priority || 0));
}
if (this.messageQueue.length >= this.options.batchSize) {
this.flush();
}
}
startFlushTimer() {
this.flushTimer = setInterval(() => {
if (this.messageQueue.length > 0) {
this.flush();
}
}, this.options.flushInterval);
}
async flush() {
if (this.processing || this.messageQueue.length === 0) {
return;
}
this.processing = true;
const batch = this.messageQueue.splice(0, this.options.batchSize);
try {
for (const message of batch) {
try {
if (message.resolve) {
const result = await this.bridge.request(
message.type,
message.payload,
message.requestTimeout
);
message.resolve(result);
} else {
this.bridge.send(message.type, message.payload);
}
} catch (error) {
if (message.reject) {
message.reject(
error instanceof Error ? error : new Error(String(error))
);
} else {
console.error("[CrossFrame] \u6D88\u606F\u5904\u7406\u5931\u8D25:", error);
}
}
}
} finally {
this.processing = false;
}
}
// 手动刷新队列
async flushNow() {
return this.flush();
}
// 设置消息优先级
setPriority(type, payload, priority) {
this.enqueue({
type,
payload,
priority,
timestamp: Date.now()
});
}
// 获取队列状态
getQueueStatus() {
return {
size: this.messageQueue.length,
maxSize: this.options.maxSize,
processing: this.processing,
usage: this.messageQueue.length / this.options.maxSize * 100
};
}
// 清空队列
clear() {
const rejectedCount = this.messageQueue.filter((msg) => msg.reject).length;
this.messageQueue.forEach((msg) => {
if (msg.reject) {
msg.reject(new Error("\u961F\u5217\u5DF2\u6E05\u7A7A"));
}
});
this.messageQueue = [];
console.log(`[CrossFrame] \u961F\u5217\u5DF2\u6E05\u7A7A\uFF0C${rejectedCount} \u4E2A\u8BF7\u6C42\u88AB\u62D2\u7EDD`);
}
// 销毁队列管理器
destroy() {
if (this.flushTimer) {
clearInterval(this.flushTimer);
}
this.clear();
}
};
function createQueueManager(bridge, options) {
return new QueueManager(bridge, options);
}
export { Logger, QueueManager, RetryManager, __objRest, __spreadValues, createLogger, createQueueManager, createRetryManager };
//# sourceMappingURL=chunk-JI2PIO5G.mjs.map
//# sourceMappingURL=chunk-JI2PIO5G.mjs.map