@frontmcp/utils 1.4.0 → 1.5.0-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/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 +1 -1
- package/esm/env/node-env.mjs +1 -1
- package/esm/event-emitter/browser-event-emitter.mjs +1 -1
- package/esm/event-emitter/node-event-emitter.mjs +1 -1
- package/esm/index.mjs +200 -20
- package/index.js +199 -19
- package/machine-id/machine-id.d.ts +2 -1
- package/package.json +5 -5
- package/storage/adapters/cloudflare-kv.d.ts +26 -0
- package/storage/adapters/index.d.ts +1 -0
- package/storage/types.d.ts +39 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire as __frontmcpCreateRequire } from 'module';
|
|
2
|
-
const require = __frontmcpCreateRequire(import.meta.url);
|
|
2
|
+
const require = __frontmcpCreateRequire(import.meta.url || 'file:///');
|
|
3
3
|
// libs/utils/src/async-context/browser-async-context.ts
|
|
4
4
|
var AsyncLocalStorage = class {
|
|
5
5
|
stack = [];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire as __frontmcpCreateRequire } from 'module';
|
|
2
|
-
const require = __frontmcpCreateRequire(import.meta.url);
|
|
2
|
+
const require = __frontmcpCreateRequire(import.meta.url || 'file:///');
|
|
3
3
|
// libs/utils/src/async-context/node-async-context.ts
|
|
4
4
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
5
5
|
export {
|
package/esm/crypto/browser.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire as __frontmcpCreateRequire } from 'module';
|
|
2
|
-
const require = __frontmcpCreateRequire(import.meta.url);
|
|
2
|
+
const require = __frontmcpCreateRequire(import.meta.url || 'file:///');
|
|
3
3
|
// libs/utils/src/crypto/browser.ts
|
|
4
4
|
import { sha256 as sha256Hash } from "@noble/hashes/sha2.js";
|
|
5
5
|
import { hmac } from "@noble/hashes/hmac.js";
|
package/esm/crypto/node.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire as __frontmcpCreateRequire } from 'module';
|
|
2
|
-
const require = __frontmcpCreateRequire(import.meta.url);
|
|
2
|
+
const require = __frontmcpCreateRequire(import.meta.url || 'file:///');
|
|
3
3
|
// libs/utils/src/crypto/node.ts
|
|
4
4
|
import crypto from "node:crypto";
|
|
5
5
|
|
package/esm/env/browser-env.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire as __frontmcpCreateRequire } from 'module';
|
|
2
|
-
const require = __frontmcpCreateRequire(import.meta.url);
|
|
2
|
+
const require = __frontmcpCreateRequire(import.meta.url || 'file:///');
|
|
3
3
|
// libs/utils/src/env/browser-env.ts
|
|
4
4
|
function getEnv(_key, defaultValue) {
|
|
5
5
|
return defaultValue;
|
package/esm/env/node-env.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire as __frontmcpCreateRequire } from 'module';
|
|
2
|
-
const require = __frontmcpCreateRequire(import.meta.url);
|
|
2
|
+
const require = __frontmcpCreateRequire(import.meta.url || 'file:///');
|
|
3
3
|
// libs/utils/src/env/node-env.ts
|
|
4
4
|
function getEnv(key, defaultValue) {
|
|
5
5
|
return process.env[key] ?? defaultValue;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire as __frontmcpCreateRequire } from 'module';
|
|
2
|
-
const require = __frontmcpCreateRequire(import.meta.url);
|
|
2
|
+
const require = __frontmcpCreateRequire(import.meta.url || 'file:///');
|
|
3
3
|
// libs/utils/src/event-emitter/browser-event-emitter.ts
|
|
4
4
|
var EventEmitter = class {
|
|
5
5
|
events = /* @__PURE__ */ new Map();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire as __frontmcpCreateRequire } from 'module';
|
|
2
|
-
const require = __frontmcpCreateRequire(import.meta.url);
|
|
2
|
+
const require = __frontmcpCreateRequire(import.meta.url || 'file:///');
|
|
3
3
|
// libs/utils/src/event-emitter/node-event-emitter.ts
|
|
4
4
|
import { EventEmitter } from "events";
|
|
5
5
|
export {
|
package/esm/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire as __frontmcpCreateRequire } from 'module';
|
|
2
|
-
const require = __frontmcpCreateRequire(import.meta.url);
|
|
2
|
+
const require = __frontmcpCreateRequire(import.meta.url || 'file:///');
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -10,8 +10,13 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
10
10
|
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
11
11
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
12
12
|
});
|
|
13
|
-
var __esm = (fn, res) => function __init() {
|
|
14
|
-
|
|
13
|
+
var __esm = (fn, res, err) => function __init() {
|
|
14
|
+
if (err) throw err[0];
|
|
15
|
+
try {
|
|
16
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
17
|
+
} catch (e) {
|
|
18
|
+
throw err = [e], e;
|
|
19
|
+
}
|
|
15
20
|
};
|
|
16
21
|
var __export = (target, all) => {
|
|
17
22
|
for (var name in all)
|
|
@@ -75,8 +80,8 @@ async function readFile(p, encoding = "utf8") {
|
|
|
75
80
|
return fsp.readFile(p, encoding);
|
|
76
81
|
}
|
|
77
82
|
function readFileSync(p, encoding = "utf8") {
|
|
78
|
-
const
|
|
79
|
-
return
|
|
83
|
+
const fs = getFs();
|
|
84
|
+
return fs.readFileSync(p, encoding);
|
|
80
85
|
}
|
|
81
86
|
async function readFileBuffer(p) {
|
|
82
87
|
const fsp = getFsp();
|
|
@@ -91,8 +96,8 @@ async function mkdir(p, options) {
|
|
|
91
96
|
await fsp.mkdir(p, options);
|
|
92
97
|
}
|
|
93
98
|
function ensureDirSync(p) {
|
|
94
|
-
const
|
|
95
|
-
|
|
99
|
+
const fs = getFs();
|
|
100
|
+
fs.mkdirSync(p, { recursive: true });
|
|
96
101
|
}
|
|
97
102
|
async function rename(oldPath, newPath) {
|
|
98
103
|
const fsp = getFsp();
|
|
@@ -153,8 +158,8 @@ async function readdir(p) {
|
|
|
153
158
|
return fsp.readdir(p);
|
|
154
159
|
}
|
|
155
160
|
function readdirSync(p) {
|
|
156
|
-
const
|
|
157
|
-
return
|
|
161
|
+
const fs = getFs();
|
|
162
|
+
return fs.readdirSync(p);
|
|
158
163
|
}
|
|
159
164
|
async function rm(p, options) {
|
|
160
165
|
const fsp = getFsp();
|
|
@@ -187,8 +192,8 @@ function runCmd(cmd, args, opts = {}) {
|
|
|
187
192
|
});
|
|
188
193
|
}
|
|
189
194
|
function watchFile(p, onChange, options) {
|
|
190
|
-
const
|
|
191
|
-
const watcher =
|
|
195
|
+
const fs = getFs();
|
|
196
|
+
const watcher = fs.watch(p, { persistent: false, recursive: options?.recursive === true }, (eventType, filename) => {
|
|
192
197
|
onChange(eventType, filename);
|
|
193
198
|
});
|
|
194
199
|
return {
|
|
@@ -1016,6 +1021,7 @@ var init_errors = __esm({
|
|
|
1016
1021
|
this.backend = backend;
|
|
1017
1022
|
this.name = "StorageConnectionError";
|
|
1018
1023
|
}
|
|
1024
|
+
backend;
|
|
1019
1025
|
};
|
|
1020
1026
|
StorageOperationError = class extends StorageError {
|
|
1021
1027
|
constructor(operation, key, message, cause) {
|
|
@@ -1024,6 +1030,8 @@ var init_errors = __esm({
|
|
|
1024
1030
|
this.key = key;
|
|
1025
1031
|
this.name = "StorageOperationError";
|
|
1026
1032
|
}
|
|
1033
|
+
operation;
|
|
1034
|
+
key;
|
|
1027
1035
|
};
|
|
1028
1036
|
StorageNotSupportedError = class extends StorageError {
|
|
1029
1037
|
constructor(operation, backend, suggestion) {
|
|
@@ -1033,6 +1041,8 @@ var init_errors = __esm({
|
|
|
1033
1041
|
this.backend = backend;
|
|
1034
1042
|
this.name = "StorageNotSupportedError";
|
|
1035
1043
|
}
|
|
1044
|
+
operation;
|
|
1045
|
+
backend;
|
|
1036
1046
|
};
|
|
1037
1047
|
StorageConfigError = class extends StorageError {
|
|
1038
1048
|
constructor(backend, message) {
|
|
@@ -1040,6 +1050,7 @@ var init_errors = __esm({
|
|
|
1040
1050
|
this.backend = backend;
|
|
1041
1051
|
this.name = "StorageConfigError";
|
|
1042
1052
|
}
|
|
1053
|
+
backend;
|
|
1043
1054
|
};
|
|
1044
1055
|
StorageTTLError = class extends StorageError {
|
|
1045
1056
|
constructor(ttl, message) {
|
|
@@ -1047,6 +1058,7 @@ var init_errors = __esm({
|
|
|
1047
1058
|
this.ttl = ttl;
|
|
1048
1059
|
this.name = "StorageTTLError";
|
|
1049
1060
|
}
|
|
1061
|
+
ttl;
|
|
1050
1062
|
};
|
|
1051
1063
|
StoragePatternError = class extends StorageError {
|
|
1052
1064
|
constructor(pattern, message) {
|
|
@@ -1054,6 +1066,7 @@ var init_errors = __esm({
|
|
|
1054
1066
|
this.pattern = pattern;
|
|
1055
1067
|
this.name = "StoragePatternError";
|
|
1056
1068
|
}
|
|
1069
|
+
pattern;
|
|
1057
1070
|
};
|
|
1058
1071
|
StorageNotConnectedError = class extends StorageError {
|
|
1059
1072
|
constructor(backend) {
|
|
@@ -1061,6 +1074,7 @@ var init_errors = __esm({
|
|
|
1061
1074
|
this.backend = backend;
|
|
1062
1075
|
this.name = "StorageNotConnectedError";
|
|
1063
1076
|
}
|
|
1077
|
+
backend;
|
|
1064
1078
|
};
|
|
1065
1079
|
EncryptedStorageError = class extends StorageError {
|
|
1066
1080
|
constructor(message) {
|
|
@@ -3809,6 +3823,154 @@ var init_upstash = __esm({
|
|
|
3809
3823
|
}
|
|
3810
3824
|
});
|
|
3811
3825
|
|
|
3826
|
+
// libs/utils/src/storage/adapters/cloudflare-kv.ts
|
|
3827
|
+
var cloudflare_kv_exports = {};
|
|
3828
|
+
__export(cloudflare_kv_exports, {
|
|
3829
|
+
CloudflareKvStorageAdapter: () => CloudflareKvStorageAdapter
|
|
3830
|
+
});
|
|
3831
|
+
function literalPrefix(pattern) {
|
|
3832
|
+
const star = pattern.indexOf("*");
|
|
3833
|
+
const q = pattern.indexOf("?");
|
|
3834
|
+
const idx = star === -1 ? q : q === -1 ? star : Math.min(star, q);
|
|
3835
|
+
return idx === -1 ? pattern : pattern.slice(0, idx);
|
|
3836
|
+
}
|
|
3837
|
+
var CF_KV_MIN_TTL_SECONDS, CloudflareKvStorageAdapter;
|
|
3838
|
+
var init_cloudflare_kv = __esm({
|
|
3839
|
+
"libs/utils/src/storage/adapters/cloudflare-kv.ts"() {
|
|
3840
|
+
"use strict";
|
|
3841
|
+
init_errors();
|
|
3842
|
+
init_pattern();
|
|
3843
|
+
init_ttl();
|
|
3844
|
+
init_base();
|
|
3845
|
+
CF_KV_MIN_TTL_SECONDS = 60;
|
|
3846
|
+
CloudflareKvStorageAdapter = class extends BaseStorageAdapter {
|
|
3847
|
+
backendName = "cloudflare-kv";
|
|
3848
|
+
kv;
|
|
3849
|
+
keyPrefix;
|
|
3850
|
+
constructor(options) {
|
|
3851
|
+
super();
|
|
3852
|
+
if (!options?.namespace) {
|
|
3853
|
+
throw new Error("CloudflareKvStorageAdapter: a bound KV `namespace` is required (resolve it from the Worker `env`).");
|
|
3854
|
+
}
|
|
3855
|
+
this.kv = options.namespace;
|
|
3856
|
+
this.keyPrefix = options.keyPrefix ?? "";
|
|
3857
|
+
}
|
|
3858
|
+
// ── Lifecycle ──────────────────────────────────────────────────────────
|
|
3859
|
+
// A KV binding is always available; "connection" is just a readiness flag.
|
|
3860
|
+
async connect() {
|
|
3861
|
+
this.connected = true;
|
|
3862
|
+
}
|
|
3863
|
+
async disconnect() {
|
|
3864
|
+
this.connected = false;
|
|
3865
|
+
}
|
|
3866
|
+
async ping() {
|
|
3867
|
+
if (!this.connected) return false;
|
|
3868
|
+
try {
|
|
3869
|
+
await this.kv.list({ limit: 1 });
|
|
3870
|
+
return true;
|
|
3871
|
+
} catch {
|
|
3872
|
+
return false;
|
|
3873
|
+
}
|
|
3874
|
+
}
|
|
3875
|
+
// ── Core ───────────────────────────────────────────────────────────────
|
|
3876
|
+
async get(key) {
|
|
3877
|
+
this.ensureConnected();
|
|
3878
|
+
return this.kv.get(this.prefixKey(key), "text");
|
|
3879
|
+
}
|
|
3880
|
+
async doSet(key, value, options) {
|
|
3881
|
+
if (options?.ifNotExists || options?.ifExists) {
|
|
3882
|
+
throw new StorageNotSupportedError(
|
|
3883
|
+
"conditional set (ifNotExists/ifExists)",
|
|
3884
|
+
this.backendName,
|
|
3885
|
+
"Cloudflare KV has no compare-and-set; use a Durable Object for atomic conditional writes."
|
|
3886
|
+
);
|
|
3887
|
+
}
|
|
3888
|
+
const putOptions = options?.ttlSeconds !== void 0 ? { expirationTtl: this.toExpirationTtl(options.ttlSeconds, key) } : void 0;
|
|
3889
|
+
await this.kv.put(this.prefixKey(key), value, putOptions);
|
|
3890
|
+
}
|
|
3891
|
+
async delete(key) {
|
|
3892
|
+
this.ensureConnected();
|
|
3893
|
+
const existed = await this.exists(key);
|
|
3894
|
+
await this.kv.delete(this.prefixKey(key));
|
|
3895
|
+
return existed;
|
|
3896
|
+
}
|
|
3897
|
+
async exists(key) {
|
|
3898
|
+
this.ensureConnected();
|
|
3899
|
+
return await this.kv.get(this.prefixKey(key), "text") !== null;
|
|
3900
|
+
}
|
|
3901
|
+
// ── TTL ────────────────────────────────────────────────────────────────
|
|
3902
|
+
async expire(key, ttlSeconds) {
|
|
3903
|
+
this.ensureConnected();
|
|
3904
|
+
const ttl = this.toExpirationTtl(ttlSeconds, key);
|
|
3905
|
+
const value = await this.kv.get(this.prefixKey(key), "text");
|
|
3906
|
+
if (value === null) return false;
|
|
3907
|
+
await this.kv.put(this.prefixKey(key), value, { expirationTtl: ttl });
|
|
3908
|
+
return true;
|
|
3909
|
+
}
|
|
3910
|
+
async ttl(_key) {
|
|
3911
|
+
throw new StorageNotSupportedError(
|
|
3912
|
+
"ttl",
|
|
3913
|
+
this.backendName,
|
|
3914
|
+
"Cloudflare KV does not expose a key's remaining TTL. Track expiry alongside the value if you need it."
|
|
3915
|
+
);
|
|
3916
|
+
}
|
|
3917
|
+
// ── Enumeration ──────────────────────────────────────────────────────────
|
|
3918
|
+
async keys(pattern = "*") {
|
|
3919
|
+
this.ensureConnected();
|
|
3920
|
+
const prefixedPattern = this.prefixKey(pattern);
|
|
3921
|
+
const listPrefix = literalPrefix(prefixedPattern);
|
|
3922
|
+
const out = [];
|
|
3923
|
+
let cursor;
|
|
3924
|
+
do {
|
|
3925
|
+
const page = await this.kv.list({ prefix: listPrefix || void 0, cursor });
|
|
3926
|
+
for (const { name } of page.keys) {
|
|
3927
|
+
if (matchesPattern(name, prefixedPattern)) out.push(this.unprefixKey(name));
|
|
3928
|
+
}
|
|
3929
|
+
cursor = page.list_complete ? void 0 : page.cursor;
|
|
3930
|
+
} while (cursor);
|
|
3931
|
+
return out;
|
|
3932
|
+
}
|
|
3933
|
+
// ── Atomic (unsupported on KV) ───────────────────────────────────────────
|
|
3934
|
+
async incr(key) {
|
|
3935
|
+
return this.incrBy(key, 1);
|
|
3936
|
+
}
|
|
3937
|
+
async decr(key) {
|
|
3938
|
+
return this.incrBy(key, -1);
|
|
3939
|
+
}
|
|
3940
|
+
async incrBy(_key, _amount) {
|
|
3941
|
+
throw new StorageNotSupportedError(
|
|
3942
|
+
"incr/decr/incrBy",
|
|
3943
|
+
this.backendName,
|
|
3944
|
+
"Cloudflare KV has no atomic increment (a get+put is racy under eventual consistency). Use a Durable Object for atomic counters."
|
|
3945
|
+
);
|
|
3946
|
+
}
|
|
3947
|
+
// ── Pub/Sub (unsupported) ────────────────────────────────────────────────
|
|
3948
|
+
getPubSubSuggestion() {
|
|
3949
|
+
return "Cloudflare KV does not support pub/sub. Use a Durable Object (or Queues) for fan-out.";
|
|
3950
|
+
}
|
|
3951
|
+
// ── Helpers ──────────────────────────────────────────────────────────────
|
|
3952
|
+
/** Validate + enforce KV's 60s minimum `expirationTtl`. */
|
|
3953
|
+
toExpirationTtl(ttlSeconds, key) {
|
|
3954
|
+
validateTTL(ttlSeconds);
|
|
3955
|
+
if (ttlSeconds < CF_KV_MIN_TTL_SECONDS) {
|
|
3956
|
+
throw new StorageOperationError(
|
|
3957
|
+
"set",
|
|
3958
|
+
key,
|
|
3959
|
+
`cloudflare-kv: expirationTtl must be >= ${CF_KV_MIN_TTL_SECONDS}s (Cloudflare KV minimum); got ${ttlSeconds}s.`
|
|
3960
|
+
);
|
|
3961
|
+
}
|
|
3962
|
+
return ttlSeconds;
|
|
3963
|
+
}
|
|
3964
|
+
prefixKey(key) {
|
|
3965
|
+
return this.keyPrefix + key;
|
|
3966
|
+
}
|
|
3967
|
+
unprefixKey(key) {
|
|
3968
|
+
return this.keyPrefix && key.startsWith(this.keyPrefix) ? key.slice(this.keyPrefix.length) : key;
|
|
3969
|
+
}
|
|
3970
|
+
};
|
|
3971
|
+
}
|
|
3972
|
+
});
|
|
3973
|
+
|
|
3812
3974
|
// libs/utils/src/regex/safe-regex.ts
|
|
3813
3975
|
import { analyzeForReDoS, REDOS_THRESHOLDS } from "@enclave-vm/ast";
|
|
3814
3976
|
var DEFAULT_MAX_INPUT_LENGTH = 5e4;
|
|
@@ -4532,7 +4694,6 @@ function isKnownTarget(value) {
|
|
|
4532
4694
|
}
|
|
4533
4695
|
|
|
4534
4696
|
// libs/utils/src/env/provider.ts
|
|
4535
|
-
import * as fs from "node:fs";
|
|
4536
4697
|
var cached2;
|
|
4537
4698
|
function detectProvider() {
|
|
4538
4699
|
if (cached2) return cached2;
|
|
@@ -4552,7 +4713,8 @@ function detectProviderUncached() {
|
|
|
4552
4713
|
if (process.env["RENDER"]) return "render";
|
|
4553
4714
|
if (process.env["RAILWAY_ENVIRONMENT"]) return "railway";
|
|
4554
4715
|
try {
|
|
4555
|
-
|
|
4716
|
+
const nodeFs = __require("node:fs");
|
|
4717
|
+
if (nodeFs.existsSync("/.dockerenv")) return "docker";
|
|
4556
4718
|
} catch {
|
|
4557
4719
|
}
|
|
4558
4720
|
return "bare";
|
|
@@ -4674,6 +4836,9 @@ var NamespacedStorageImpl = class _NamespacedStorageImpl {
|
|
|
4674
4836
|
this.prefix = prefix;
|
|
4675
4837
|
this.root = root;
|
|
4676
4838
|
}
|
|
4839
|
+
adapter;
|
|
4840
|
+
prefix;
|
|
4841
|
+
root;
|
|
4677
4842
|
// ============================================
|
|
4678
4843
|
// Key Prefixing Helpers
|
|
4679
4844
|
// ============================================
|
|
@@ -4847,6 +5012,16 @@ async function createAdapter(type, config) {
|
|
|
4847
5012
|
const { UpstashStorageAdapter: UpstashStorageAdapter2 } = await Promise.resolve().then(() => (init_upstash(), upstash_exports));
|
|
4848
5013
|
return new UpstashStorageAdapter2(config.upstash);
|
|
4849
5014
|
}
|
|
5015
|
+
case "cloudflare-kv": {
|
|
5016
|
+
if (!config.cloudflareKv) {
|
|
5017
|
+
throw new StorageConfigError(
|
|
5018
|
+
"cloudflare-kv",
|
|
5019
|
+
"cloudflare-kv requires `cloudflareKv: { namespace }` (the KV binding can't be auto-detected)"
|
|
5020
|
+
);
|
|
5021
|
+
}
|
|
5022
|
+
const { CloudflareKvStorageAdapter: CloudflareKvStorageAdapter2 } = await Promise.resolve().then(() => (init_cloudflare_kv(), cloudflare_kv_exports));
|
|
5023
|
+
return new CloudflareKvStorageAdapter2(config.cloudflareKv);
|
|
5024
|
+
}
|
|
4850
5025
|
case "auto":
|
|
4851
5026
|
throw new StorageConfigError("auto", "Auto type should be resolved before calling createAdapter");
|
|
4852
5027
|
default:
|
|
@@ -5495,8 +5670,8 @@ function loadMachineIdSync() {
|
|
|
5495
5670
|
if (!isDevPersistenceEnabled()) return null;
|
|
5496
5671
|
const machineIdPath = resolveMachineIdPath();
|
|
5497
5672
|
try {
|
|
5498
|
-
const
|
|
5499
|
-
const content =
|
|
5673
|
+
const fs = __require("fs");
|
|
5674
|
+
const content = fs.readFileSync(machineIdPath, "utf8").trim();
|
|
5500
5675
|
if (/^[0-9a-f-]{32,36}$/i.test(content)) return content;
|
|
5501
5676
|
console.warn(`[MachineId] Invalid format at ${machineIdPath}, will regenerate`);
|
|
5502
5677
|
return null;
|
|
@@ -5507,7 +5682,7 @@ function loadMachineIdSync() {
|
|
|
5507
5682
|
return null;
|
|
5508
5683
|
}
|
|
5509
5684
|
}
|
|
5510
|
-
function saveMachineIdAsync(
|
|
5685
|
+
function saveMachineIdAsync(machineId) {
|
|
5511
5686
|
if (!isDevPersistenceEnabled()) return;
|
|
5512
5687
|
const machineIdPath = resolveMachineIdPath();
|
|
5513
5688
|
const path = __require("path");
|
|
@@ -5516,13 +5691,13 @@ function saveMachineIdAsync(machineId2) {
|
|
|
5516
5691
|
try {
|
|
5517
5692
|
const fsp = __require("fs").promises;
|
|
5518
5693
|
await fsp.mkdir(dir, { recursive: true, mode: 448 });
|
|
5519
|
-
await fsp.writeFile(machineIdPath,
|
|
5694
|
+
await fsp.writeFile(machineIdPath, machineId, { mode: 384 });
|
|
5520
5695
|
} catch (error) {
|
|
5521
5696
|
console.warn(`[MachineId] Failed to save to ${machineIdPath}: ${error.message}`);
|
|
5522
5697
|
}
|
|
5523
5698
|
})();
|
|
5524
5699
|
}
|
|
5525
|
-
|
|
5700
|
+
function computeMachineId() {
|
|
5526
5701
|
const envMachineId = getEnvDirect("MACHINE_ID");
|
|
5527
5702
|
if (envMachineId) return envMachineId;
|
|
5528
5703
|
const deploymentMode = getEnvDirect("FRONTMCP_DEPLOYMENT_MODE");
|
|
@@ -5542,10 +5717,15 @@ var machineId = (() => {
|
|
|
5542
5717
|
const newId = randomUUID();
|
|
5543
5718
|
saveMachineIdAsync(newId);
|
|
5544
5719
|
return newId;
|
|
5545
|
-
}
|
|
5720
|
+
}
|
|
5721
|
+
var cachedMachineId;
|
|
5546
5722
|
var machineIdOverride;
|
|
5547
5723
|
function getMachineId() {
|
|
5548
|
-
|
|
5724
|
+
if (machineIdOverride !== void 0) return machineIdOverride;
|
|
5725
|
+
if (cachedMachineId === void 0) {
|
|
5726
|
+
cachedMachineId = computeMachineId();
|
|
5727
|
+
}
|
|
5728
|
+
return cachedMachineId;
|
|
5549
5729
|
}
|
|
5550
5730
|
function setMachineIdOverride(id) {
|
|
5551
5731
|
machineIdOverride = id;
|
package/index.js
CHANGED
|
@@ -5,8 +5,13 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __esm = (fn, res) => function __init() {
|
|
9
|
-
|
|
8
|
+
var __esm = (fn, res, err) => function __init() {
|
|
9
|
+
if (err) throw err[0];
|
|
10
|
+
try {
|
|
11
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
12
|
+
} catch (e) {
|
|
13
|
+
throw err = [e], e;
|
|
14
|
+
}
|
|
10
15
|
};
|
|
11
16
|
var __export = (target, all) => {
|
|
12
17
|
for (var name in all)
|
|
@@ -78,8 +83,8 @@ async function readFile(p, encoding = "utf8") {
|
|
|
78
83
|
return fsp.readFile(p, encoding);
|
|
79
84
|
}
|
|
80
85
|
function readFileSync(p, encoding = "utf8") {
|
|
81
|
-
const
|
|
82
|
-
return
|
|
86
|
+
const fs = getFs();
|
|
87
|
+
return fs.readFileSync(p, encoding);
|
|
83
88
|
}
|
|
84
89
|
async function readFileBuffer(p) {
|
|
85
90
|
const fsp = getFsp();
|
|
@@ -94,8 +99,8 @@ async function mkdir(p, options) {
|
|
|
94
99
|
await fsp.mkdir(p, options);
|
|
95
100
|
}
|
|
96
101
|
function ensureDirSync(p) {
|
|
97
|
-
const
|
|
98
|
-
|
|
102
|
+
const fs = getFs();
|
|
103
|
+
fs.mkdirSync(p, { recursive: true });
|
|
99
104
|
}
|
|
100
105
|
async function rename(oldPath, newPath) {
|
|
101
106
|
const fsp = getFsp();
|
|
@@ -156,8 +161,8 @@ async function readdir(p) {
|
|
|
156
161
|
return fsp.readdir(p);
|
|
157
162
|
}
|
|
158
163
|
function readdirSync(p) {
|
|
159
|
-
const
|
|
160
|
-
return
|
|
164
|
+
const fs = getFs();
|
|
165
|
+
return fs.readdirSync(p);
|
|
161
166
|
}
|
|
162
167
|
async function rm(p, options) {
|
|
163
168
|
const fsp = getFsp();
|
|
@@ -190,8 +195,8 @@ function runCmd(cmd, args, opts = {}) {
|
|
|
190
195
|
});
|
|
191
196
|
}
|
|
192
197
|
function watchFile(p, onChange, options) {
|
|
193
|
-
const
|
|
194
|
-
const watcher =
|
|
198
|
+
const fs = getFs();
|
|
199
|
+
const watcher = fs.watch(p, { persistent: false, recursive: options?.recursive === true }, (eventType, filename) => {
|
|
195
200
|
onChange(eventType, filename);
|
|
196
201
|
});
|
|
197
202
|
return {
|
|
@@ -1019,6 +1024,7 @@ var init_errors = __esm({
|
|
|
1019
1024
|
this.backend = backend;
|
|
1020
1025
|
this.name = "StorageConnectionError";
|
|
1021
1026
|
}
|
|
1027
|
+
backend;
|
|
1022
1028
|
};
|
|
1023
1029
|
StorageOperationError = class extends StorageError {
|
|
1024
1030
|
constructor(operation, key, message, cause) {
|
|
@@ -1027,6 +1033,8 @@ var init_errors = __esm({
|
|
|
1027
1033
|
this.key = key;
|
|
1028
1034
|
this.name = "StorageOperationError";
|
|
1029
1035
|
}
|
|
1036
|
+
operation;
|
|
1037
|
+
key;
|
|
1030
1038
|
};
|
|
1031
1039
|
StorageNotSupportedError = class extends StorageError {
|
|
1032
1040
|
constructor(operation, backend, suggestion) {
|
|
@@ -1036,6 +1044,8 @@ var init_errors = __esm({
|
|
|
1036
1044
|
this.backend = backend;
|
|
1037
1045
|
this.name = "StorageNotSupportedError";
|
|
1038
1046
|
}
|
|
1047
|
+
operation;
|
|
1048
|
+
backend;
|
|
1039
1049
|
};
|
|
1040
1050
|
StorageConfigError = class extends StorageError {
|
|
1041
1051
|
constructor(backend, message) {
|
|
@@ -1043,6 +1053,7 @@ var init_errors = __esm({
|
|
|
1043
1053
|
this.backend = backend;
|
|
1044
1054
|
this.name = "StorageConfigError";
|
|
1045
1055
|
}
|
|
1056
|
+
backend;
|
|
1046
1057
|
};
|
|
1047
1058
|
StorageTTLError = class extends StorageError {
|
|
1048
1059
|
constructor(ttl, message) {
|
|
@@ -1050,6 +1061,7 @@ var init_errors = __esm({
|
|
|
1050
1061
|
this.ttl = ttl;
|
|
1051
1062
|
this.name = "StorageTTLError";
|
|
1052
1063
|
}
|
|
1064
|
+
ttl;
|
|
1053
1065
|
};
|
|
1054
1066
|
StoragePatternError = class extends StorageError {
|
|
1055
1067
|
constructor(pattern, message) {
|
|
@@ -1057,6 +1069,7 @@ var init_errors = __esm({
|
|
|
1057
1069
|
this.pattern = pattern;
|
|
1058
1070
|
this.name = "StoragePatternError";
|
|
1059
1071
|
}
|
|
1072
|
+
pattern;
|
|
1060
1073
|
};
|
|
1061
1074
|
StorageNotConnectedError = class extends StorageError {
|
|
1062
1075
|
constructor(backend) {
|
|
@@ -1064,6 +1077,7 @@ var init_errors = __esm({
|
|
|
1064
1077
|
this.backend = backend;
|
|
1065
1078
|
this.name = "StorageNotConnectedError";
|
|
1066
1079
|
}
|
|
1080
|
+
backend;
|
|
1067
1081
|
};
|
|
1068
1082
|
EncryptedStorageError = class extends StorageError {
|
|
1069
1083
|
constructor(message) {
|
|
@@ -3812,6 +3826,154 @@ var init_upstash = __esm({
|
|
|
3812
3826
|
}
|
|
3813
3827
|
});
|
|
3814
3828
|
|
|
3829
|
+
// libs/utils/src/storage/adapters/cloudflare-kv.ts
|
|
3830
|
+
var cloudflare_kv_exports = {};
|
|
3831
|
+
__export(cloudflare_kv_exports, {
|
|
3832
|
+
CloudflareKvStorageAdapter: () => CloudflareKvStorageAdapter
|
|
3833
|
+
});
|
|
3834
|
+
function literalPrefix(pattern) {
|
|
3835
|
+
const star = pattern.indexOf("*");
|
|
3836
|
+
const q = pattern.indexOf("?");
|
|
3837
|
+
const idx = star === -1 ? q : q === -1 ? star : Math.min(star, q);
|
|
3838
|
+
return idx === -1 ? pattern : pattern.slice(0, idx);
|
|
3839
|
+
}
|
|
3840
|
+
var CF_KV_MIN_TTL_SECONDS, CloudflareKvStorageAdapter;
|
|
3841
|
+
var init_cloudflare_kv = __esm({
|
|
3842
|
+
"libs/utils/src/storage/adapters/cloudflare-kv.ts"() {
|
|
3843
|
+
"use strict";
|
|
3844
|
+
init_errors();
|
|
3845
|
+
init_pattern();
|
|
3846
|
+
init_ttl();
|
|
3847
|
+
init_base();
|
|
3848
|
+
CF_KV_MIN_TTL_SECONDS = 60;
|
|
3849
|
+
CloudflareKvStorageAdapter = class extends BaseStorageAdapter {
|
|
3850
|
+
backendName = "cloudflare-kv";
|
|
3851
|
+
kv;
|
|
3852
|
+
keyPrefix;
|
|
3853
|
+
constructor(options) {
|
|
3854
|
+
super();
|
|
3855
|
+
if (!options?.namespace) {
|
|
3856
|
+
throw new Error("CloudflareKvStorageAdapter: a bound KV `namespace` is required (resolve it from the Worker `env`).");
|
|
3857
|
+
}
|
|
3858
|
+
this.kv = options.namespace;
|
|
3859
|
+
this.keyPrefix = options.keyPrefix ?? "";
|
|
3860
|
+
}
|
|
3861
|
+
// ── Lifecycle ──────────────────────────────────────────────────────────
|
|
3862
|
+
// A KV binding is always available; "connection" is just a readiness flag.
|
|
3863
|
+
async connect() {
|
|
3864
|
+
this.connected = true;
|
|
3865
|
+
}
|
|
3866
|
+
async disconnect() {
|
|
3867
|
+
this.connected = false;
|
|
3868
|
+
}
|
|
3869
|
+
async ping() {
|
|
3870
|
+
if (!this.connected) return false;
|
|
3871
|
+
try {
|
|
3872
|
+
await this.kv.list({ limit: 1 });
|
|
3873
|
+
return true;
|
|
3874
|
+
} catch {
|
|
3875
|
+
return false;
|
|
3876
|
+
}
|
|
3877
|
+
}
|
|
3878
|
+
// ── Core ───────────────────────────────────────────────────────────────
|
|
3879
|
+
async get(key) {
|
|
3880
|
+
this.ensureConnected();
|
|
3881
|
+
return this.kv.get(this.prefixKey(key), "text");
|
|
3882
|
+
}
|
|
3883
|
+
async doSet(key, value, options) {
|
|
3884
|
+
if (options?.ifNotExists || options?.ifExists) {
|
|
3885
|
+
throw new StorageNotSupportedError(
|
|
3886
|
+
"conditional set (ifNotExists/ifExists)",
|
|
3887
|
+
this.backendName,
|
|
3888
|
+
"Cloudflare KV has no compare-and-set; use a Durable Object for atomic conditional writes."
|
|
3889
|
+
);
|
|
3890
|
+
}
|
|
3891
|
+
const putOptions = options?.ttlSeconds !== void 0 ? { expirationTtl: this.toExpirationTtl(options.ttlSeconds, key) } : void 0;
|
|
3892
|
+
await this.kv.put(this.prefixKey(key), value, putOptions);
|
|
3893
|
+
}
|
|
3894
|
+
async delete(key) {
|
|
3895
|
+
this.ensureConnected();
|
|
3896
|
+
const existed = await this.exists(key);
|
|
3897
|
+
await this.kv.delete(this.prefixKey(key));
|
|
3898
|
+
return existed;
|
|
3899
|
+
}
|
|
3900
|
+
async exists(key) {
|
|
3901
|
+
this.ensureConnected();
|
|
3902
|
+
return await this.kv.get(this.prefixKey(key), "text") !== null;
|
|
3903
|
+
}
|
|
3904
|
+
// ── TTL ────────────────────────────────────────────────────────────────
|
|
3905
|
+
async expire(key, ttlSeconds) {
|
|
3906
|
+
this.ensureConnected();
|
|
3907
|
+
const ttl = this.toExpirationTtl(ttlSeconds, key);
|
|
3908
|
+
const value = await this.kv.get(this.prefixKey(key), "text");
|
|
3909
|
+
if (value === null) return false;
|
|
3910
|
+
await this.kv.put(this.prefixKey(key), value, { expirationTtl: ttl });
|
|
3911
|
+
return true;
|
|
3912
|
+
}
|
|
3913
|
+
async ttl(_key) {
|
|
3914
|
+
throw new StorageNotSupportedError(
|
|
3915
|
+
"ttl",
|
|
3916
|
+
this.backendName,
|
|
3917
|
+
"Cloudflare KV does not expose a key's remaining TTL. Track expiry alongside the value if you need it."
|
|
3918
|
+
);
|
|
3919
|
+
}
|
|
3920
|
+
// ── Enumeration ──────────────────────────────────────────────────────────
|
|
3921
|
+
async keys(pattern = "*") {
|
|
3922
|
+
this.ensureConnected();
|
|
3923
|
+
const prefixedPattern = this.prefixKey(pattern);
|
|
3924
|
+
const listPrefix = literalPrefix(prefixedPattern);
|
|
3925
|
+
const out = [];
|
|
3926
|
+
let cursor;
|
|
3927
|
+
do {
|
|
3928
|
+
const page = await this.kv.list({ prefix: listPrefix || void 0, cursor });
|
|
3929
|
+
for (const { name } of page.keys) {
|
|
3930
|
+
if (matchesPattern(name, prefixedPattern)) out.push(this.unprefixKey(name));
|
|
3931
|
+
}
|
|
3932
|
+
cursor = page.list_complete ? void 0 : page.cursor;
|
|
3933
|
+
} while (cursor);
|
|
3934
|
+
return out;
|
|
3935
|
+
}
|
|
3936
|
+
// ── Atomic (unsupported on KV) ───────────────────────────────────────────
|
|
3937
|
+
async incr(key) {
|
|
3938
|
+
return this.incrBy(key, 1);
|
|
3939
|
+
}
|
|
3940
|
+
async decr(key) {
|
|
3941
|
+
return this.incrBy(key, -1);
|
|
3942
|
+
}
|
|
3943
|
+
async incrBy(_key, _amount) {
|
|
3944
|
+
throw new StorageNotSupportedError(
|
|
3945
|
+
"incr/decr/incrBy",
|
|
3946
|
+
this.backendName,
|
|
3947
|
+
"Cloudflare KV has no atomic increment (a get+put is racy under eventual consistency). Use a Durable Object for atomic counters."
|
|
3948
|
+
);
|
|
3949
|
+
}
|
|
3950
|
+
// ── Pub/Sub (unsupported) ────────────────────────────────────────────────
|
|
3951
|
+
getPubSubSuggestion() {
|
|
3952
|
+
return "Cloudflare KV does not support pub/sub. Use a Durable Object (or Queues) for fan-out.";
|
|
3953
|
+
}
|
|
3954
|
+
// ── Helpers ──────────────────────────────────────────────────────────────
|
|
3955
|
+
/** Validate + enforce KV's 60s minimum `expirationTtl`. */
|
|
3956
|
+
toExpirationTtl(ttlSeconds, key) {
|
|
3957
|
+
validateTTL(ttlSeconds);
|
|
3958
|
+
if (ttlSeconds < CF_KV_MIN_TTL_SECONDS) {
|
|
3959
|
+
throw new StorageOperationError(
|
|
3960
|
+
"set",
|
|
3961
|
+
key,
|
|
3962
|
+
`cloudflare-kv: expirationTtl must be >= ${CF_KV_MIN_TTL_SECONDS}s (Cloudflare KV minimum); got ${ttlSeconds}s.`
|
|
3963
|
+
);
|
|
3964
|
+
}
|
|
3965
|
+
return ttlSeconds;
|
|
3966
|
+
}
|
|
3967
|
+
prefixKey(key) {
|
|
3968
|
+
return this.keyPrefix + key;
|
|
3969
|
+
}
|
|
3970
|
+
unprefixKey(key) {
|
|
3971
|
+
return this.keyPrefix && key.startsWith(this.keyPrefix) ? key.slice(this.keyPrefix.length) : key;
|
|
3972
|
+
}
|
|
3973
|
+
};
|
|
3974
|
+
}
|
|
3975
|
+
});
|
|
3976
|
+
|
|
3815
3977
|
// libs/utils/src/index.ts
|
|
3816
3978
|
var index_exports = {};
|
|
3817
3979
|
__export(index_exports, {
|
|
@@ -4746,7 +4908,6 @@ function isKnownTarget(value) {
|
|
|
4746
4908
|
}
|
|
4747
4909
|
|
|
4748
4910
|
// libs/utils/src/env/provider.ts
|
|
4749
|
-
var fs = __toESM(require("node:fs"));
|
|
4750
4911
|
var cached2;
|
|
4751
4912
|
function detectProvider() {
|
|
4752
4913
|
if (cached2) return cached2;
|
|
@@ -4766,7 +4927,8 @@ function detectProviderUncached() {
|
|
|
4766
4927
|
if (process.env["RENDER"]) return "render";
|
|
4767
4928
|
if (process.env["RAILWAY_ENVIRONMENT"]) return "railway";
|
|
4768
4929
|
try {
|
|
4769
|
-
|
|
4930
|
+
const nodeFs = require("node:fs");
|
|
4931
|
+
if (nodeFs.existsSync("/.dockerenv")) return "docker";
|
|
4770
4932
|
} catch {
|
|
4771
4933
|
}
|
|
4772
4934
|
return "bare";
|
|
@@ -4888,6 +5050,9 @@ var NamespacedStorageImpl = class _NamespacedStorageImpl {
|
|
|
4888
5050
|
this.prefix = prefix;
|
|
4889
5051
|
this.root = root;
|
|
4890
5052
|
}
|
|
5053
|
+
adapter;
|
|
5054
|
+
prefix;
|
|
5055
|
+
root;
|
|
4891
5056
|
// ============================================
|
|
4892
5057
|
// Key Prefixing Helpers
|
|
4893
5058
|
// ============================================
|
|
@@ -5061,6 +5226,16 @@ async function createAdapter(type, config) {
|
|
|
5061
5226
|
const { UpstashStorageAdapter: UpstashStorageAdapter2 } = await Promise.resolve().then(() => (init_upstash(), upstash_exports));
|
|
5062
5227
|
return new UpstashStorageAdapter2(config.upstash);
|
|
5063
5228
|
}
|
|
5229
|
+
case "cloudflare-kv": {
|
|
5230
|
+
if (!config.cloudflareKv) {
|
|
5231
|
+
throw new StorageConfigError(
|
|
5232
|
+
"cloudflare-kv",
|
|
5233
|
+
"cloudflare-kv requires `cloudflareKv: { namespace }` (the KV binding can't be auto-detected)"
|
|
5234
|
+
);
|
|
5235
|
+
}
|
|
5236
|
+
const { CloudflareKvStorageAdapter: CloudflareKvStorageAdapter2 } = await Promise.resolve().then(() => (init_cloudflare_kv(), cloudflare_kv_exports));
|
|
5237
|
+
return new CloudflareKvStorageAdapter2(config.cloudflareKv);
|
|
5238
|
+
}
|
|
5064
5239
|
case "auto":
|
|
5065
5240
|
throw new StorageConfigError("auto", "Auto type should be resolved before calling createAdapter");
|
|
5066
5241
|
default:
|
|
@@ -5709,8 +5884,8 @@ function loadMachineIdSync() {
|
|
|
5709
5884
|
if (!isDevPersistenceEnabled()) return null;
|
|
5710
5885
|
const machineIdPath = resolveMachineIdPath();
|
|
5711
5886
|
try {
|
|
5712
|
-
const
|
|
5713
|
-
const content =
|
|
5887
|
+
const fs = require("fs");
|
|
5888
|
+
const content = fs.readFileSync(machineIdPath, "utf8").trim();
|
|
5714
5889
|
if (/^[0-9a-f-]{32,36}$/i.test(content)) return content;
|
|
5715
5890
|
console.warn(`[MachineId] Invalid format at ${machineIdPath}, will regenerate`);
|
|
5716
5891
|
return null;
|
|
@@ -5721,7 +5896,7 @@ function loadMachineIdSync() {
|
|
|
5721
5896
|
return null;
|
|
5722
5897
|
}
|
|
5723
5898
|
}
|
|
5724
|
-
function saveMachineIdAsync(
|
|
5899
|
+
function saveMachineIdAsync(machineId) {
|
|
5725
5900
|
if (!isDevPersistenceEnabled()) return;
|
|
5726
5901
|
const machineIdPath = resolveMachineIdPath();
|
|
5727
5902
|
const path = require("path");
|
|
@@ -5730,13 +5905,13 @@ function saveMachineIdAsync(machineId2) {
|
|
|
5730
5905
|
try {
|
|
5731
5906
|
const fsp = require("fs").promises;
|
|
5732
5907
|
await fsp.mkdir(dir, { recursive: true, mode: 448 });
|
|
5733
|
-
await fsp.writeFile(machineIdPath,
|
|
5908
|
+
await fsp.writeFile(machineIdPath, machineId, { mode: 384 });
|
|
5734
5909
|
} catch (error) {
|
|
5735
5910
|
console.warn(`[MachineId] Failed to save to ${machineIdPath}: ${error.message}`);
|
|
5736
5911
|
}
|
|
5737
5912
|
})();
|
|
5738
5913
|
}
|
|
5739
|
-
|
|
5914
|
+
function computeMachineId() {
|
|
5740
5915
|
const envMachineId = getEnvDirect("MACHINE_ID");
|
|
5741
5916
|
if (envMachineId) return envMachineId;
|
|
5742
5917
|
const deploymentMode = getEnvDirect("FRONTMCP_DEPLOYMENT_MODE");
|
|
@@ -5756,10 +5931,15 @@ var machineId = (() => {
|
|
|
5756
5931
|
const newId = randomUUID();
|
|
5757
5932
|
saveMachineIdAsync(newId);
|
|
5758
5933
|
return newId;
|
|
5759
|
-
}
|
|
5934
|
+
}
|
|
5935
|
+
var cachedMachineId;
|
|
5760
5936
|
var machineIdOverride;
|
|
5761
5937
|
function getMachineId() {
|
|
5762
|
-
|
|
5938
|
+
if (machineIdOverride !== void 0) return machineIdOverride;
|
|
5939
|
+
if (cachedMachineId === void 0) {
|
|
5940
|
+
cachedMachineId = computeMachineId();
|
|
5941
|
+
}
|
|
5942
|
+
return cachedMachineId;
|
|
5763
5943
|
}
|
|
5764
5944
|
function setMachineIdOverride(id) {
|
|
5765
5945
|
machineIdOverride = id;
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
*/
|
|
23
23
|
/**
|
|
24
24
|
* Get the current machine ID.
|
|
25
|
-
* Returns the override (if set via `setMachineIdOverride`) or the
|
|
25
|
+
* Returns the override (if set via `setMachineIdOverride`) or the lazily
|
|
26
|
+
* computed-and-memoized value.
|
|
26
27
|
*/
|
|
27
28
|
export declare function getMachineId(): string;
|
|
28
29
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frontmcp/utils",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0-rc.1",
|
|
4
4
|
"description": "Shared utility functions for FrontMCP - string manipulation, URI handling, path utilities, and more",
|
|
5
5
|
"author": "AgentFront <info@agentfront.dev>",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -27,14 +27,14 @@
|
|
|
27
27
|
"node": ">=24.0.0"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@
|
|
30
|
+
"@enclave-vm/ast": "^2.14.1",
|
|
31
31
|
"@noble/ciphers": "^2.1.1",
|
|
32
|
-
"@
|
|
32
|
+
"@noble/hashes": "^2.0.1"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
|
+
"@frontmcp/lazy-zod": "1.5.0-rc.1",
|
|
35
36
|
"@vercel/kv": "^2.0.0 || ^3.0.0",
|
|
36
|
-
"ioredis": "^5.0.0"
|
|
37
|
-
"@frontmcp/lazy-zod": "1.4.0"
|
|
37
|
+
"ioredis": "^5.0.0"
|
|
38
38
|
},
|
|
39
39
|
"peerDependenciesMeta": {
|
|
40
40
|
"@vercel/kv": {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { CloudflareKvAdapterOptions, SetOptions } from '../types';
|
|
2
|
+
import { BaseStorageAdapter } from './base';
|
|
3
|
+
export declare class CloudflareKvStorageAdapter extends BaseStorageAdapter {
|
|
4
|
+
protected readonly backendName = "cloudflare-kv";
|
|
5
|
+
private readonly kv;
|
|
6
|
+
private readonly keyPrefix;
|
|
7
|
+
constructor(options: CloudflareKvAdapterOptions);
|
|
8
|
+
connect(): Promise<void>;
|
|
9
|
+
disconnect(): Promise<void>;
|
|
10
|
+
ping(): Promise<boolean>;
|
|
11
|
+
get(key: string): Promise<string | null>;
|
|
12
|
+
protected doSet(key: string, value: string, options?: SetOptions): Promise<void>;
|
|
13
|
+
delete(key: string): Promise<boolean>;
|
|
14
|
+
exists(key: string): Promise<boolean>;
|
|
15
|
+
expire(key: string, ttlSeconds: number): Promise<boolean>;
|
|
16
|
+
ttl(_key: string): Promise<number | null>;
|
|
17
|
+
keys(pattern?: string): Promise<string[]>;
|
|
18
|
+
incr(key: string): Promise<number>;
|
|
19
|
+
decr(key: string): Promise<number>;
|
|
20
|
+
incrBy(_key: string, _amount: number): Promise<number>;
|
|
21
|
+
protected getPubSubSuggestion(): string;
|
|
22
|
+
/** Validate + enforce KV's 60s minimum `expirationTtl`. */
|
|
23
|
+
private toExpirationTtl;
|
|
24
|
+
private prefixKey;
|
|
25
|
+
private unprefixKey;
|
|
26
|
+
}
|
|
@@ -8,6 +8,7 @@ export { MemoryStorageAdapter } from './memory';
|
|
|
8
8
|
export { RedisStorageAdapter } from './redis';
|
|
9
9
|
export { VercelKvStorageAdapter } from './vercel-kv';
|
|
10
10
|
export { UpstashStorageAdapter } from './upstash';
|
|
11
|
+
export { CloudflareKvStorageAdapter } from './cloudflare-kv';
|
|
11
12
|
export { FileSystemStorageAdapter } from './filesystem';
|
|
12
13
|
export type { FileSystemAdapterOptions } from './filesystem';
|
|
13
14
|
export { LocalStorageAdapter } from './localstorage';
|
package/storage/types.d.ts
CHANGED
|
@@ -378,10 +378,44 @@ export interface UpstashAdapterOptions {
|
|
|
378
378
|
*/
|
|
379
379
|
enablePubSub?: boolean;
|
|
380
380
|
}
|
|
381
|
+
/**
|
|
382
|
+
* Minimal structural subset of the Cloudflare `KVNamespace` binding the
|
|
383
|
+
* `cloudflare-kv` adapter uses. Declared here rather than importing
|
|
384
|
+
* `@cloudflare/workers-types` so any runtime exposing this shape works.
|
|
385
|
+
*/
|
|
386
|
+
export interface CloudflareKvNamespace {
|
|
387
|
+
get(key: string, type?: 'text'): Promise<string | null>;
|
|
388
|
+
put(key: string, value: string, options?: {
|
|
389
|
+
expirationTtl?: number;
|
|
390
|
+
}): Promise<void>;
|
|
391
|
+
delete(key: string): Promise<void>;
|
|
392
|
+
list(options?: {
|
|
393
|
+
prefix?: string;
|
|
394
|
+
limit?: number;
|
|
395
|
+
cursor?: string;
|
|
396
|
+
}): Promise<{
|
|
397
|
+
keys: {
|
|
398
|
+
name: string;
|
|
399
|
+
}[];
|
|
400
|
+
list_complete: boolean;
|
|
401
|
+
cursor?: string;
|
|
402
|
+
}>;
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Cloudflare Workers KV adapter options (when type='cloudflare-kv'). The bound
|
|
406
|
+
* KV namespace is supplied explicitly (resolved from the Worker `env`), since
|
|
407
|
+
* bindings don't exist as env vars and can't be auto-detected.
|
|
408
|
+
*/
|
|
409
|
+
export interface CloudflareKvAdapterOptions {
|
|
410
|
+
/** The bound KV namespace. */
|
|
411
|
+
namespace: CloudflareKvNamespace;
|
|
412
|
+
/** Key prefix applied to all keys. @default '' */
|
|
413
|
+
keyPrefix?: string;
|
|
414
|
+
}
|
|
381
415
|
/**
|
|
382
416
|
* Storage backend type.
|
|
383
417
|
*/
|
|
384
|
-
export type StorageType = 'memory' | 'redis' | 'vercel-kv' | 'upstash' | 'auto';
|
|
418
|
+
export type StorageType = 'memory' | 'redis' | 'vercel-kv' | 'upstash' | 'cloudflare-kv' | 'auto';
|
|
385
419
|
/**
|
|
386
420
|
* Configuration for createStorage factory.
|
|
387
421
|
*/
|
|
@@ -408,6 +442,10 @@ export interface StorageConfig {
|
|
|
408
442
|
* Vercel KV adapter options (when type='vercel-kv').
|
|
409
443
|
*/
|
|
410
444
|
vercelKv?: VercelKvAdapterOptions;
|
|
445
|
+
/**
|
|
446
|
+
* Cloudflare KV adapter options (when type='cloudflare-kv').
|
|
447
|
+
*/
|
|
448
|
+
cloudflareKv?: CloudflareKvAdapterOptions;
|
|
411
449
|
/**
|
|
412
450
|
* Upstash adapter options (when type='upstash').
|
|
413
451
|
*/
|