@frontmcp/utils 1.8.7 → 1.9.1-rc.1
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/env/browser-env.d.ts +1 -0
- package/env/browser-env.js +5 -0
- package/env/browser-runtime-context.d.ts +2 -1
- package/env/browser-runtime-context.js +104 -0
- package/env/index.d.ts +1 -1
- package/env/node-env.d.ts +11 -0
- package/env/node-env.js +8 -2
- package/env/runtime-context.d.ts +7 -4
- package/env/runtime-context.js +192 -0
- package/esm/async-context/browser-async-context.mjs +1 -1
- package/esm/async-context/node-async-context.mjs +1 -1
- package/esm/crypto/browser.mjs +1 -1
- package/esm/crypto/node.mjs +1 -1
- package/esm/env/browser-env.mjs +5 -1
- package/esm/env/browser-runtime-context.mjs +77 -0
- package/esm/env/node-env.mjs +8 -3
- package/esm/env/runtime-context.mjs +172 -0
- package/esm/event-emitter/browser-event-emitter.mjs +1 -1
- package/esm/event-emitter/node-event-emitter.mjs +1 -1
- package/esm/index.mjs +188 -258
- package/esm/path/browser-path.mjs +50 -0
- package/esm/path/node-path.mjs +16 -0
- package/index.d.ts +1 -1
- package/index.js +197 -283
- package/package.json +27 -9
- package/path/browser-path.js +79 -0
- package/path/node-path.js +45 -0
- package/storage/adapters/base.d.ts +6 -1
- package/storage/adapters/cloudflare-kv.d.ts +1 -0
- package/storage/adapters/memory.d.ts +2 -1
- package/storage/adapters/redis.d.ts +1 -0
- package/storage/adapters/upstash.d.ts +2 -1
- package/storage/adapters/vercel-kv.d.ts +2 -1
- package/storage/namespace.d.ts +2 -1
- package/storage/types.d.ts +11 -0
- package/storage/utils/compare-and-delete.d.ts +2 -0
package/esm/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
var __frontmcpModule = typeof process !== "undefined" && typeof process.getBuiltinModule === "function" ? process.getBuiltinModule("module") : undefined;
|
|
2
2
|
const require = __frontmcpModule ? __frontmcpModule.createRequire(import.meta.url || 'file:///') : undefined;
|
|
3
3
|
// __frontmcpCreateRequire
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -595,9 +595,9 @@ function createSecretData(options) {
|
|
|
595
595
|
}
|
|
596
596
|
async function getOrCreateSecret(options) {
|
|
597
597
|
const cacheKey = resolveSecretPath(options);
|
|
598
|
-
const
|
|
599
|
-
if (
|
|
600
|
-
return
|
|
598
|
+
const cached = secretCache.get(cacheKey);
|
|
599
|
+
if (cached) {
|
|
600
|
+
return cached;
|
|
601
601
|
}
|
|
602
602
|
const existing = generationPromises.get(cacheKey);
|
|
603
603
|
if (existing) {
|
|
@@ -834,8 +834,8 @@ var init_key_persistence = __esm({
|
|
|
834
834
|
*/
|
|
835
835
|
async get(kid) {
|
|
836
836
|
if (this.enableCache) {
|
|
837
|
-
const
|
|
838
|
-
if (
|
|
837
|
+
const cached = this.cache.get(kid);
|
|
838
|
+
if (cached) return cached;
|
|
839
839
|
}
|
|
840
840
|
const raw = await this.storage.get(kid);
|
|
841
841
|
if (!raw) return null;
|
|
@@ -1086,6 +1086,75 @@ var init_errors = __esm({
|
|
|
1086
1086
|
}
|
|
1087
1087
|
});
|
|
1088
1088
|
|
|
1089
|
+
// libs/utils/src/storage/utils/pattern.ts
|
|
1090
|
+
function globToRegex(pattern) {
|
|
1091
|
+
if (pattern.length > MAX_PATTERN_LENGTH) {
|
|
1092
|
+
throw new StoragePatternError(
|
|
1093
|
+
pattern.substring(0, 50) + "...",
|
|
1094
|
+
`Pattern exceeds maximum length of ${MAX_PATTERN_LENGTH} characters`
|
|
1095
|
+
);
|
|
1096
|
+
}
|
|
1097
|
+
const wildcardCount = (pattern.match(/[*?]/g) || []).length;
|
|
1098
|
+
if (wildcardCount > MAX_WILDCARDS) {
|
|
1099
|
+
throw new StoragePatternError(pattern, `Pattern has too many wildcards (max: ${MAX_WILDCARDS})`);
|
|
1100
|
+
}
|
|
1101
|
+
if (pattern === "" || pattern === "*") {
|
|
1102
|
+
return /^.*$/;
|
|
1103
|
+
}
|
|
1104
|
+
let regexStr = "^";
|
|
1105
|
+
let prevChar = "";
|
|
1106
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
1107
|
+
const char = pattern[i];
|
|
1108
|
+
switch (char) {
|
|
1109
|
+
case "*":
|
|
1110
|
+
if (prevChar !== "*") {
|
|
1111
|
+
regexStr += ".*";
|
|
1112
|
+
}
|
|
1113
|
+
break;
|
|
1114
|
+
case "?":
|
|
1115
|
+
regexStr += ".";
|
|
1116
|
+
break;
|
|
1117
|
+
default:
|
|
1118
|
+
regexStr += char.replace(REGEX_SPECIAL_CHARS, "\\$&");
|
|
1119
|
+
}
|
|
1120
|
+
prevChar = char;
|
|
1121
|
+
}
|
|
1122
|
+
regexStr += "$";
|
|
1123
|
+
try {
|
|
1124
|
+
return new RegExp(regexStr);
|
|
1125
|
+
} catch {
|
|
1126
|
+
throw new StoragePatternError(pattern, "Failed to compile pattern to regex");
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
function matchesPattern(key, pattern) {
|
|
1130
|
+
const regex = globToRegex(pattern);
|
|
1131
|
+
return regex.test(key);
|
|
1132
|
+
}
|
|
1133
|
+
function validatePattern(pattern) {
|
|
1134
|
+
try {
|
|
1135
|
+
globToRegex(pattern);
|
|
1136
|
+
return { valid: true };
|
|
1137
|
+
} catch (e) {
|
|
1138
|
+
return {
|
|
1139
|
+
valid: false,
|
|
1140
|
+
error: e instanceof Error ? e.message : "Invalid pattern"
|
|
1141
|
+
};
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
function escapeGlob(literal) {
|
|
1145
|
+
return literal.replace(/[*?\\]/g, "\\$&");
|
|
1146
|
+
}
|
|
1147
|
+
var MAX_PATTERN_LENGTH, MAX_WILDCARDS, REGEX_SPECIAL_CHARS;
|
|
1148
|
+
var init_pattern = __esm({
|
|
1149
|
+
"libs/utils/src/storage/utils/pattern.ts"() {
|
|
1150
|
+
"use strict";
|
|
1151
|
+
init_errors();
|
|
1152
|
+
MAX_PATTERN_LENGTH = 500;
|
|
1153
|
+
MAX_WILDCARDS = 20;
|
|
1154
|
+
REGEX_SPECIAL_CHARS = /[.+^${}()|[\]\\]/g;
|
|
1155
|
+
}
|
|
1156
|
+
});
|
|
1157
|
+
|
|
1089
1158
|
// libs/utils/src/storage/utils/ttl.ts
|
|
1090
1159
|
function validateTTL(ttlSeconds) {
|
|
1091
1160
|
if (typeof ttlSeconds !== "number") {
|
|
@@ -1200,6 +1269,17 @@ var init_base = __esm({
|
|
|
1200
1269
|
const matchedKeys = await this.keys(pattern);
|
|
1201
1270
|
return matchedKeys.length;
|
|
1202
1271
|
}
|
|
1272
|
+
/**
|
|
1273
|
+
* Default: not supported, since a read followed by a delete is not atomic.
|
|
1274
|
+
* Override in adapters whose backend can compare and delete in one step.
|
|
1275
|
+
*/
|
|
1276
|
+
async deleteIfEquals(_key, _expectedValue) {
|
|
1277
|
+
throw new StorageNotSupportedError(
|
|
1278
|
+
"deleteIfEquals",
|
|
1279
|
+
this.backendName,
|
|
1280
|
+
"Use the memory, Redis, Upstash or Vercel KV adapter for an atomic compare-and-delete."
|
|
1281
|
+
);
|
|
1282
|
+
}
|
|
1203
1283
|
// ============================================
|
|
1204
1284
|
// Pub/Sub (default: not supported)
|
|
1205
1285
|
// ============================================
|
|
@@ -1248,85 +1328,16 @@ var init_base = __esm({
|
|
|
1248
1328
|
}
|
|
1249
1329
|
});
|
|
1250
1330
|
|
|
1251
|
-
// libs/utils/src/storage/utils/pattern.ts
|
|
1252
|
-
function globToRegex(pattern) {
|
|
1253
|
-
if (pattern.length > MAX_PATTERN_LENGTH) {
|
|
1254
|
-
throw new StoragePatternError(
|
|
1255
|
-
pattern.substring(0, 50) + "...",
|
|
1256
|
-
`Pattern exceeds maximum length of ${MAX_PATTERN_LENGTH} characters`
|
|
1257
|
-
);
|
|
1258
|
-
}
|
|
1259
|
-
const wildcardCount = (pattern.match(/[*?]/g) || []).length;
|
|
1260
|
-
if (wildcardCount > MAX_WILDCARDS) {
|
|
1261
|
-
throw new StoragePatternError(pattern, `Pattern has too many wildcards (max: ${MAX_WILDCARDS})`);
|
|
1262
|
-
}
|
|
1263
|
-
if (pattern === "" || pattern === "*") {
|
|
1264
|
-
return /^.*$/;
|
|
1265
|
-
}
|
|
1266
|
-
let regexStr = "^";
|
|
1267
|
-
let prevChar = "";
|
|
1268
|
-
for (let i = 0; i < pattern.length; i++) {
|
|
1269
|
-
const char = pattern[i];
|
|
1270
|
-
switch (char) {
|
|
1271
|
-
case "*":
|
|
1272
|
-
if (prevChar !== "*") {
|
|
1273
|
-
regexStr += ".*";
|
|
1274
|
-
}
|
|
1275
|
-
break;
|
|
1276
|
-
case "?":
|
|
1277
|
-
regexStr += ".";
|
|
1278
|
-
break;
|
|
1279
|
-
default:
|
|
1280
|
-
regexStr += char.replace(REGEX_SPECIAL_CHARS, "\\$&");
|
|
1281
|
-
}
|
|
1282
|
-
prevChar = char;
|
|
1283
|
-
}
|
|
1284
|
-
regexStr += "$";
|
|
1285
|
-
try {
|
|
1286
|
-
return new RegExp(regexStr);
|
|
1287
|
-
} catch {
|
|
1288
|
-
throw new StoragePatternError(pattern, "Failed to compile pattern to regex");
|
|
1289
|
-
}
|
|
1290
|
-
}
|
|
1291
|
-
function matchesPattern(key, pattern) {
|
|
1292
|
-
const regex = globToRegex(pattern);
|
|
1293
|
-
return regex.test(key);
|
|
1294
|
-
}
|
|
1295
|
-
function validatePattern(pattern) {
|
|
1296
|
-
try {
|
|
1297
|
-
globToRegex(pattern);
|
|
1298
|
-
return { valid: true };
|
|
1299
|
-
} catch (e) {
|
|
1300
|
-
return {
|
|
1301
|
-
valid: false,
|
|
1302
|
-
error: e instanceof Error ? e.message : "Invalid pattern"
|
|
1303
|
-
};
|
|
1304
|
-
}
|
|
1305
|
-
}
|
|
1306
|
-
function escapeGlob(literal) {
|
|
1307
|
-
return literal.replace(/[*?\\]/g, "\\$&");
|
|
1308
|
-
}
|
|
1309
|
-
var MAX_PATTERN_LENGTH, MAX_WILDCARDS, REGEX_SPECIAL_CHARS;
|
|
1310
|
-
var init_pattern = __esm({
|
|
1311
|
-
"libs/utils/src/storage/utils/pattern.ts"() {
|
|
1312
|
-
"use strict";
|
|
1313
|
-
init_errors();
|
|
1314
|
-
MAX_PATTERN_LENGTH = 500;
|
|
1315
|
-
MAX_WILDCARDS = 20;
|
|
1316
|
-
REGEX_SPECIAL_CHARS = /[.+^${}()|[\]\\]/g;
|
|
1317
|
-
}
|
|
1318
|
-
});
|
|
1319
|
-
|
|
1320
1331
|
// libs/utils/src/storage/adapters/memory.ts
|
|
1321
1332
|
import { EventEmitter } from "#event-emitter";
|
|
1322
1333
|
var DEFAULT_SWEEP_INTERVAL_SECONDS, MAX_TIMEOUT_MS, MemoryStorageAdapter;
|
|
1323
1334
|
var init_memory = __esm({
|
|
1324
1335
|
"libs/utils/src/storage/adapters/memory.ts"() {
|
|
1325
1336
|
"use strict";
|
|
1326
|
-
init_base();
|
|
1327
1337
|
init_errors();
|
|
1328
1338
|
init_pattern();
|
|
1329
1339
|
init_ttl();
|
|
1340
|
+
init_base();
|
|
1330
1341
|
DEFAULT_SWEEP_INTERVAL_SECONDS = 60;
|
|
1331
1342
|
MAX_TIMEOUT_MS = 2147483647;
|
|
1332
1343
|
MemoryStorageAdapter = class extends BaseStorageAdapter {
|
|
@@ -1418,6 +1429,12 @@ var init_memory = __esm({
|
|
|
1418
1429
|
this.ensureConnected();
|
|
1419
1430
|
return this.deleteEntry(key);
|
|
1420
1431
|
}
|
|
1432
|
+
async deleteIfEquals(key, expectedValue) {
|
|
1433
|
+
this.ensureConnected();
|
|
1434
|
+
const entry = this.store.get(key);
|
|
1435
|
+
if (!entry || isExpired(entry.expiresAt) || entry.value !== expectedValue) return false;
|
|
1436
|
+
return this.deleteEntry(key);
|
|
1437
|
+
}
|
|
1421
1438
|
async exists(key) {
|
|
1422
1439
|
this.ensureConnected();
|
|
1423
1440
|
const entry = this.store.get(key);
|
|
@@ -3006,6 +3023,15 @@ var init_utils = __esm({
|
|
|
3006
3023
|
}
|
|
3007
3024
|
});
|
|
3008
3025
|
|
|
3026
|
+
// libs/utils/src/storage/utils/compare-and-delete.ts
|
|
3027
|
+
var COMPARE_AND_DELETE_SCRIPT;
|
|
3028
|
+
var init_compare_and_delete = __esm({
|
|
3029
|
+
"libs/utils/src/storage/utils/compare-and-delete.ts"() {
|
|
3030
|
+
"use strict";
|
|
3031
|
+
COMPARE_AND_DELETE_SCRIPT = `if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('DEL', KEYS[1]) end return 0`;
|
|
3032
|
+
}
|
|
3033
|
+
});
|
|
3034
|
+
|
|
3009
3035
|
// libs/utils/src/storage/adapters/redis.ts
|
|
3010
3036
|
var redis_exports = {};
|
|
3011
3037
|
__export(redis_exports, {
|
|
@@ -3049,6 +3075,7 @@ var init_redis = __esm({
|
|
|
3049
3075
|
init_errors();
|
|
3050
3076
|
init_redis_error_listener();
|
|
3051
3077
|
init_utils();
|
|
3078
|
+
init_compare_and_delete();
|
|
3052
3079
|
init_base();
|
|
3053
3080
|
RedisStorageAdapter = class extends BaseStorageAdapter {
|
|
3054
3081
|
backendName = "redis";
|
|
@@ -3203,6 +3230,15 @@ var init_redis = __esm({
|
|
|
3203
3230
|
const result = await this.getConnectedClient().del(this.prefixKey(key));
|
|
3204
3231
|
return result > 0;
|
|
3205
3232
|
}
|
|
3233
|
+
async deleteIfEquals(key, expectedValue) {
|
|
3234
|
+
const deleted = await this.getConnectedClient().eval(
|
|
3235
|
+
COMPARE_AND_DELETE_SCRIPT,
|
|
3236
|
+
1,
|
|
3237
|
+
this.prefixKey(key),
|
|
3238
|
+
expectedValue
|
|
3239
|
+
);
|
|
3240
|
+
return deleted === 1;
|
|
3241
|
+
}
|
|
3206
3242
|
async exists(key) {
|
|
3207
3243
|
const result = await this.getConnectedClient().exists(this.prefixKey(key));
|
|
3208
3244
|
return result > 0;
|
|
@@ -3411,9 +3447,12 @@ var vercel_kv_exports = {};
|
|
|
3411
3447
|
__export(vercel_kv_exports, {
|
|
3412
3448
|
VercelKvStorageAdapter: () => VercelKvStorageAdapter
|
|
3413
3449
|
});
|
|
3414
|
-
function
|
|
3450
|
+
async function loadVercelKv() {
|
|
3415
3451
|
try {
|
|
3416
|
-
|
|
3452
|
+
const mod = await import("@vercel/kv");
|
|
3453
|
+
const resolved = typeof mod.createClient === "function" ? mod : mod.default;
|
|
3454
|
+
if (!resolved || typeof resolved.createClient !== "function") throw new Error("createClient missing");
|
|
3455
|
+
return resolved;
|
|
3417
3456
|
} catch {
|
|
3418
3457
|
throw new Error("@vercel/kv is required for Vercel KV storage adapter. Install it with: npm install @vercel/kv");
|
|
3419
3458
|
}
|
|
@@ -3422,9 +3461,10 @@ var VercelKvStorageAdapter;
|
|
|
3422
3461
|
var init_vercel_kv = __esm({
|
|
3423
3462
|
"libs/utils/src/storage/adapters/vercel-kv.ts"() {
|
|
3424
3463
|
"use strict";
|
|
3425
|
-
init_base();
|
|
3426
3464
|
init_errors();
|
|
3465
|
+
init_compare_and_delete();
|
|
3427
3466
|
init_ttl();
|
|
3467
|
+
init_base();
|
|
3428
3468
|
VercelKvStorageAdapter = class extends BaseStorageAdapter {
|
|
3429
3469
|
backendName = "vercel-kv";
|
|
3430
3470
|
client;
|
|
@@ -3449,17 +3489,13 @@ var init_vercel_kv = __esm({
|
|
|
3449
3489
|
async connect() {
|
|
3450
3490
|
if (this.connected) return;
|
|
3451
3491
|
try {
|
|
3452
|
-
const { createClient
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
const token = this.options.token;
|
|
3458
|
-
if (!url || !token) {
|
|
3459
|
-
throw new StorageConfigError("vercel-kv", "URL and token are required");
|
|
3460
|
-
}
|
|
3461
|
-
this.client = createClient({ url, token });
|
|
3492
|
+
const { createClient } = await loadVercelKv();
|
|
3493
|
+
const url = this.options.url;
|
|
3494
|
+
const token = this.options.token;
|
|
3495
|
+
if (!url || !token) {
|
|
3496
|
+
throw new StorageConfigError("vercel-kv", "URL and token are required");
|
|
3462
3497
|
}
|
|
3498
|
+
this.client = createClient({ url, token, cache: void 0, automaticDeserialization: false });
|
|
3463
3499
|
await this.client.exists("__healthcheck__");
|
|
3464
3500
|
this.connected = true;
|
|
3465
3501
|
} catch (e) {
|
|
@@ -3500,8 +3536,7 @@ var init_vercel_kv = __esm({
|
|
|
3500
3536
|
// Core Operations
|
|
3501
3537
|
// ============================================
|
|
3502
3538
|
async get(key) {
|
|
3503
|
-
|
|
3504
|
-
return result;
|
|
3539
|
+
return this.getConnectedClient().get(this.prefixKey(key));
|
|
3505
3540
|
}
|
|
3506
3541
|
async doSet(key, value, options) {
|
|
3507
3542
|
const client = this.getConnectedClient();
|
|
@@ -3521,6 +3556,14 @@ var init_vercel_kv = __esm({
|
|
|
3521
3556
|
const result = await this.getConnectedClient().del(this.prefixKey(key));
|
|
3522
3557
|
return result > 0;
|
|
3523
3558
|
}
|
|
3559
|
+
async deleteIfEquals(key, expectedValue) {
|
|
3560
|
+
const deleted = await this.getConnectedClient().eval(
|
|
3561
|
+
COMPARE_AND_DELETE_SCRIPT,
|
|
3562
|
+
[this.prefixKey(key)],
|
|
3563
|
+
[expectedValue]
|
|
3564
|
+
);
|
|
3565
|
+
return deleted === 1;
|
|
3566
|
+
}
|
|
3524
3567
|
async exists(key) {
|
|
3525
3568
|
const result = await this.getConnectedClient().exists(this.prefixKey(key));
|
|
3526
3569
|
return result > 0;
|
|
@@ -3638,9 +3681,10 @@ var PUBSUB_POLL_INTERVAL_MS, UpstashStorageAdapter;
|
|
|
3638
3681
|
var init_upstash = __esm({
|
|
3639
3682
|
"libs/utils/src/storage/adapters/upstash.ts"() {
|
|
3640
3683
|
"use strict";
|
|
3641
|
-
init_base();
|
|
3642
3684
|
init_errors();
|
|
3685
|
+
init_compare_and_delete();
|
|
3643
3686
|
init_ttl();
|
|
3687
|
+
init_base();
|
|
3644
3688
|
PUBSUB_POLL_INTERVAL_MS = 100;
|
|
3645
3689
|
UpstashStorageAdapter = class extends BaseStorageAdapter {
|
|
3646
3690
|
backendName = "upstash";
|
|
@@ -3677,7 +3721,7 @@ var init_upstash = __esm({
|
|
|
3677
3721
|
if (!url || !token) {
|
|
3678
3722
|
throw new StorageConfigError("upstash", "URL and token are required");
|
|
3679
3723
|
}
|
|
3680
|
-
this.client = new Redis({ url, token });
|
|
3724
|
+
this.client = new Redis({ url, token, automaticDeserialization: false });
|
|
3681
3725
|
await this.client.exists("__healthcheck__");
|
|
3682
3726
|
this.connected = true;
|
|
3683
3727
|
} catch (e) {
|
|
@@ -3724,8 +3768,7 @@ var init_upstash = __esm({
|
|
|
3724
3768
|
// Core Operations
|
|
3725
3769
|
// ============================================
|
|
3726
3770
|
async get(key) {
|
|
3727
|
-
|
|
3728
|
-
return result;
|
|
3771
|
+
return this.getConnectedClient().get(this.prefixKey(key));
|
|
3729
3772
|
}
|
|
3730
3773
|
async doSet(key, value, options) {
|
|
3731
3774
|
const client = this.getConnectedClient();
|
|
@@ -3745,6 +3788,14 @@ var init_upstash = __esm({
|
|
|
3745
3788
|
const result = await this.getConnectedClient().del(this.prefixKey(key));
|
|
3746
3789
|
return result > 0;
|
|
3747
3790
|
}
|
|
3791
|
+
async deleteIfEquals(key, expectedValue) {
|
|
3792
|
+
const deleted = await this.getConnectedClient().eval(
|
|
3793
|
+
COMPARE_AND_DELETE_SCRIPT,
|
|
3794
|
+
[this.prefixKey(key)],
|
|
3795
|
+
[expectedValue]
|
|
3796
|
+
);
|
|
3797
|
+
return deleted === 1;
|
|
3798
|
+
}
|
|
3748
3799
|
async exists(key) {
|
|
3749
3800
|
const result = await this.getConnectedClient().exists(this.prefixKey(key));
|
|
3750
3801
|
return result > 0;
|
|
@@ -3934,7 +3985,9 @@ var init_cloudflare_kv = __esm({
|
|
|
3934
3985
|
constructor(options) {
|
|
3935
3986
|
super();
|
|
3936
3987
|
if (!options?.namespace) {
|
|
3937
|
-
throw new Error(
|
|
3988
|
+
throw new Error(
|
|
3989
|
+
"CloudflareKvStorageAdapter: a bound KV `namespace` is required (resolve it from the Worker `env`)."
|
|
3990
|
+
);
|
|
3938
3991
|
}
|
|
3939
3992
|
this.kv = options.namespace;
|
|
3940
3993
|
this.keyPrefix = options.keyPrefix ?? "";
|
|
@@ -4028,6 +4081,13 @@ var init_cloudflare_kv = __esm({
|
|
|
4028
4081
|
"Cloudflare KV has no atomic increment (a get+put is racy under eventual consistency). Use a Durable Object for atomic counters."
|
|
4029
4082
|
);
|
|
4030
4083
|
}
|
|
4084
|
+
async deleteIfEquals(_key, _expectedValue) {
|
|
4085
|
+
throw new StorageNotSupportedError(
|
|
4086
|
+
"deleteIfEquals",
|
|
4087
|
+
this.backendName,
|
|
4088
|
+
"Cloudflare KV has no compare-and-set; use a Durable Object for an atomic compare-and-delete."
|
|
4089
|
+
);
|
|
4090
|
+
}
|
|
4031
4091
|
// ── Pub/Sub (unsupported) ────────────────────────────────────────────────
|
|
4032
4092
|
getPubSubSuggestion() {
|
|
4033
4093
|
return "Cloudflare KV does not support pub/sub. Use a Durable Object (or Queues) for fan-out.";
|
|
@@ -4456,9 +4516,17 @@ function joinPath(...parts) {
|
|
|
4456
4516
|
return cleaned.length ? `/${cleaned.join("/")}` : "";
|
|
4457
4517
|
}
|
|
4458
4518
|
|
|
4459
|
-
// libs/utils/src/path/
|
|
4460
|
-
import {
|
|
4461
|
-
|
|
4519
|
+
// libs/utils/src/path/index.ts
|
|
4520
|
+
import {
|
|
4521
|
+
resolve,
|
|
4522
|
+
join,
|
|
4523
|
+
basename,
|
|
4524
|
+
dirname,
|
|
4525
|
+
extname,
|
|
4526
|
+
isAbsolute,
|
|
4527
|
+
pathToFileURL,
|
|
4528
|
+
sep
|
|
4529
|
+
} from "#path";
|
|
4462
4530
|
|
|
4463
4531
|
// libs/utils/src/content/content.ts
|
|
4464
4532
|
function sanitizeToJson(value) {
|
|
@@ -4885,175 +4953,30 @@ import { EventEmitter as EventEmitter2 } from "#event-emitter";
|
|
|
4885
4953
|
import {
|
|
4886
4954
|
getEnv as getEnv2,
|
|
4887
4955
|
getCwd as getCwd2,
|
|
4956
|
+
getNodeEnv,
|
|
4888
4957
|
isProduction,
|
|
4889
4958
|
isDevelopment,
|
|
4890
4959
|
getEnvFlag,
|
|
4891
4960
|
isDebug,
|
|
4892
4961
|
setEnv,
|
|
4893
|
-
isEdgeRuntime
|
|
4894
|
-
isServerless
|
|
4962
|
+
isEdgeRuntime,
|
|
4963
|
+
isServerless,
|
|
4895
4964
|
supportsAnsi
|
|
4896
4965
|
} from "#env";
|
|
4897
|
-
|
|
4898
|
-
|
|
4899
|
-
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
|
|
4905
|
-
if (cached) return cached;
|
|
4906
|
-
cached = resolveBuildTarget();
|
|
4907
|
-
return cached;
|
|
4908
|
-
}
|
|
4909
|
-
function resolveBuildTarget() {
|
|
4910
|
-
const globalAny = globalThis;
|
|
4911
|
-
const fromGlobal = globalAny.FRONTMCP_BUILD_TARGET;
|
|
4912
|
-
if (typeof fromGlobal === "string" && isKnownTarget(fromGlobal)) return fromGlobal;
|
|
4913
|
-
const fromEnv = typeof process !== "undefined" ? process.env?.["FRONTMCP_BUILD_TARGET"] : void 0;
|
|
4914
|
-
if (typeof fromEnv === "string" && isKnownTarget(fromEnv)) return fromEnv;
|
|
4915
|
-
return "unknown";
|
|
4916
|
-
}
|
|
4917
|
-
function isKnownTarget(value) {
|
|
4918
|
-
return value === "unknown" || value === "node" || value === "distributed" || value === "cli" || value === "vercel" || value === "lambda" || value === "cloudflare" || value === "browser" || value === "sdk" || value === "mcpb";
|
|
4919
|
-
}
|
|
4920
|
-
|
|
4921
|
-
// libs/utils/src/env/provider.ts
|
|
4922
|
-
var cached2;
|
|
4923
|
-
function detectProvider() {
|
|
4924
|
-
if (cached2) return cached2;
|
|
4925
|
-
cached2 = detectProviderUncached();
|
|
4926
|
-
return cached2;
|
|
4927
|
-
}
|
|
4928
|
-
function detectProviderUncached() {
|
|
4929
|
-
const explicit = process.env["FRONTMCP_PROVIDER"];
|
|
4930
|
-
if (explicit && isKnownProvider(explicit)) return explicit;
|
|
4931
|
-
if (process.env["VERCEL"]) return "vercel";
|
|
4932
|
-
if (process.env["AWS_LAMBDA_FUNCTION_NAME"]) return "lambda";
|
|
4933
|
-
if (process.env["CF_PAGES"]) return "cloudflare";
|
|
4934
|
-
if (process.env["NETLIFY"]) return "netlify";
|
|
4935
|
-
if (process.env["AZURE_FUNCTIONS_ENVIRONMENT"]) return "azure";
|
|
4936
|
-
if (process.env["K_SERVICE"]) return "gcp";
|
|
4937
|
-
if (process.env["FLY_APP_NAME"]) return "fly";
|
|
4938
|
-
if (process.env["RENDER"]) return "render";
|
|
4939
|
-
if (process.env["RAILWAY_ENVIRONMENT"]) return "railway";
|
|
4940
|
-
try {
|
|
4941
|
-
const nodeFs = __require("node:fs");
|
|
4942
|
-
if (nodeFs.existsSync("/.dockerenv")) return "docker";
|
|
4943
|
-
} catch {
|
|
4944
|
-
}
|
|
4945
|
-
return "bare";
|
|
4946
|
-
}
|
|
4947
|
-
function isKnownProvider(value) {
|
|
4948
|
-
return value === "bare" || value === "docker" || value === "vercel" || value === "lambda" || value === "cloudflare" || value === "netlify" || value === "azure" || value === "gcp" || value === "fly" || value === "render" || value === "railway";
|
|
4949
|
-
}
|
|
4950
|
-
|
|
4951
|
-
// libs/utils/src/env/runtime-context.ts
|
|
4952
|
-
var entryAvailabilitySchema = z3.object({
|
|
4953
|
-
os: z3.array(z3.string().min(1)).optional(),
|
|
4954
|
-
platform: z3.array(z3.string().min(1)).optional(),
|
|
4955
|
-
runtime: z3.array(z3.string().min(1)).optional(),
|
|
4956
|
-
deployment: z3.array(z3.string().min(1)).optional(),
|
|
4957
|
-
provider: z3.array(z3.string().min(1)).optional(),
|
|
4958
|
-
target: z3.array(z3.string().min(1)).optional(),
|
|
4959
|
-
surface: z3.array(z3.enum(["mcp", "cli", "http-trigger", "job", "agent"])).optional(),
|
|
4960
|
-
env: z3.array(z3.string().min(1)).optional()
|
|
4961
|
-
}).strict();
|
|
4962
|
-
var PROCESS_AXES = [
|
|
4963
|
-
// `os` and `platform` both compare against the same RuntimeContext value
|
|
4964
|
-
// — keeping `platform` as a deprecated alias lets pre-#417 metadata
|
|
4965
|
-
// continue to match without any code change.
|
|
4966
|
-
{ key: "os", ctxKey: "os" },
|
|
4967
|
-
{ key: "platform", ctxKey: "platform" },
|
|
4968
|
-
{ key: "runtime", ctxKey: "runtime" },
|
|
4969
|
-
{ key: "deployment", ctxKey: "deployment" },
|
|
4970
|
-
{ key: "provider", ctxKey: "provider" },
|
|
4971
|
-
{ key: "target", ctxKey: "target" },
|
|
4972
|
-
{ key: "env", ctxKey: "env" }
|
|
4973
|
-
];
|
|
4974
|
-
function isEntryAvailable(availability, ctx, callCtx) {
|
|
4975
|
-
if (!availability) return true;
|
|
4976
|
-
for (const { key, ctxKey } of PROCESS_AXES) {
|
|
4977
|
-
const allowed = availability[key];
|
|
4978
|
-
if (allowed === void 0) continue;
|
|
4979
|
-
if (allowed.length === 0) return false;
|
|
4980
|
-
if (!allowed.includes(ctx[ctxKey])) return false;
|
|
4981
|
-
}
|
|
4982
|
-
if (availability.surface !== void 0) {
|
|
4983
|
-
if (availability.surface.length === 0) return false;
|
|
4984
|
-
if (callCtx?.surface !== void 0 && !availability.surface.includes(callCtx.surface)) {
|
|
4985
|
-
return false;
|
|
4986
|
-
}
|
|
4987
|
-
}
|
|
4988
|
-
return true;
|
|
4989
|
-
}
|
|
4990
|
-
function checkEntryAvailability(availability, ctx, callCtx) {
|
|
4991
|
-
if (!availability) return { available: true, missingAxes: [] };
|
|
4992
|
-
const missing = [];
|
|
4993
|
-
for (const { key, ctxKey } of PROCESS_AXES) {
|
|
4994
|
-
const allowed = availability[key];
|
|
4995
|
-
if (allowed === void 0) continue;
|
|
4996
|
-
if (allowed.length === 0 || !allowed.includes(ctx[ctxKey])) {
|
|
4997
|
-
missing.push(key);
|
|
4998
|
-
}
|
|
4999
|
-
}
|
|
5000
|
-
if (availability.surface !== void 0) {
|
|
5001
|
-
if (availability.surface.length === 0) {
|
|
5002
|
-
missing.push("surface");
|
|
5003
|
-
} else if (callCtx?.surface !== void 0 && !availability.surface.includes(callCtx.surface)) {
|
|
5004
|
-
missing.push("surface");
|
|
5005
|
-
}
|
|
5006
|
-
}
|
|
5007
|
-
return { available: missing.length === 0, missingAxes: missing };
|
|
5008
|
-
}
|
|
5009
|
-
function detectRuntime() {
|
|
5010
|
-
if (typeof globalThis !== "undefined" && "Bun" in globalThis) return "bun";
|
|
5011
|
-
if (typeof globalThis !== "undefined" && "Deno" in globalThis) return "deno";
|
|
5012
|
-
if (isEdgeRuntime()) return "edge";
|
|
5013
|
-
return "node";
|
|
5014
|
-
}
|
|
5015
|
-
function detectDeployment(runtime) {
|
|
5016
|
-
const explicit = process.env["FRONTMCP_DEPLOYMENT_MODE"];
|
|
5017
|
-
if (explicit === "distributed") return "distributed";
|
|
5018
|
-
if (explicit === "serverless") return "serverless";
|
|
5019
|
-
if (runtime === "browser") return "browser";
|
|
5020
|
-
if (isServerless()) return "serverless";
|
|
5021
|
-
return "standalone";
|
|
5022
|
-
}
|
|
5023
|
-
function detectRuntimeContext() {
|
|
5024
|
-
const runtime = detectRuntime();
|
|
5025
|
-
const os = process.platform;
|
|
5026
|
-
return {
|
|
5027
|
-
os,
|
|
5028
|
-
platform: os,
|
|
5029
|
-
runtime,
|
|
5030
|
-
deployment: detectDeployment(runtime),
|
|
5031
|
-
provider: detectProvider(),
|
|
5032
|
-
target: getBuildTarget(),
|
|
5033
|
-
env: process.env["NODE_ENV"] || "development"
|
|
5034
|
-
};
|
|
5035
|
-
}
|
|
5036
|
-
var cached3;
|
|
5037
|
-
function getRuntimeContext() {
|
|
5038
|
-
if (!cached3) {
|
|
5039
|
-
const detected = detectRuntimeContext();
|
|
5040
|
-
Object.defineProperty(detected, "env", {
|
|
5041
|
-
get: () => process.env["NODE_ENV"] || "development",
|
|
5042
|
-
enumerable: true,
|
|
5043
|
-
configurable: true
|
|
5044
|
-
});
|
|
5045
|
-
cached3 = detected;
|
|
5046
|
-
}
|
|
5047
|
-
return cached3;
|
|
5048
|
-
}
|
|
5049
|
-
function resetRuntimeContext() {
|
|
5050
|
-
cached3 = void 0;
|
|
5051
|
-
}
|
|
4966
|
+
import {
|
|
4967
|
+
getRuntimeContext,
|
|
4968
|
+
resetRuntimeContext,
|
|
4969
|
+
detectRuntimeContext,
|
|
4970
|
+
isEntryAvailable,
|
|
4971
|
+
checkEntryAvailability,
|
|
4972
|
+
entryAvailabilitySchema
|
|
4973
|
+
} from "#runtime-context";
|
|
5052
4974
|
|
|
5053
4975
|
// libs/utils/src/storage/factory.ts
|
|
5054
4976
|
init_errors();
|
|
5055
4977
|
|
|
5056
4978
|
// libs/utils/src/storage/namespace.ts
|
|
4979
|
+
init_errors();
|
|
5057
4980
|
var NAMESPACE_SEPARATOR = ":";
|
|
5058
4981
|
function buildPrefix(name, id) {
|
|
5059
4982
|
if (id) {
|
|
@@ -5185,6 +5108,12 @@ var NamespacedStorageImpl = class _NamespacedStorageImpl {
|
|
|
5185
5108
|
async incrBy(key, amount) {
|
|
5186
5109
|
return this.adapter.incrBy(this.prefixKey(key), amount);
|
|
5187
5110
|
}
|
|
5111
|
+
async deleteIfEquals(key, expectedValue) {
|
|
5112
|
+
if (!this.adapter.deleteIfEquals) {
|
|
5113
|
+
throw new StorageNotSupportedError("deleteIfEquals", "this storage adapter");
|
|
5114
|
+
}
|
|
5115
|
+
return this.adapter.deleteIfEquals(this.prefixKey(key), expectedValue);
|
|
5116
|
+
}
|
|
5188
5117
|
// ============================================
|
|
5189
5118
|
// Pub/Sub (with channel prefixing)
|
|
5190
5119
|
// ============================================
|
|
@@ -6070,6 +5999,7 @@ export {
|
|
|
6070
5999
|
getEnv2 as getEnv,
|
|
6071
6000
|
getEnvFlag,
|
|
6072
6001
|
getMachineId,
|
|
6002
|
+
getNodeEnv,
|
|
6073
6003
|
getOrCreateSecret,
|
|
6074
6004
|
getRuntimeContext,
|
|
6075
6005
|
getSpawnFn,
|
|
@@ -6085,7 +6015,7 @@ export {
|
|
|
6085
6015
|
isDebug,
|
|
6086
6016
|
isDevelopment,
|
|
6087
6017
|
isDirEmpty,
|
|
6088
|
-
|
|
6018
|
+
isEdgeRuntime,
|
|
6089
6019
|
isEntryAvailable,
|
|
6090
6020
|
isExpired,
|
|
6091
6021
|
isInputLengthSafe,
|
|
@@ -6099,7 +6029,7 @@ export {
|
|
|
6099
6029
|
isSecretKeyData,
|
|
6100
6030
|
isSecretPersistenceEnabled,
|
|
6101
6031
|
isSecureRequest,
|
|
6102
|
-
|
|
6032
|
+
isServerless,
|
|
6103
6033
|
isSignedData,
|
|
6104
6034
|
isUriTemplate,
|
|
6105
6035
|
isValidCodeChallenge,
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
var __frontmcpModule = typeof process !== "undefined" && typeof process.getBuiltinModule === "function" ? process.getBuiltinModule("module") : undefined;
|
|
2
|
+
const require = __frontmcpModule ? __frontmcpModule.createRequire(import.meta.url || 'file:///') : undefined;
|
|
3
|
+
// __frontmcpCreateRequire
|
|
4
|
+
// libs/utils/src/path/browser-path.ts
|
|
5
|
+
function notAvailable(name) {
|
|
6
|
+
throw new Error(`path.${name}() is not available in browser environments`);
|
|
7
|
+
}
|
|
8
|
+
function resolve(..._segments) {
|
|
9
|
+
return notAvailable("resolve");
|
|
10
|
+
}
|
|
11
|
+
function join(..._segments) {
|
|
12
|
+
return notAvailable("join");
|
|
13
|
+
}
|
|
14
|
+
function basename(p, ext) {
|
|
15
|
+
const trimmed = p.replace(/[/\\]+$/, "");
|
|
16
|
+
const lastSep = Math.max(trimmed.lastIndexOf("/"), trimmed.lastIndexOf("\\"));
|
|
17
|
+
let base = lastSep >= 0 ? trimmed.slice(lastSep + 1) : trimmed;
|
|
18
|
+
if (ext && base.endsWith(ext)) {
|
|
19
|
+
base = base.slice(0, -ext.length);
|
|
20
|
+
}
|
|
21
|
+
return base;
|
|
22
|
+
}
|
|
23
|
+
function dirname(_p) {
|
|
24
|
+
return notAvailable("dirname");
|
|
25
|
+
}
|
|
26
|
+
function extname(p) {
|
|
27
|
+
const base = basename(p);
|
|
28
|
+
const dotIndex = base.lastIndexOf(".");
|
|
29
|
+
return dotIndex > 0 ? base.slice(dotIndex) : "";
|
|
30
|
+
}
|
|
31
|
+
function isAbsolute(p) {
|
|
32
|
+
if (!p) return false;
|
|
33
|
+
if (p.startsWith("/") || p.startsWith("\\")) return true;
|
|
34
|
+
if (/^[A-Za-z]:[\\/]/.test(p)) return true;
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
function pathToFileURL(_p) {
|
|
38
|
+
return notAvailable("pathToFileURL");
|
|
39
|
+
}
|
|
40
|
+
var sep = "/";
|
|
41
|
+
export {
|
|
42
|
+
basename,
|
|
43
|
+
dirname,
|
|
44
|
+
extname,
|
|
45
|
+
isAbsolute,
|
|
46
|
+
join,
|
|
47
|
+
pathToFileURL,
|
|
48
|
+
resolve,
|
|
49
|
+
sep
|
|
50
|
+
};
|