@frontmcp/utils 1.3.0 → 1.4.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.
@@ -1,3 +1,5 @@
1
+ import { createRequire as __frontmcpCreateRequire } from 'module';
2
+ const require = __frontmcpCreateRequire(import.meta.url);
1
3
  // libs/utils/src/async-context/browser-async-context.ts
2
4
  var AsyncLocalStorage = class {
3
5
  stack = [];
@@ -1,3 +1,5 @@
1
+ import { createRequire as __frontmcpCreateRequire } from 'module';
2
+ const require = __frontmcpCreateRequire(import.meta.url);
1
3
  // libs/utils/src/async-context/node-async-context.ts
2
4
  import { AsyncLocalStorage } from "node:async_hooks";
3
5
  export {
@@ -1,3 +1,5 @@
1
+ import { createRequire as __frontmcpCreateRequire } from 'module';
2
+ const require = __frontmcpCreateRequire(import.meta.url);
1
3
  // libs/utils/src/crypto/browser.ts
2
4
  import { sha256 as sha256Hash } from "@noble/hashes/sha2.js";
3
5
  import { hmac } from "@noble/hashes/hmac.js";
@@ -1,3 +1,5 @@
1
+ import { createRequire as __frontmcpCreateRequire } from 'module';
2
+ const require = __frontmcpCreateRequire(import.meta.url);
1
3
  // libs/utils/src/crypto/node.ts
2
4
  import crypto from "node:crypto";
3
5
 
@@ -1,3 +1,5 @@
1
+ import { createRequire as __frontmcpCreateRequire } from 'module';
2
+ const require = __frontmcpCreateRequire(import.meta.url);
1
3
  // libs/utils/src/env/browser-env.ts
2
4
  function getEnv(_key, defaultValue) {
3
5
  return defaultValue;
@@ -1,3 +1,5 @@
1
+ import { createRequire as __frontmcpCreateRequire } from 'module';
2
+ const require = __frontmcpCreateRequire(import.meta.url);
1
3
  // libs/utils/src/env/node-env.ts
2
4
  function getEnv(key, defaultValue) {
3
5
  return process.env[key] ?? defaultValue;
@@ -1,3 +1,5 @@
1
+ import { createRequire as __frontmcpCreateRequire } from 'module';
2
+ const require = __frontmcpCreateRequire(import.meta.url);
1
3
  // libs/utils/src/event-emitter/browser-event-emitter.ts
2
4
  var EventEmitter = class {
3
5
  events = /* @__PURE__ */ new Map();
@@ -1,3 +1,5 @@
1
+ import { createRequire as __frontmcpCreateRequire } from 'module';
2
+ const require = __frontmcpCreateRequire(import.meta.url);
1
3
  // libs/utils/src/event-emitter/node-event-emitter.ts
2
4
  import { EventEmitter } from "events";
3
5
  export {
package/esm/index.mjs CHANGED
@@ -1,3 +1,5 @@
1
+ import { createRequire as __frontmcpCreateRequire } from 'module';
2
+ const require = __frontmcpCreateRequire(import.meta.url);
1
3
  var __defProp = Object.defineProperty;
2
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -65,6 +67,9 @@ function getSpawn() {
65
67
  }
66
68
  return _spawn;
67
69
  }
70
+ function getSpawnFn() {
71
+ return getSpawn();
72
+ }
68
73
  async function readFile(p, encoding = "utf8") {
69
74
  const fsp = getFsp();
70
75
  return fsp.readFile(p, encoding);
@@ -85,6 +90,10 @@ async function mkdir(p, options) {
85
90
  const fsp = getFsp();
86
91
  await fsp.mkdir(p, options);
87
92
  }
93
+ function ensureDirSync(p) {
94
+ const fs2 = getFs();
95
+ fs2.mkdirSync(p, { recursive: true });
96
+ }
88
97
  async function rename(oldPath, newPath) {
89
98
  const fsp = getFsp();
90
99
  await fsp.rename(oldPath, newPath);
@@ -177,6 +186,20 @@ function runCmd(cmd, args, opts = {}) {
177
186
  child.on("error", reject);
178
187
  });
179
188
  }
189
+ function watchFile(p, onChange, options) {
190
+ const fs2 = getFs();
191
+ const watcher = fs2.watch(p, { persistent: false, recursive: options?.recursive === true }, (eventType, filename) => {
192
+ onChange(eventType, filename);
193
+ });
194
+ return {
195
+ close() {
196
+ watcher.close();
197
+ },
198
+ onError(handler) {
199
+ watcher.on("error", handler);
200
+ }
201
+ };
202
+ }
180
203
  var _fsp, _fs, _spawn, F_OK;
181
204
  var init_fs = __esm({
182
205
  "libs/utils/src/fs/fs.ts"() {
@@ -4188,7 +4211,7 @@ function joinPath(...parts) {
4188
4211
  }
4189
4212
 
4190
4213
  // libs/utils/src/path/node-path.ts
4191
- import { resolve, join, basename, dirname, extname, isAbsolute } from "path";
4214
+ import { resolve, join, basename, dirname, extname, isAbsolute, sep } from "path";
4192
4215
  import { pathToFileURL } from "url";
4193
4216
 
4194
4217
  // libs/utils/src/content/content.ts
@@ -5597,6 +5620,7 @@ export {
5597
5620
  encryptAndSerialize,
5598
5621
  encryptValue,
5599
5622
  ensureDir,
5623
+ ensureDirSync,
5600
5624
  ensureMaxLen,
5601
5625
  entryAvailabilitySchema,
5602
5626
  escapeGlob,
@@ -5627,6 +5651,7 @@ export {
5627
5651
  getMachineId,
5628
5652
  getOrCreateSecret,
5629
5653
  getRuntimeContext,
5654
+ getSpawnFn,
5630
5655
  globToRegex,
5631
5656
  hasTemplatePlaceholders,
5632
5657
  hkdfSha256,
@@ -5704,6 +5729,7 @@ export {
5704
5729
  saveSecret,
5705
5730
  secretDataSchema,
5706
5731
  secretKeyDataSchema,
5732
+ sep,
5707
5733
  sepFor,
5708
5734
  serializeBlob,
5709
5735
  setEnv,
@@ -5738,6 +5764,7 @@ export {
5738
5764
  verifyCodeChallenge,
5739
5765
  verifyData,
5740
5766
  verifyOrParseData,
5767
+ watchFile,
5741
5768
  writeFile,
5742
5769
  writeJSON
5743
5770
  };
package/fs/fs.d.ts CHANGED
@@ -6,6 +6,16 @@
6
6
  * **Note:** These functions are Node.js only and will throw an error
7
7
  * if called in a browser environment.
8
8
  */
9
+ /**
10
+ * Lazily resolve `child_process.spawn` for callers that need to spawn a
11
+ * detached worker (CLI task runners, dev-server supervisors, etc.). Throws
12
+ * via `assertNode` on non-Node runtimes.
13
+ *
14
+ * **Node.js only.** Exposed because consumers (e.g. `CliTaskRunner` in the
15
+ * SDK) need a single place to reach `spawn` without a top-level
16
+ * `import 'node:child_process'` that V8 isolates would choke on.
17
+ */
18
+ export declare function getSpawnFn(): typeof import('child_process').spawn;
9
19
  /**
10
20
  * Read a file's contents as a string.
11
21
  *
@@ -77,6 +87,21 @@ export declare function mkdir(p: string, options?: {
77
87
  recursive?: boolean;
78
88
  mode?: number;
79
89
  }): Promise<void>;
90
+ /**
91
+ * Ensure a directory exists, creating it recursively if needed (synchronous).
92
+ *
93
+ * **Node.js only** - throws an error if called in browser.
94
+ *
95
+ * Use this only when async operations are not possible (e.g., a synchronous
96
+ * constructor that must open a file path before the first I/O). Prefer the
97
+ * async `ensureDir` in most cases.
98
+ *
99
+ * @param p - Path to directory
100
+ *
101
+ * @example
102
+ * ensureDirSync('/path/to/new/directory');
103
+ */
104
+ export declare function ensureDirSync(p: string): void;
80
105
  /**
81
106
  * Rename/move a file or directory.
82
107
  *
@@ -313,3 +338,34 @@ export declare function runCmd(cmd: string, args: string[], opts?: {
313
338
  cwd?: string;
314
339
  env?: NodeJS.ProcessEnv;
315
340
  }): Promise<void>;
341
+ /**
342
+ * Handle returned by {@link watchFile}. `close()` stops the watch and is safe
343
+ * to call multiple times. `onError` registers an error handler — useful for
344
+ * platforms (Linux watch-count limits, network filesystems) that surface
345
+ * mid-stream failures.
346
+ */
347
+ export interface FileWatcherHandle {
348
+ close(): void;
349
+ onError(handler: (err: Error) => void): void;
350
+ }
351
+ /** Options for {@link watchFile}. Mirrors a subset of Node `fs.watch`. */
352
+ export interface WatchFileOptions {
353
+ /** Watch a directory recursively. Node-specific; default false. */
354
+ recursive?: boolean;
355
+ }
356
+ /** Callback fired on each filesystem change event. */
357
+ export type WatchFileListener = (eventType: 'rename' | 'change', filename: string | null) => void;
358
+ /**
359
+ * Watch a file or directory for changes. Returns a handle the caller closes
360
+ * to stop watching.
361
+ *
362
+ * Accepts either a no-arg listener (the simple case) or one that receives
363
+ * the Node-shaped `(eventType, filename)` pair — both are tolerated so
364
+ * shallow callers stay terse while filesystem-walking callers get the full
365
+ * signal.
366
+ *
367
+ * **Node.js only** — calls `assertNode` at invocation time. Build-time env
368
+ * selection (`frontmcp build --target <env>`) keeps this off non-Node
369
+ * targets; runtime callers in V8 isolates will hit the assertion.
370
+ */
371
+ export declare function watchFile(p: string, onChange: WatchFileListener | (() => void), options?: WatchFileOptions): FileWatcherHandle;
package/fs/index.d.ts CHANGED
@@ -1 +1,2 @@
1
- export { readFile, readFileSync, readFileBuffer, writeFile, mkdir, rename, unlink, stat, copyFile, cp, readdir, readdirSync, realpath, rm, mkdtemp, symlink, access, fileExists, readJSON, writeJSON, ensureDir, isDirEmpty, runCmd, } from './fs';
1
+ export { readFile, readFileSync, readFileBuffer, writeFile, mkdir, rename, unlink, stat, copyFile, cp, readdir, readdirSync, realpath, rm, mkdtemp, symlink, access, fileExists, readJSON, writeJSON, ensureDir, ensureDirSync, isDirEmpty, runCmd, watchFile, getSpawnFn, } from './fs';
2
+ export type { FileWatcherHandle } from './fs';
package/index.d.ts CHANGED
@@ -9,11 +9,12 @@ export { splitWords, toCase, sepFor, shortHash, ensureMaxLen, idFromString } fro
9
9
  export type { NameCase } from './naming';
10
10
  export { isValidMcpUri, extractUriScheme, isValidMcpUriTemplate, parseUriTemplate, matchUriTemplate, expandUriTemplate, extractTemplateParams, isUriTemplate, } from './uri';
11
11
  export type { ParsedUriTemplate } from './uri';
12
- export { trimSlashes, joinPath, pathResolve, pathJoin, basename, dirname, extname, isAbsolute, pathToFileURL, } from './path';
12
+ export { trimSlashes, joinPath, pathResolve, pathJoin, basename, dirname, extname, isAbsolute, pathToFileURL, sep, } from './path';
13
13
  export { sanitizeToJson, inferMimeType, findNonFiniteNumber } from './content';
14
14
  export { validateBaseUrl, buildSetCookie, parseCookies, getCookie, isLocalhost, isSecureRequest } from './http';
15
15
  export type { CookieOptions, SecureDetectionRequest } from './http';
16
- export { readFile, readFileSync, readFileBuffer, writeFile, mkdir, rename, unlink, stat, copyFile, cp, readdir, readdirSync, realpath, rm, mkdtemp, symlink, access, fileExists, readJSON, writeJSON, ensureDir, isDirEmpty, runCmd, } from './fs';
16
+ export { readFile, readFileSync, readFileBuffer, writeFile, mkdir, rename, unlink, stat, copyFile, cp, readdir, readdirSync, realpath, rm, mkdtemp, symlink, access, fileExists, readJSON, writeJSON, ensureDir, ensureDirSync, isDirEmpty, runCmd, watchFile, getSpawnFn, } from './fs';
17
+ export type { FileWatcherHandle } from './fs';
17
18
  export { escapeHtml, escapeHtmlAttr, escapeJsString, escapeScriptClose, safeJsonForScript } from './escape';
18
19
  export { safeStringify } from './serialization';
19
20
  export { getCrypto, rsaVerify, rsaVerifySync, pemToPublicJwk, generateRsaKeyPair, rsaSignBase64Url, type RsaJwk, type RsaKeyPair, jwtAlgToNodeAlg, isRsaPssAlg, randomUUID, randomBytes, sha256, sha256Hex, sha256Base64url, hmacSha256, hkdfSha256, encryptAesGcm, decryptAesGcm, timingSafeEqual, bytesToHex, base64urlEncode, base64urlDecode, base64Encode, base64Decode, isNode, isBrowser, assertNode, EncryptedBlobError, encryptValue, decryptValue, tryDecryptValue, serializeBlob, deserializeBlob, tryDeserializeBlob, isValidEncryptedBlob, encryptAndSerialize, deserializeAndDecrypt, tryDeserializeAndDecrypt, generateCodeVerifier, generateCodeChallenge, verifyCodeChallenge, generatePkcePair, isValidCodeVerifier, isValidCodeChallenge, MIN_CODE_VERIFIER_LENGTH, MAX_CODE_VERIFIER_LENGTH, DEFAULT_CODE_VERIFIER_LENGTH, PkceError, type PkcePair, type SecretData, type SecretPersistenceOptions, type SecretValidationResult, secretDataSchema, validateSecretData, parseSecretData, isSecretPersistenceEnabled, resolveSecretPath, loadSecret, saveSecret, deleteSecret, generateSecret, createSecretData, getOrCreateSecret, clearCachedSecret, isSecretCached, type SignedData, type HmacSigningConfig, signData, verifyData, isSignedData, verifyOrParseData, type BaseKeyData, type SecretKeyData, type AsymmetricKeyData, type AnyKeyData, type KeyPersistenceOptions, type CreateKeyPersistenceOptions, type CreateSecretOptions, type CreateAsymmetricOptions, type KeyValidationResult, asymmetricAlgSchema, secretKeyDataSchema, asymmetricKeyDataSchema, anyKeyDataSchema, validateKeyData, parseKeyData, isSecretKeyData, isAsymmetricKeyData, KeyPersistence, createKeyPersistence, createKeyPersistenceWithStorage, } from './crypto';
package/index.js CHANGED
@@ -70,6 +70,9 @@ function getSpawn() {
70
70
  }
71
71
  return _spawn;
72
72
  }
73
+ function getSpawnFn() {
74
+ return getSpawn();
75
+ }
73
76
  async function readFile(p, encoding = "utf8") {
74
77
  const fsp = getFsp();
75
78
  return fsp.readFile(p, encoding);
@@ -90,6 +93,10 @@ async function mkdir(p, options) {
90
93
  const fsp = getFsp();
91
94
  await fsp.mkdir(p, options);
92
95
  }
96
+ function ensureDirSync(p) {
97
+ const fs2 = getFs();
98
+ fs2.mkdirSync(p, { recursive: true });
99
+ }
93
100
  async function rename(oldPath, newPath) {
94
101
  const fsp = getFsp();
95
102
  await fsp.rename(oldPath, newPath);
@@ -182,6 +189,20 @@ function runCmd(cmd, args, opts = {}) {
182
189
  child.on("error", reject);
183
190
  });
184
191
  }
192
+ function watchFile(p, onChange, options) {
193
+ const fs2 = getFs();
194
+ const watcher = fs2.watch(p, { persistent: false, recursive: options?.recursive === true }, (eventType, filename) => {
195
+ onChange(eventType, filename);
196
+ });
197
+ return {
198
+ close() {
199
+ watcher.close();
200
+ },
201
+ onError(handler) {
202
+ watcher.on("error", handler);
203
+ }
204
+ };
205
+ }
185
206
  var _fsp, _fs, _spawn, F_OK;
186
207
  var init_fs = __esm({
187
208
  "libs/utils/src/fs/fs.ts"() {
@@ -3863,6 +3884,7 @@ __export(index_exports, {
3863
3884
  encryptAndSerialize: () => encryptAndSerialize,
3864
3885
  encryptValue: () => encryptValue,
3865
3886
  ensureDir: () => ensureDir,
3887
+ ensureDirSync: () => ensureDirSync,
3866
3888
  ensureMaxLen: () => ensureMaxLen,
3867
3889
  entryAvailabilitySchema: () => entryAvailabilitySchema,
3868
3890
  escapeGlob: () => escapeGlob,
@@ -3893,6 +3915,7 @@ __export(index_exports, {
3893
3915
  getMachineId: () => getMachineId,
3894
3916
  getOrCreateSecret: () => getOrCreateSecret,
3895
3917
  getRuntimeContext: () => getRuntimeContext,
3918
+ getSpawnFn: () => getSpawnFn,
3896
3919
  globToRegex: () => globToRegex,
3897
3920
  hasTemplatePlaceholders: () => hasTemplatePlaceholders,
3898
3921
  hkdfSha256: () => hkdfSha256,
@@ -3970,6 +3993,7 @@ __export(index_exports, {
3970
3993
  saveSecret: () => saveSecret,
3971
3994
  secretDataSchema: () => secretDataSchema,
3972
3995
  secretKeyDataSchema: () => secretKeyDataSchema,
3996
+ sep: () => import_path.sep,
3973
3997
  sepFor: () => sepFor,
3974
3998
  serializeBlob: () => serializeBlob,
3975
3999
  setEnv: () => import_env3.setEnv,
@@ -4004,6 +4028,7 @@ __export(index_exports, {
4004
4028
  verifyCodeChallenge: () => verifyCodeChallenge,
4005
4029
  verifyData: () => verifyData,
4006
4030
  verifyOrParseData: () => verifyOrParseData,
4031
+ watchFile: () => watchFile,
4007
4032
  writeFile: () => writeFile,
4008
4033
  writeJSON: () => writeJSON
4009
4034
  });
@@ -5810,6 +5835,7 @@ function setMachineIdOverride(id) {
5810
5835
  encryptAndSerialize,
5811
5836
  encryptValue,
5812
5837
  ensureDir,
5838
+ ensureDirSync,
5813
5839
  ensureMaxLen,
5814
5840
  entryAvailabilitySchema,
5815
5841
  escapeGlob,
@@ -5840,6 +5866,7 @@ function setMachineIdOverride(id) {
5840
5866
  getMachineId,
5841
5867
  getOrCreateSecret,
5842
5868
  getRuntimeContext,
5869
+ getSpawnFn,
5843
5870
  globToRegex,
5844
5871
  hasTemplatePlaceholders,
5845
5872
  hkdfSha256,
@@ -5917,6 +5944,7 @@ function setMachineIdOverride(id) {
5917
5944
  saveSecret,
5918
5945
  secretDataSchema,
5919
5946
  secretKeyDataSchema,
5947
+ sep,
5920
5948
  sepFor,
5921
5949
  serializeBlob,
5922
5950
  setEnv,
@@ -5951,6 +5979,7 @@ function setMachineIdOverride(id) {
5951
5979
  verifyCodeChallenge,
5952
5980
  verifyData,
5953
5981
  verifyOrParseData,
5982
+ watchFile,
5954
5983
  writeFile,
5955
5984
  writeJSON
5956
5985
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontmcp/utils",
3
- "version": "1.3.0",
3
+ "version": "1.4.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
- "@noble/hashes": "^2.0.1",
30
+ "@enclave-vm/ast": "^2.13.0",
31
31
  "@noble/ciphers": "^2.1.1",
32
- "@enclave-vm/ast": "^2.13.0"
32
+ "@noble/hashes": "^2.0.1"
33
33
  },
34
34
  "peerDependencies": {
35
+ "@frontmcp/lazy-zod": "1.4.1",
35
36
  "@vercel/kv": "^2.0.0 || ^3.0.0",
36
- "ioredis": "^5.0.0",
37
- "@frontmcp/lazy-zod": "1.3.0"
37
+ "ioredis": "^5.0.0"
38
38
  },
39
39
  "peerDependenciesMeta": {
40
40
  "@vercel/kv": {
@@ -5,3 +5,9 @@ export declare function dirname(_p: string): string;
5
5
  export declare function extname(p: string): string;
6
6
  export declare function isAbsolute(p: string): boolean;
7
7
  export declare function pathToFileURL(_p: string): URL;
8
+ /**
9
+ * Platform-specific path separator. In browser/Worker builds we mirror POSIX
10
+ * (`/`) — these targets never read a real filesystem so the value is only
11
+ * used for string parsing, and POSIX matches the runtime's URL conventions.
12
+ */
13
+ export declare const sep = "/";
package/path/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  export { trimSlashes, joinPath } from './path';
2
- export { resolve as pathResolve, join as pathJoin, basename, dirname, extname, isAbsolute, pathToFileURL } from '#path';
2
+ export { resolve as pathResolve, join as pathJoin, basename, dirname, extname, isAbsolute, pathToFileURL, sep, } from '#path';
@@ -1,2 +1,2 @@
1
- export { resolve, join, basename, dirname, extname, isAbsolute } from 'path';
1
+ export { resolve, join, basename, dirname, extname, isAbsolute, sep } from 'path';
2
2
  export { pathToFileURL } from 'url';