@shuffleio/shuffle-mcps 0.0.33 → 0.0.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{appsCache-KWDP7F2K.mjs → appsCache-PP55YC62.mjs} +1 -1
- package/dist/{chunk-B4JFC2JU.mjs → chunk-5B3Q2RHS.mjs} +54 -30
- package/dist/index.d.mts +300 -90
- package/dist/index.d.ts +300 -90
- package/dist/index.js +7096 -2470
- package/dist/index.mjs +7303 -2637
- package/dist/{shuffle-mcp-TWJGPBOQ.css → shuffle-mcp-3U5AFQDK.css} +32 -5
- package/package.json +1 -1
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// fetchBreaker.ts
|
|
2
2
|
var FAIL_THRESHOLD = 12;
|
|
3
3
|
var ROLLING_WINDOW_MS = 5e3;
|
|
4
|
-
var COOLDOWN_MS =
|
|
4
|
+
var COOLDOWN_MS = 1e4;
|
|
5
|
+
var PROBE_AFTER_MS = 1500;
|
|
6
|
+
var MAX_PROBE_BACKOFF_MS = 5e3;
|
|
5
7
|
var HARD_BURST_THRESHOLD = 30;
|
|
6
8
|
var HARD_BURST_WINDOW_MS = 1e3;
|
|
7
9
|
var state = /* @__PURE__ */ new Map();
|
|
@@ -10,11 +12,24 @@ var allowedOrigins = /* @__PURE__ */ new Set();
|
|
|
10
12
|
var getEntry = (key) => {
|
|
11
13
|
let entry = state.get(key);
|
|
12
14
|
if (!entry) {
|
|
13
|
-
entry = { failures: [], attempts: [], blockedUntil: 0, warned: false };
|
|
15
|
+
entry = { failures: [], attempts: [], blockedUntil: 0, probeAfter: 0, probing: false, warned: false };
|
|
14
16
|
state.set(key, entry);
|
|
15
17
|
}
|
|
16
18
|
return entry;
|
|
17
19
|
};
|
|
20
|
+
var trip = (entry, now, cooldownMs = COOLDOWN_MS) => {
|
|
21
|
+
entry.blockedUntil = now + cooldownMs;
|
|
22
|
+
entry.probeAfter = now + PROBE_AFTER_MS;
|
|
23
|
+
entry.probing = false;
|
|
24
|
+
};
|
|
25
|
+
var reset = (entry) => {
|
|
26
|
+
entry.failures.length = 0;
|
|
27
|
+
entry.attempts.length = 0;
|
|
28
|
+
entry.blockedUntil = 0;
|
|
29
|
+
entry.probeAfter = 0;
|
|
30
|
+
entry.probing = false;
|
|
31
|
+
entry.warned = false;
|
|
32
|
+
};
|
|
18
33
|
var prune = (arr, now, windowMs) => {
|
|
19
34
|
const cutoff = now - windowMs;
|
|
20
35
|
while (arr.length && arr[0] < cutoff) arr.shift();
|
|
@@ -64,21 +79,35 @@ var installFetchBreaker = () => {
|
|
|
64
79
|
if (!key) return original(input, init);
|
|
65
80
|
const entry = getEntry(key);
|
|
66
81
|
const now = Date.now();
|
|
82
|
+
let isProbe = false;
|
|
67
83
|
if (entry.blockedUntil > now) {
|
|
68
|
-
|
|
84
|
+
if (!entry.probing && now >= entry.probeAfter) {
|
|
85
|
+
entry.probing = true;
|
|
86
|
+
isProbe = true;
|
|
87
|
+
} else {
|
|
88
|
+
return synthetic503(key, entry.blockedUntil - now);
|
|
89
|
+
}
|
|
69
90
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
entry.
|
|
74
|
-
|
|
75
|
-
entry.warned
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
91
|
+
if (!isProbe) {
|
|
92
|
+
entry.attempts.push(now);
|
|
93
|
+
prune(entry.attempts, now, HARD_BURST_WINDOW_MS);
|
|
94
|
+
if (entry.attempts.length > HARD_BURST_THRESHOLD) {
|
|
95
|
+
trip(entry, now);
|
|
96
|
+
if (!entry.warned) {
|
|
97
|
+
entry.warned = true;
|
|
98
|
+
console.error(
|
|
99
|
+
`[fetchBreaker] Burst detected on ${key} (${entry.attempts.length} calls / ${HARD_BURST_WINDOW_MS}ms). Blocking for up to ${COOLDOWN_MS / 1e3}s (probing again in ${PROBE_AFTER_MS / 1e3}s). Fix the caller \u2014 this is almost always a missing useEffect dep or a render loop.`
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
return synthetic503(key, COOLDOWN_MS);
|
|
79
103
|
}
|
|
80
|
-
return synthetic503(key, COOLDOWN_MS);
|
|
81
104
|
}
|
|
105
|
+
const onProbeFailure = (ts) => {
|
|
106
|
+
if (!isProbe) return;
|
|
107
|
+
entry.probing = false;
|
|
108
|
+
entry.probeAfter = ts + Math.min(MAX_PROBE_BACKOFF_MS, PROBE_AFTER_MS * 2);
|
|
109
|
+
entry.blockedUntil = Math.max(entry.blockedUntil, ts + PROBE_AFTER_MS);
|
|
110
|
+
};
|
|
82
111
|
let response;
|
|
83
112
|
try {
|
|
84
113
|
response = await original(input, init);
|
|
@@ -86,12 +115,13 @@ var installFetchBreaker = () => {
|
|
|
86
115
|
const ts = Date.now();
|
|
87
116
|
entry.failures.push(ts);
|
|
88
117
|
prune(entry.failures, ts, ROLLING_WINDOW_MS);
|
|
89
|
-
|
|
90
|
-
|
|
118
|
+
onProbeFailure(ts);
|
|
119
|
+
if (!isProbe && entry.failures.length >= FAIL_THRESHOLD) {
|
|
120
|
+
trip(entry, ts);
|
|
91
121
|
if (!entry.warned) {
|
|
92
122
|
entry.warned = true;
|
|
93
123
|
console.error(
|
|
94
|
-
`[fetchBreaker] ${entry.failures.length} network errors on ${key} in ${ROLLING_WINDOW_MS / 1e3}s. Blocking for ${COOLDOWN_MS / 1e3}s.`
|
|
124
|
+
`[fetchBreaker] ${entry.failures.length} network errors on ${key} in ${ROLLING_WINDOW_MS / 1e3}s. Blocking for up to ${COOLDOWN_MS / 1e3}s.`
|
|
95
125
|
);
|
|
96
126
|
}
|
|
97
127
|
}
|
|
@@ -101,18 +131,20 @@ var installFetchBreaker = () => {
|
|
|
101
131
|
const ts = Date.now();
|
|
102
132
|
entry.failures.push(ts);
|
|
103
133
|
prune(entry.failures, ts, ROLLING_WINDOW_MS);
|
|
104
|
-
|
|
105
|
-
|
|
134
|
+
onProbeFailure(ts);
|
|
135
|
+
if (!isProbe && entry.failures.length >= FAIL_THRESHOLD) {
|
|
136
|
+
trip(entry, ts);
|
|
106
137
|
if (!entry.warned) {
|
|
107
138
|
entry.warned = true;
|
|
108
139
|
console.error(
|
|
109
|
-
`[fetchBreaker] ${entry.failures.length} ${response.status}s on ${key} in ${ROLLING_WINDOW_MS / 1e3}s. Blocking for ${COOLDOWN_MS / 1e3}s.`
|
|
140
|
+
`[fetchBreaker] ${entry.failures.length} ${response.status}s on ${key} in ${ROLLING_WINDOW_MS / 1e3}s. Blocking for up to ${COOLDOWN_MS / 1e3}s.`
|
|
110
141
|
);
|
|
111
142
|
}
|
|
112
143
|
}
|
|
113
144
|
} else if (response.status < 400) {
|
|
114
|
-
entry
|
|
115
|
-
|
|
145
|
+
reset(entry);
|
|
146
|
+
} else {
|
|
147
|
+
if (isProbe) reset(entry);
|
|
116
148
|
}
|
|
117
149
|
return response;
|
|
118
150
|
});
|
|
@@ -134,7 +166,7 @@ var getEnvVar = (key) => {
|
|
|
134
166
|
var isDevEnvironment = () => {
|
|
135
167
|
if (getEnvVar("VITE_SHUFFLE_API_URL")) return false;
|
|
136
168
|
const hostname = typeof window !== "undefined" ? window.location.hostname : "";
|
|
137
|
-
return hostname.includes("lovableproject.com") || hostname.includes("id-preview--");
|
|
169
|
+
return hostname.includes("lovableproject.com") || hostname.includes("id-preview--") || hostname.endsWith(".lovable.app") || hostname.endsWith(".lovable.dev");
|
|
138
170
|
};
|
|
139
171
|
var isCloudDomain = () => {
|
|
140
172
|
const hostname = typeof window !== "undefined" ? window.location.hostname : "";
|
|
@@ -244,13 +276,6 @@ var API_CONFIG = {
|
|
|
244
276
|
var getApiUrl = (endpoint) => {
|
|
245
277
|
return `${API_CONFIG.baseUrl}${endpoint}`;
|
|
246
278
|
};
|
|
247
|
-
var getShuffleCoreFormUrl = (refUrl) => {
|
|
248
|
-
if (!refUrl) return refUrl;
|
|
249
|
-
if (/^https?:\/\//i.test(refUrl)) return refUrl;
|
|
250
|
-
const path = refUrl.startsWith("/") ? refUrl : `/${refUrl}`;
|
|
251
|
-
if (isCloud()) return `https://shuffler.io${path}`;
|
|
252
|
-
return `${API_CONFIG.baseUrl}${path}`;
|
|
253
|
-
};
|
|
254
279
|
var shuffleFetch = (url, init) => {
|
|
255
280
|
const { headers: extraHeaders, ...rest } = init || {};
|
|
256
281
|
return fetch(url, {
|
|
@@ -340,7 +365,6 @@ export {
|
|
|
340
365
|
getTrackedOrgId,
|
|
341
366
|
API_CONFIG,
|
|
342
367
|
getApiUrl,
|
|
343
|
-
getShuffleCoreFormUrl,
|
|
344
368
|
shuffleFetch,
|
|
345
369
|
getAuthHeader,
|
|
346
370
|
fetchApps,
|