@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/index.js CHANGED
@@ -596,9 +596,9 @@ function createSecretData(options) {
596
596
  }
597
597
  async function getOrCreateSecret(options) {
598
598
  const cacheKey = resolveSecretPath(options);
599
- const cached4 = secretCache.get(cacheKey);
600
- if (cached4) {
601
- return cached4;
599
+ const cached = secretCache.get(cacheKey);
600
+ if (cached) {
601
+ return cached;
602
602
  }
603
603
  const existing = generationPromises.get(cacheKey);
604
604
  if (existing) {
@@ -836,8 +836,8 @@ var init_key_persistence = __esm({
836
836
  */
837
837
  async get(kid) {
838
838
  if (this.enableCache) {
839
- const cached4 = this.cache.get(kid);
840
- if (cached4) return cached4;
839
+ const cached = this.cache.get(kid);
840
+ if (cached) return cached;
841
841
  }
842
842
  const raw = await this.storage.get(kid);
843
843
  if (!raw) return null;
@@ -1088,6 +1088,75 @@ var init_errors = __esm({
1088
1088
  }
1089
1089
  });
1090
1090
 
1091
+ // libs/utils/src/storage/utils/pattern.ts
1092
+ function globToRegex(pattern) {
1093
+ if (pattern.length > MAX_PATTERN_LENGTH) {
1094
+ throw new StoragePatternError(
1095
+ pattern.substring(0, 50) + "...",
1096
+ `Pattern exceeds maximum length of ${MAX_PATTERN_LENGTH} characters`
1097
+ );
1098
+ }
1099
+ const wildcardCount = (pattern.match(/[*?]/g) || []).length;
1100
+ if (wildcardCount > MAX_WILDCARDS) {
1101
+ throw new StoragePatternError(pattern, `Pattern has too many wildcards (max: ${MAX_WILDCARDS})`);
1102
+ }
1103
+ if (pattern === "" || pattern === "*") {
1104
+ return /^.*$/;
1105
+ }
1106
+ let regexStr = "^";
1107
+ let prevChar = "";
1108
+ for (let i = 0; i < pattern.length; i++) {
1109
+ const char = pattern[i];
1110
+ switch (char) {
1111
+ case "*":
1112
+ if (prevChar !== "*") {
1113
+ regexStr += ".*";
1114
+ }
1115
+ break;
1116
+ case "?":
1117
+ regexStr += ".";
1118
+ break;
1119
+ default:
1120
+ regexStr += char.replace(REGEX_SPECIAL_CHARS, "\\$&");
1121
+ }
1122
+ prevChar = char;
1123
+ }
1124
+ regexStr += "$";
1125
+ try {
1126
+ return new RegExp(regexStr);
1127
+ } catch {
1128
+ throw new StoragePatternError(pattern, "Failed to compile pattern to regex");
1129
+ }
1130
+ }
1131
+ function matchesPattern(key, pattern) {
1132
+ const regex = globToRegex(pattern);
1133
+ return regex.test(key);
1134
+ }
1135
+ function validatePattern(pattern) {
1136
+ try {
1137
+ globToRegex(pattern);
1138
+ return { valid: true };
1139
+ } catch (e) {
1140
+ return {
1141
+ valid: false,
1142
+ error: e instanceof Error ? e.message : "Invalid pattern"
1143
+ };
1144
+ }
1145
+ }
1146
+ function escapeGlob(literal) {
1147
+ return literal.replace(/[*?\\]/g, "\\$&");
1148
+ }
1149
+ var MAX_PATTERN_LENGTH, MAX_WILDCARDS, REGEX_SPECIAL_CHARS;
1150
+ var init_pattern = __esm({
1151
+ "libs/utils/src/storage/utils/pattern.ts"() {
1152
+ "use strict";
1153
+ init_errors();
1154
+ MAX_PATTERN_LENGTH = 500;
1155
+ MAX_WILDCARDS = 20;
1156
+ REGEX_SPECIAL_CHARS = /[.+^${}()|[\]\\]/g;
1157
+ }
1158
+ });
1159
+
1091
1160
  // libs/utils/src/storage/utils/ttl.ts
1092
1161
  function validateTTL(ttlSeconds) {
1093
1162
  if (typeof ttlSeconds !== "number") {
@@ -1202,6 +1271,17 @@ var init_base = __esm({
1202
1271
  const matchedKeys = await this.keys(pattern);
1203
1272
  return matchedKeys.length;
1204
1273
  }
1274
+ /**
1275
+ * Default: not supported, since a read followed by a delete is not atomic.
1276
+ * Override in adapters whose backend can compare and delete in one step.
1277
+ */
1278
+ async deleteIfEquals(_key, _expectedValue) {
1279
+ throw new StorageNotSupportedError(
1280
+ "deleteIfEquals",
1281
+ this.backendName,
1282
+ "Use the memory, Redis, Upstash or Vercel KV adapter for an atomic compare-and-delete."
1283
+ );
1284
+ }
1205
1285
  // ============================================
1206
1286
  // Pub/Sub (default: not supported)
1207
1287
  // ============================================
@@ -1250,85 +1330,16 @@ var init_base = __esm({
1250
1330
  }
1251
1331
  });
1252
1332
 
1253
- // libs/utils/src/storage/utils/pattern.ts
1254
- function globToRegex(pattern) {
1255
- if (pattern.length > MAX_PATTERN_LENGTH) {
1256
- throw new StoragePatternError(
1257
- pattern.substring(0, 50) + "...",
1258
- `Pattern exceeds maximum length of ${MAX_PATTERN_LENGTH} characters`
1259
- );
1260
- }
1261
- const wildcardCount = (pattern.match(/[*?]/g) || []).length;
1262
- if (wildcardCount > MAX_WILDCARDS) {
1263
- throw new StoragePatternError(pattern, `Pattern has too many wildcards (max: ${MAX_WILDCARDS})`);
1264
- }
1265
- if (pattern === "" || pattern === "*") {
1266
- return /^.*$/;
1267
- }
1268
- let regexStr = "^";
1269
- let prevChar = "";
1270
- for (let i = 0; i < pattern.length; i++) {
1271
- const char = pattern[i];
1272
- switch (char) {
1273
- case "*":
1274
- if (prevChar !== "*") {
1275
- regexStr += ".*";
1276
- }
1277
- break;
1278
- case "?":
1279
- regexStr += ".";
1280
- break;
1281
- default:
1282
- regexStr += char.replace(REGEX_SPECIAL_CHARS, "\\$&");
1283
- }
1284
- prevChar = char;
1285
- }
1286
- regexStr += "$";
1287
- try {
1288
- return new RegExp(regexStr);
1289
- } catch {
1290
- throw new StoragePatternError(pattern, "Failed to compile pattern to regex");
1291
- }
1292
- }
1293
- function matchesPattern(key, pattern) {
1294
- const regex = globToRegex(pattern);
1295
- return regex.test(key);
1296
- }
1297
- function validatePattern(pattern) {
1298
- try {
1299
- globToRegex(pattern);
1300
- return { valid: true };
1301
- } catch (e) {
1302
- return {
1303
- valid: false,
1304
- error: e instanceof Error ? e.message : "Invalid pattern"
1305
- };
1306
- }
1307
- }
1308
- function escapeGlob(literal) {
1309
- return literal.replace(/[*?\\]/g, "\\$&");
1310
- }
1311
- var MAX_PATTERN_LENGTH, MAX_WILDCARDS, REGEX_SPECIAL_CHARS;
1312
- var init_pattern = __esm({
1313
- "libs/utils/src/storage/utils/pattern.ts"() {
1314
- "use strict";
1315
- init_errors();
1316
- MAX_PATTERN_LENGTH = 500;
1317
- MAX_WILDCARDS = 20;
1318
- REGEX_SPECIAL_CHARS = /[.+^${}()|[\]\\]/g;
1319
- }
1320
- });
1321
-
1322
1333
  // libs/utils/src/storage/adapters/memory.ts
1323
1334
  var import_event_emitter, DEFAULT_SWEEP_INTERVAL_SECONDS, MAX_TIMEOUT_MS, MemoryStorageAdapter;
1324
1335
  var init_memory = __esm({
1325
1336
  "libs/utils/src/storage/adapters/memory.ts"() {
1326
1337
  "use strict";
1327
1338
  import_event_emitter = require("#event-emitter");
1328
- init_base();
1329
1339
  init_errors();
1330
1340
  init_pattern();
1331
1341
  init_ttl();
1342
+ init_base();
1332
1343
  DEFAULT_SWEEP_INTERVAL_SECONDS = 60;
1333
1344
  MAX_TIMEOUT_MS = 2147483647;
1334
1345
  MemoryStorageAdapter = class extends BaseStorageAdapter {
@@ -1420,6 +1431,12 @@ var init_memory = __esm({
1420
1431
  this.ensureConnected();
1421
1432
  return this.deleteEntry(key);
1422
1433
  }
1434
+ async deleteIfEquals(key, expectedValue) {
1435
+ this.ensureConnected();
1436
+ const entry = this.store.get(key);
1437
+ if (!entry || isExpired(entry.expiresAt) || entry.value !== expectedValue) return false;
1438
+ return this.deleteEntry(key);
1439
+ }
1423
1440
  async exists(key) {
1424
1441
  this.ensureConnected();
1425
1442
  const entry = this.store.get(key);
@@ -3008,6 +3025,15 @@ var init_utils = __esm({
3008
3025
  }
3009
3026
  });
3010
3027
 
3028
+ // libs/utils/src/storage/utils/compare-and-delete.ts
3029
+ var COMPARE_AND_DELETE_SCRIPT;
3030
+ var init_compare_and_delete = __esm({
3031
+ "libs/utils/src/storage/utils/compare-and-delete.ts"() {
3032
+ "use strict";
3033
+ COMPARE_AND_DELETE_SCRIPT = `if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('DEL', KEYS[1]) end return 0`;
3034
+ }
3035
+ });
3036
+
3011
3037
  // libs/utils/src/storage/adapters/redis.ts
3012
3038
  var redis_exports = {};
3013
3039
  __export(redis_exports, {
@@ -3051,6 +3077,7 @@ var init_redis = __esm({
3051
3077
  init_errors();
3052
3078
  init_redis_error_listener();
3053
3079
  init_utils();
3080
+ init_compare_and_delete();
3054
3081
  init_base();
3055
3082
  RedisStorageAdapter = class extends BaseStorageAdapter {
3056
3083
  backendName = "redis";
@@ -3205,6 +3232,15 @@ var init_redis = __esm({
3205
3232
  const result = await this.getConnectedClient().del(this.prefixKey(key));
3206
3233
  return result > 0;
3207
3234
  }
3235
+ async deleteIfEquals(key, expectedValue) {
3236
+ const deleted = await this.getConnectedClient().eval(
3237
+ COMPARE_AND_DELETE_SCRIPT,
3238
+ 1,
3239
+ this.prefixKey(key),
3240
+ expectedValue
3241
+ );
3242
+ return deleted === 1;
3243
+ }
3208
3244
  async exists(key) {
3209
3245
  const result = await this.getConnectedClient().exists(this.prefixKey(key));
3210
3246
  return result > 0;
@@ -3413,9 +3449,12 @@ var vercel_kv_exports = {};
3413
3449
  __export(vercel_kv_exports, {
3414
3450
  VercelKvStorageAdapter: () => VercelKvStorageAdapter
3415
3451
  });
3416
- function getVercelKv() {
3452
+ async function loadVercelKv() {
3417
3453
  try {
3418
- return require("@vercel/kv");
3454
+ const mod = await import("@vercel/kv");
3455
+ const resolved = typeof mod.createClient === "function" ? mod : mod.default;
3456
+ if (!resolved || typeof resolved.createClient !== "function") throw new Error("createClient missing");
3457
+ return resolved;
3419
3458
  } catch {
3420
3459
  throw new Error("@vercel/kv is required for Vercel KV storage adapter. Install it with: npm install @vercel/kv");
3421
3460
  }
@@ -3424,9 +3463,10 @@ var VercelKvStorageAdapter;
3424
3463
  var init_vercel_kv = __esm({
3425
3464
  "libs/utils/src/storage/adapters/vercel-kv.ts"() {
3426
3465
  "use strict";
3427
- init_base();
3428
3466
  init_errors();
3467
+ init_compare_and_delete();
3429
3468
  init_ttl();
3469
+ init_base();
3430
3470
  VercelKvStorageAdapter = class extends BaseStorageAdapter {
3431
3471
  backendName = "vercel-kv";
3432
3472
  client;
@@ -3451,17 +3491,13 @@ var init_vercel_kv = __esm({
3451
3491
  async connect() {
3452
3492
  if (this.connected) return;
3453
3493
  try {
3454
- const { createClient, kv } = getVercelKv();
3455
- if (this.options.url === process.env["KV_REST_API_URL"]) {
3456
- this.client = kv;
3457
- } else {
3458
- const url = this.options.url;
3459
- const token = this.options.token;
3460
- if (!url || !token) {
3461
- throw new StorageConfigError("vercel-kv", "URL and token are required");
3462
- }
3463
- this.client = createClient({ url, token });
3494
+ const { createClient } = await loadVercelKv();
3495
+ const url = this.options.url;
3496
+ const token = this.options.token;
3497
+ if (!url || !token) {
3498
+ throw new StorageConfigError("vercel-kv", "URL and token are required");
3464
3499
  }
3500
+ this.client = createClient({ url, token, cache: void 0, automaticDeserialization: false });
3465
3501
  await this.client.exists("__healthcheck__");
3466
3502
  this.connected = true;
3467
3503
  } catch (e) {
@@ -3502,8 +3538,7 @@ var init_vercel_kv = __esm({
3502
3538
  // Core Operations
3503
3539
  // ============================================
3504
3540
  async get(key) {
3505
- const result = await this.getConnectedClient().get(this.prefixKey(key));
3506
- return result;
3541
+ return this.getConnectedClient().get(this.prefixKey(key));
3507
3542
  }
3508
3543
  async doSet(key, value, options) {
3509
3544
  const client = this.getConnectedClient();
@@ -3523,6 +3558,14 @@ var init_vercel_kv = __esm({
3523
3558
  const result = await this.getConnectedClient().del(this.prefixKey(key));
3524
3559
  return result > 0;
3525
3560
  }
3561
+ async deleteIfEquals(key, expectedValue) {
3562
+ const deleted = await this.getConnectedClient().eval(
3563
+ COMPARE_AND_DELETE_SCRIPT,
3564
+ [this.prefixKey(key)],
3565
+ [expectedValue]
3566
+ );
3567
+ return deleted === 1;
3568
+ }
3526
3569
  async exists(key) {
3527
3570
  const result = await this.getConnectedClient().exists(this.prefixKey(key));
3528
3571
  return result > 0;
@@ -3640,9 +3683,10 @@ var PUBSUB_POLL_INTERVAL_MS, UpstashStorageAdapter;
3640
3683
  var init_upstash = __esm({
3641
3684
  "libs/utils/src/storage/adapters/upstash.ts"() {
3642
3685
  "use strict";
3643
- init_base();
3644
3686
  init_errors();
3687
+ init_compare_and_delete();
3645
3688
  init_ttl();
3689
+ init_base();
3646
3690
  PUBSUB_POLL_INTERVAL_MS = 100;
3647
3691
  UpstashStorageAdapter = class extends BaseStorageAdapter {
3648
3692
  backendName = "upstash";
@@ -3679,7 +3723,7 @@ var init_upstash = __esm({
3679
3723
  if (!url || !token) {
3680
3724
  throw new StorageConfigError("upstash", "URL and token are required");
3681
3725
  }
3682
- this.client = new Redis({ url, token });
3726
+ this.client = new Redis({ url, token, automaticDeserialization: false });
3683
3727
  await this.client.exists("__healthcheck__");
3684
3728
  this.connected = true;
3685
3729
  } catch (e) {
@@ -3726,8 +3770,7 @@ var init_upstash = __esm({
3726
3770
  // Core Operations
3727
3771
  // ============================================
3728
3772
  async get(key) {
3729
- const result = await this.getConnectedClient().get(this.prefixKey(key));
3730
- return result;
3773
+ return this.getConnectedClient().get(this.prefixKey(key));
3731
3774
  }
3732
3775
  async doSet(key, value, options) {
3733
3776
  const client = this.getConnectedClient();
@@ -3747,6 +3790,14 @@ var init_upstash = __esm({
3747
3790
  const result = await this.getConnectedClient().del(this.prefixKey(key));
3748
3791
  return result > 0;
3749
3792
  }
3793
+ async deleteIfEquals(key, expectedValue) {
3794
+ const deleted = await this.getConnectedClient().eval(
3795
+ COMPARE_AND_DELETE_SCRIPT,
3796
+ [this.prefixKey(key)],
3797
+ [expectedValue]
3798
+ );
3799
+ return deleted === 1;
3800
+ }
3750
3801
  async exists(key) {
3751
3802
  const result = await this.getConnectedClient().exists(this.prefixKey(key));
3752
3803
  return result > 0;
@@ -3936,7 +3987,9 @@ var init_cloudflare_kv = __esm({
3936
3987
  constructor(options) {
3937
3988
  super();
3938
3989
  if (!options?.namespace) {
3939
- throw new Error("CloudflareKvStorageAdapter: a bound KV `namespace` is required (resolve it from the Worker `env`).");
3990
+ throw new Error(
3991
+ "CloudflareKvStorageAdapter: a bound KV `namespace` is required (resolve it from the Worker `env`)."
3992
+ );
3940
3993
  }
3941
3994
  this.kv = options.namespace;
3942
3995
  this.keyPrefix = options.keyPrefix ?? "";
@@ -4030,6 +4083,13 @@ var init_cloudflare_kv = __esm({
4030
4083
  "Cloudflare KV has no atomic increment (a get+put is racy under eventual consistency). Use a Durable Object for atomic counters."
4031
4084
  );
4032
4085
  }
4086
+ async deleteIfEquals(_key, _expectedValue) {
4087
+ throw new StorageNotSupportedError(
4088
+ "deleteIfEquals",
4089
+ this.backendName,
4090
+ "Cloudflare KV has no compare-and-set; use a Durable Object for an atomic compare-and-delete."
4091
+ );
4092
+ }
4033
4093
  // ── Pub/Sub (unsupported) ────────────────────────────────────────────────
4034
4094
  getPubSubSuggestion() {
4035
4095
  return "Cloudflare KV does not support pub/sub. Use a Durable Object (or Queues) for fan-out.";
@@ -4104,11 +4164,11 @@ __export(index_exports, {
4104
4164
  base64Encode: () => base64Encode,
4105
4165
  base64urlDecode: () => base64urlDecode,
4106
4166
  base64urlEncode: () => base64urlEncode,
4107
- basename: () => import_path.basename,
4167
+ basename: () => import_path2.basename,
4108
4168
  buildPrefix: () => buildPrefix,
4109
4169
  buildSetCookie: () => buildSetCookie,
4110
4170
  bytesToHex: () => bytesToHex,
4111
- checkEntryAvailability: () => checkEntryAvailability,
4171
+ checkEntryAvailability: () => import_runtime_context.checkEntryAvailability,
4112
4172
  classifyIpAddress: () => classifyIpAddress,
4113
4173
  clearCachedSecret: () => clearCachedSecret,
4114
4174
  collapseChar: () => collapseChar,
@@ -4129,15 +4189,15 @@ __export(index_exports, {
4129
4189
  deleteSecret: () => deleteSecret,
4130
4190
  deserializeAndDecrypt: () => deserializeAndDecrypt,
4131
4191
  deserializeBlob: () => deserializeBlob,
4132
- detectRuntimeContext: () => detectRuntimeContext,
4133
- dirname: () => import_path.dirname,
4192
+ detectRuntimeContext: () => import_runtime_context.detectRuntimeContext,
4193
+ dirname: () => import_path2.dirname,
4134
4194
  encryptAesGcm: () => encryptAesGcm,
4135
4195
  encryptAndSerialize: () => encryptAndSerialize,
4136
4196
  encryptValue: () => encryptValue,
4137
4197
  ensureDir: () => ensureDir,
4138
4198
  ensureDirSync: () => ensureDirSync,
4139
4199
  ensureMaxLen: () => ensureMaxLen,
4140
- entryAvailabilitySchema: () => entryAvailabilitySchema,
4200
+ entryAvailabilitySchema: () => import_runtime_context.entryAvailabilitySchema,
4141
4201
  escapeGlob: () => escapeGlob,
4142
4202
  escapeHtml: () => escapeHtml,
4143
4203
  escapeHtmlAttr: () => escapeHtmlAttr,
@@ -4147,7 +4207,7 @@ __export(index_exports, {
4147
4207
  expandTemplate: () => expandTemplate,
4148
4208
  expandUriTemplate: () => expandUriTemplate,
4149
4209
  expiresAtToTTL: () => expiresAtToTTL,
4150
- extname: () => import_path.extname,
4210
+ extname: () => import_path2.extname,
4151
4211
  extractBracedParams: () => extractBracedParams,
4152
4212
  extractEmbeddedIpv4: () => extractEmbeddedIpv4,
4153
4213
  extractTemplateParams: () => extractTemplateParams,
@@ -4162,13 +4222,14 @@ __export(index_exports, {
4162
4222
  getAsyncContextMode: () => import_async_context.getAsyncContextMode,
4163
4223
  getCookie: () => getCookie,
4164
4224
  getCrypto: () => getCrypto,
4165
- getCwd: () => import_env3.getCwd,
4225
+ getCwd: () => import_env2.getCwd,
4166
4226
  getDetectedStorageType: () => getDetectedStorageType,
4167
- getEnv: () => import_env3.getEnv,
4168
- getEnvFlag: () => import_env3.getEnvFlag,
4227
+ getEnv: () => import_env2.getEnv,
4228
+ getEnvFlag: () => import_env2.getEnvFlag,
4169
4229
  getMachineId: () => getMachineId,
4230
+ getNodeEnv: () => import_env2.getNodeEnv,
4170
4231
  getOrCreateSecret: () => getOrCreateSecret,
4171
- getRuntimeContext: () => getRuntimeContext,
4232
+ getRuntimeContext: () => import_runtime_context.getRuntimeContext,
4172
4233
  getSpawnFn: () => getSpawnFn,
4173
4234
  globToRegex: () => globToRegex,
4174
4235
  hasTemplatePlaceholders: () => hasTemplatePlaceholders,
@@ -4176,27 +4237,27 @@ __export(index_exports, {
4176
4237
  hmacSha256: () => hmacSha256,
4177
4238
  idFromString: () => idFromString,
4178
4239
  inferMimeType: () => inferMimeType,
4179
- isAbsolute: () => import_path.isAbsolute,
4240
+ isAbsolute: () => import_path2.isAbsolute,
4180
4241
  isAsymmetricKeyData: () => isAsymmetricKeyData,
4181
4242
  isBrowser: () => isBrowser,
4182
- isDebug: () => import_env3.isDebug,
4183
- isDevelopment: () => import_env3.isDevelopment,
4243
+ isDebug: () => import_env2.isDebug,
4244
+ isDevelopment: () => import_env2.isDevelopment,
4184
4245
  isDirEmpty: () => isDirEmpty,
4185
- isEdgeRuntime: () => import_env3.isEdgeRuntime,
4186
- isEntryAvailable: () => isEntryAvailable,
4246
+ isEdgeRuntime: () => import_env2.isEdgeRuntime,
4247
+ isEntryAvailable: () => import_runtime_context.isEntryAvailable,
4187
4248
  isExpired: () => isExpired,
4188
4249
  isInputLengthSafe: () => isInputLengthSafe,
4189
4250
  isLocalhost: () => isLocalhost,
4190
4251
  isNode: () => isNode,
4191
4252
  isPatternSafe: () => isPatternSafe,
4192
- isProduction: () => import_env3.isProduction,
4253
+ isProduction: () => import_env2.isProduction,
4193
4254
  isRedirectResponse: () => isRedirectResponse,
4194
4255
  isRsaPssAlg: () => isRsaPssAlg,
4195
4256
  isSecretCached: () => isSecretCached,
4196
4257
  isSecretKeyData: () => isSecretKeyData,
4197
4258
  isSecretPersistenceEnabled: () => isSecretPersistenceEnabled,
4198
4259
  isSecureRequest: () => isSecureRequest,
4199
- isServerless: () => import_env3.isServerless,
4260
+ isServerless: () => import_env2.isServerless,
4200
4261
  isSignedData: () => isSignedData,
4201
4262
  isUriTemplate: () => isUriTemplate,
4202
4263
  isValidCodeChallenge: () => isValidCodeChallenge,
@@ -4217,9 +4278,9 @@ __export(index_exports, {
4217
4278
  parseKeyData: () => parseKeyData,
4218
4279
  parseSecretData: () => parseSecretData,
4219
4280
  parseUriTemplate: () => parseUriTemplate,
4220
- pathJoin: () => import_path.join,
4221
- pathResolve: () => import_path.resolve,
4222
- pathToFileURL: () => import_url.pathToFileURL,
4281
+ pathJoin: () => import_path2.join,
4282
+ pathResolve: () => import_path2.resolve,
4283
+ pathToFileURL: () => import_path2.pathToFileURL,
4223
4284
  pemToPublicJwk: () => pemToPublicJwk2,
4224
4285
  processPlatformToolCalls: () => processPlatformToolCalls,
4225
4286
  randomBytes: () => randomBytes,
@@ -4232,7 +4293,7 @@ __export(index_exports, {
4232
4293
  readdirSync: () => readdirSync,
4233
4294
  realpath: () => realpath,
4234
4295
  rename: () => rename,
4235
- resetRuntimeContext: () => resetRuntimeContext,
4296
+ resetRuntimeContext: () => import_runtime_context.resetRuntimeContext,
4236
4297
  resolveSecretPath: () => resolveSecretPath,
4237
4298
  rm: () => rm,
4238
4299
  rsaSignBase64Url: () => rsaSignBase64Url2,
@@ -4250,10 +4311,10 @@ __export(index_exports, {
4250
4311
  saveSecret: () => saveSecret,
4251
4312
  secretDataSchema: () => secretDataSchema,
4252
4313
  secretKeyDataSchema: () => secretKeyDataSchema,
4253
- sep: () => import_path.sep,
4314
+ sep: () => import_path2.sep,
4254
4315
  sepFor: () => sepFor,
4255
4316
  serializeBlob: () => serializeBlob,
4256
- setEnv: () => import_env3.setEnv,
4317
+ setEnv: () => import_env2.setEnv,
4257
4318
  setMachineIdOverride: () => setMachineIdOverride,
4258
4319
  sha256: () => sha256,
4259
4320
  sha256Base64url: () => sha256Base64url,
@@ -4262,7 +4323,7 @@ __export(index_exports, {
4262
4323
  signData: () => signData,
4263
4324
  splitWords: () => splitWords,
4264
4325
  stat: () => stat,
4265
- supportsAnsi: () => import_env3.supportsAnsi,
4326
+ supportsAnsi: () => import_env2.supportsAnsi,
4266
4327
  symlink: () => symlink,
4267
4328
  timingSafeEqual: () => timingSafeEqual,
4268
4329
  toCase: () => toCase,
@@ -4692,9 +4753,8 @@ function joinPath(...parts) {
4692
4753
  return cleaned.length ? `/${cleaned.join("/")}` : "";
4693
4754
  }
4694
4755
 
4695
- // libs/utils/src/path/node-path.ts
4696
- var import_path = require("path");
4697
- var import_url = require("url");
4756
+ // libs/utils/src/path/index.ts
4757
+ var import_path2 = require("#path");
4698
4758
 
4699
4759
  // libs/utils/src/content/content.ts
4700
4760
  function sanitizeToJson(value) {
@@ -5112,167 +5172,14 @@ var import_async_context = require("#async-context");
5112
5172
  var import_event_emitter2 = require("#event-emitter");
5113
5173
 
5114
5174
  // libs/utils/src/env/index.ts
5115
- var import_env3 = require("#env");
5116
-
5117
- // libs/utils/src/env/runtime-context.ts
5118
- var import_lazy_zod3 = require("@frontmcp/lazy-zod");
5119
5175
  var import_env2 = require("#env");
5120
-
5121
- // libs/utils/src/env/build-target.ts
5122
- var cached;
5123
- function getBuildTarget() {
5124
- if (cached) return cached;
5125
- cached = resolveBuildTarget();
5126
- return cached;
5127
- }
5128
- function resolveBuildTarget() {
5129
- const globalAny = globalThis;
5130
- const fromGlobal = globalAny.FRONTMCP_BUILD_TARGET;
5131
- if (typeof fromGlobal === "string" && isKnownTarget(fromGlobal)) return fromGlobal;
5132
- const fromEnv = typeof process !== "undefined" ? process.env?.["FRONTMCP_BUILD_TARGET"] : void 0;
5133
- if (typeof fromEnv === "string" && isKnownTarget(fromEnv)) return fromEnv;
5134
- return "unknown";
5135
- }
5136
- function isKnownTarget(value) {
5137
- return value === "unknown" || value === "node" || value === "distributed" || value === "cli" || value === "vercel" || value === "lambda" || value === "cloudflare" || value === "browser" || value === "sdk" || value === "mcpb";
5138
- }
5139
-
5140
- // libs/utils/src/env/provider.ts
5141
- var cached2;
5142
- function detectProvider() {
5143
- if (cached2) return cached2;
5144
- cached2 = detectProviderUncached();
5145
- return cached2;
5146
- }
5147
- function detectProviderUncached() {
5148
- const explicit = process.env["FRONTMCP_PROVIDER"];
5149
- if (explicit && isKnownProvider(explicit)) return explicit;
5150
- if (process.env["VERCEL"]) return "vercel";
5151
- if (process.env["AWS_LAMBDA_FUNCTION_NAME"]) return "lambda";
5152
- if (process.env["CF_PAGES"]) return "cloudflare";
5153
- if (process.env["NETLIFY"]) return "netlify";
5154
- if (process.env["AZURE_FUNCTIONS_ENVIRONMENT"]) return "azure";
5155
- if (process.env["K_SERVICE"]) return "gcp";
5156
- if (process.env["FLY_APP_NAME"]) return "fly";
5157
- if (process.env["RENDER"]) return "render";
5158
- if (process.env["RAILWAY_ENVIRONMENT"]) return "railway";
5159
- try {
5160
- const nodeFs = require("node:fs");
5161
- if (nodeFs.existsSync("/.dockerenv")) return "docker";
5162
- } catch {
5163
- }
5164
- return "bare";
5165
- }
5166
- function isKnownProvider(value) {
5167
- return value === "bare" || value === "docker" || value === "vercel" || value === "lambda" || value === "cloudflare" || value === "netlify" || value === "azure" || value === "gcp" || value === "fly" || value === "render" || value === "railway";
5168
- }
5169
-
5170
- // libs/utils/src/env/runtime-context.ts
5171
- var entryAvailabilitySchema = import_lazy_zod3.z.object({
5172
- os: import_lazy_zod3.z.array(import_lazy_zod3.z.string().min(1)).optional(),
5173
- platform: import_lazy_zod3.z.array(import_lazy_zod3.z.string().min(1)).optional(),
5174
- runtime: import_lazy_zod3.z.array(import_lazy_zod3.z.string().min(1)).optional(),
5175
- deployment: import_lazy_zod3.z.array(import_lazy_zod3.z.string().min(1)).optional(),
5176
- provider: import_lazy_zod3.z.array(import_lazy_zod3.z.string().min(1)).optional(),
5177
- target: import_lazy_zod3.z.array(import_lazy_zod3.z.string().min(1)).optional(),
5178
- surface: import_lazy_zod3.z.array(import_lazy_zod3.z.enum(["mcp", "cli", "http-trigger", "job", "agent"])).optional(),
5179
- env: import_lazy_zod3.z.array(import_lazy_zod3.z.string().min(1)).optional()
5180
- }).strict();
5181
- var PROCESS_AXES = [
5182
- // `os` and `platform` both compare against the same RuntimeContext value
5183
- // — keeping `platform` as a deprecated alias lets pre-#417 metadata
5184
- // continue to match without any code change.
5185
- { key: "os", ctxKey: "os" },
5186
- { key: "platform", ctxKey: "platform" },
5187
- { key: "runtime", ctxKey: "runtime" },
5188
- { key: "deployment", ctxKey: "deployment" },
5189
- { key: "provider", ctxKey: "provider" },
5190
- { key: "target", ctxKey: "target" },
5191
- { key: "env", ctxKey: "env" }
5192
- ];
5193
- function isEntryAvailable(availability, ctx, callCtx) {
5194
- if (!availability) return true;
5195
- for (const { key, ctxKey } of PROCESS_AXES) {
5196
- const allowed = availability[key];
5197
- if (allowed === void 0) continue;
5198
- if (allowed.length === 0) return false;
5199
- if (!allowed.includes(ctx[ctxKey])) return false;
5200
- }
5201
- if (availability.surface !== void 0) {
5202
- if (availability.surface.length === 0) return false;
5203
- if (callCtx?.surface !== void 0 && !availability.surface.includes(callCtx.surface)) {
5204
- return false;
5205
- }
5206
- }
5207
- return true;
5208
- }
5209
- function checkEntryAvailability(availability, ctx, callCtx) {
5210
- if (!availability) return { available: true, missingAxes: [] };
5211
- const missing = [];
5212
- for (const { key, ctxKey } of PROCESS_AXES) {
5213
- const allowed = availability[key];
5214
- if (allowed === void 0) continue;
5215
- if (allowed.length === 0 || !allowed.includes(ctx[ctxKey])) {
5216
- missing.push(key);
5217
- }
5218
- }
5219
- if (availability.surface !== void 0) {
5220
- if (availability.surface.length === 0) {
5221
- missing.push("surface");
5222
- } else if (callCtx?.surface !== void 0 && !availability.surface.includes(callCtx.surface)) {
5223
- missing.push("surface");
5224
- }
5225
- }
5226
- return { available: missing.length === 0, missingAxes: missing };
5227
- }
5228
- function detectRuntime() {
5229
- if (typeof globalThis !== "undefined" && "Bun" in globalThis) return "bun";
5230
- if (typeof globalThis !== "undefined" && "Deno" in globalThis) return "deno";
5231
- if ((0, import_env2.isEdgeRuntime)()) return "edge";
5232
- return "node";
5233
- }
5234
- function detectDeployment(runtime) {
5235
- const explicit = process.env["FRONTMCP_DEPLOYMENT_MODE"];
5236
- if (explicit === "distributed") return "distributed";
5237
- if (explicit === "serverless") return "serverless";
5238
- if (runtime === "browser") return "browser";
5239
- if ((0, import_env2.isServerless)()) return "serverless";
5240
- return "standalone";
5241
- }
5242
- function detectRuntimeContext() {
5243
- const runtime = detectRuntime();
5244
- const os = process.platform;
5245
- return {
5246
- os,
5247
- platform: os,
5248
- runtime,
5249
- deployment: detectDeployment(runtime),
5250
- provider: detectProvider(),
5251
- target: getBuildTarget(),
5252
- env: process.env["NODE_ENV"] || "development"
5253
- };
5254
- }
5255
- var cached3;
5256
- function getRuntimeContext() {
5257
- if (!cached3) {
5258
- const detected = detectRuntimeContext();
5259
- Object.defineProperty(detected, "env", {
5260
- get: () => process.env["NODE_ENV"] || "development",
5261
- enumerable: true,
5262
- configurable: true
5263
- });
5264
- cached3 = detected;
5265
- }
5266
- return cached3;
5267
- }
5268
- function resetRuntimeContext() {
5269
- cached3 = void 0;
5270
- }
5176
+ var import_runtime_context = require("#runtime-context");
5271
5177
 
5272
5178
  // libs/utils/src/storage/factory.ts
5273
5179
  init_errors();
5274
5180
 
5275
5181
  // libs/utils/src/storage/namespace.ts
5182
+ init_errors();
5276
5183
  var NAMESPACE_SEPARATOR = ":";
5277
5184
  function buildPrefix(name, id) {
5278
5185
  if (id) {
@@ -5404,6 +5311,12 @@ var NamespacedStorageImpl = class _NamespacedStorageImpl {
5404
5311
  async incrBy(key, amount) {
5405
5312
  return this.adapter.incrBy(this.prefixKey(key), amount);
5406
5313
  }
5314
+ async deleteIfEquals(key, expectedValue) {
5315
+ if (!this.adapter.deleteIfEquals) {
5316
+ throw new StorageNotSupportedError("deleteIfEquals", "this storage adapter");
5317
+ }
5318
+ return this.adapter.deleteIfEquals(this.prefixKey(key), expectedValue);
5319
+ }
5407
5320
  // ============================================
5408
5321
  // Pub/Sub (with channel prefixing)
5409
5322
  // ============================================
@@ -5432,15 +5345,15 @@ function createNamespacedStorage(adapter, prefix) {
5432
5345
 
5433
5346
  // libs/utils/src/storage/factory.ts
5434
5347
  init_memory();
5435
- var import_env4 = require("#env");
5348
+ var import_env3 = require("#env");
5436
5349
  function detectStorageType() {
5437
- if ((0, import_env4.getEnv)("UPSTASH_REDIS_REST_URL") && (0, import_env4.getEnv)("UPSTASH_REDIS_REST_TOKEN")) {
5350
+ if ((0, import_env3.getEnv)("UPSTASH_REDIS_REST_URL") && (0, import_env3.getEnv)("UPSTASH_REDIS_REST_TOKEN")) {
5438
5351
  return "upstash";
5439
5352
  }
5440
- if ((0, import_env4.getEnv)("KV_REST_API_URL") && (0, import_env4.getEnv)("KV_REST_API_TOKEN")) {
5353
+ if ((0, import_env3.getEnv)("KV_REST_API_URL") && (0, import_env3.getEnv)("KV_REST_API_TOKEN")) {
5441
5354
  return "vercel-kv";
5442
5355
  }
5443
- if ((0, import_env4.getEnv)("REDIS_URL") || (0, import_env4.getEnv)("REDIS_HOST")) {
5356
+ if ((0, import_env3.getEnv)("REDIS_URL") || (0, import_env3.getEnv)("REDIS_HOST")) {
5444
5357
  return "redis";
5445
5358
  }
5446
5359
  return "memory";
@@ -5480,10 +5393,10 @@ async function createAdapter(type, config) {
5480
5393
  }
5481
5394
  async function createStorage(config = {}) {
5482
5395
  let type = config.type ?? "auto";
5483
- const fallback = config.fallback ?? ((0, import_env4.isProduction)() ? "error" : "memory");
5396
+ const fallback = config.fallback ?? ((0, import_env3.isProduction)() ? "error" : "memory");
5484
5397
  if (type === "auto") {
5485
5398
  type = detectStorageType();
5486
- if (type === "memory" && (0, import_env4.isProduction)()) {
5399
+ if (type === "memory" && (0, import_env3.isProduction)()) {
5487
5400
  console.warn(
5488
5401
  "[storage] Warning: No distributed storage backend detected in production. Using in-memory storage. Set REDIS_URL, UPSTASH_REDIS_REST_URL, or KV_REST_API_URL."
5489
5402
  );
@@ -6290,6 +6203,7 @@ function setMachineIdOverride(id) {
6290
6203
  getEnv,
6291
6204
  getEnvFlag,
6292
6205
  getMachineId,
6206
+ getNodeEnv,
6293
6207
  getOrCreateSecret,
6294
6208
  getRuntimeContext,
6295
6209
  getSpawnFn,