@frontmcp/utils 1.0.4 → 1.1.0

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.
@@ -3,12 +3,11 @@
3
3
  *
4
4
  * @module @frontmcp/utils/key-persistence
5
5
  */
6
- import { z } from 'zod';
7
- import type { AnyKeyData, SecretKeyData, AsymmetricKeyData } from './types';
6
+ import type { AnyKeyData, AsymmetricKeyData, SecretKeyData } from './types';
8
7
  /**
9
8
  * Supported asymmetric algorithms.
10
9
  */
11
- export declare const asymmetricAlgSchema: z.ZodEnum<{
10
+ export declare const asymmetricAlgSchema: import("@frontmcp/lazy-zod").ZodEnum<{
12
11
  RS256: "RS256";
13
12
  RS384: "RS384";
14
13
  RS512: "RS512";
@@ -19,23 +18,23 @@ export declare const asymmetricAlgSchema: z.ZodEnum<{
19
18
  /**
20
19
  * Zod schema for SecretKeyData.
21
20
  */
22
- export declare const secretKeyDataSchema: z.ZodObject<{
23
- kid: z.ZodString;
24
- createdAt: z.ZodNumber;
25
- version: z.ZodNumber;
26
- type: z.ZodLiteral<"secret">;
27
- secret: z.ZodString;
28
- bytes: z.ZodNumber;
29
- }, z.core.$strip>;
21
+ export declare const secretKeyDataSchema: import("@frontmcp/lazy-zod").ZodObject<{
22
+ kid: import("@frontmcp/lazy-zod").ZodString;
23
+ createdAt: import("@frontmcp/lazy-zod").ZodNumber;
24
+ version: import("@frontmcp/lazy-zod").ZodNumber;
25
+ type: import("@frontmcp/lazy-zod").ZodLiteral<"secret">;
26
+ secret: import("@frontmcp/lazy-zod").ZodString;
27
+ bytes: import("@frontmcp/lazy-zod").ZodNumber;
28
+ }, import("zod/v4/core").$strip>;
30
29
  /**
31
30
  * Zod schema for AsymmetricKeyData.
32
31
  */
33
- export declare const asymmetricKeyDataSchema: z.ZodObject<{
34
- kid: z.ZodString;
35
- createdAt: z.ZodNumber;
36
- version: z.ZodNumber;
37
- type: z.ZodLiteral<"asymmetric">;
38
- alg: z.ZodEnum<{
32
+ export declare const asymmetricKeyDataSchema: import("@frontmcp/lazy-zod").ZodObject<{
33
+ kid: import("@frontmcp/lazy-zod").ZodString;
34
+ createdAt: import("@frontmcp/lazy-zod").ZodNumber;
35
+ version: import("@frontmcp/lazy-zod").ZodNumber;
36
+ type: import("@frontmcp/lazy-zod").ZodLiteral<"asymmetric">;
37
+ alg: import("@frontmcp/lazy-zod").ZodEnum<{
39
38
  RS256: "RS256";
40
39
  RS384: "RS384";
41
40
  RS512: "RS512";
@@ -43,59 +42,59 @@ export declare const asymmetricKeyDataSchema: z.ZodObject<{
43
42
  ES384: "ES384";
44
43
  ES512: "ES512";
45
44
  }>;
46
- privateKey: z.ZodObject<{
47
- kty: z.ZodOptional<z.ZodString>;
48
- use: z.ZodOptional<z.ZodString>;
49
- alg: z.ZodOptional<z.ZodString>;
50
- kid: z.ZodOptional<z.ZodString>;
51
- n: z.ZodOptional<z.ZodString>;
52
- e: z.ZodOptional<z.ZodString>;
53
- d: z.ZodOptional<z.ZodString>;
54
- p: z.ZodOptional<z.ZodString>;
55
- q: z.ZodOptional<z.ZodString>;
56
- dp: z.ZodOptional<z.ZodString>;
57
- dq: z.ZodOptional<z.ZodString>;
58
- qi: z.ZodOptional<z.ZodString>;
59
- x: z.ZodOptional<z.ZodString>;
60
- y: z.ZodOptional<z.ZodString>;
61
- crv: z.ZodOptional<z.ZodString>;
62
- }, z.core.$loose>;
63
- publicJwk: z.ZodObject<{
64
- keys: z.ZodArray<z.ZodObject<{
65
- kty: z.ZodOptional<z.ZodString>;
66
- use: z.ZodOptional<z.ZodString>;
67
- alg: z.ZodOptional<z.ZodString>;
68
- kid: z.ZodOptional<z.ZodString>;
69
- n: z.ZodOptional<z.ZodString>;
70
- e: z.ZodOptional<z.ZodString>;
71
- d: z.ZodOptional<z.ZodString>;
72
- p: z.ZodOptional<z.ZodString>;
73
- q: z.ZodOptional<z.ZodString>;
74
- dp: z.ZodOptional<z.ZodString>;
75
- dq: z.ZodOptional<z.ZodString>;
76
- qi: z.ZodOptional<z.ZodString>;
77
- x: z.ZodOptional<z.ZodString>;
78
- y: z.ZodOptional<z.ZodString>;
79
- crv: z.ZodOptional<z.ZodString>;
80
- }, z.core.$loose>>;
81
- }, z.core.$strip>;
82
- }, z.core.$strip>;
45
+ privateKey: import("@frontmcp/lazy-zod").ZodObject<{
46
+ kty: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
47
+ use: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
48
+ alg: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
49
+ kid: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
50
+ n: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
51
+ e: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
52
+ d: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
53
+ p: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
54
+ q: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
55
+ dp: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
56
+ dq: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
57
+ qi: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
58
+ x: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
59
+ y: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
60
+ crv: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
61
+ }, import("zod/v4/core").$loose>;
62
+ publicJwk: import("@frontmcp/lazy-zod").ZodObject<{
63
+ keys: import("@frontmcp/lazy-zod").ZodArray<import("@frontmcp/lazy-zod").ZodObject<{
64
+ kty: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
65
+ use: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
66
+ alg: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
67
+ kid: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
68
+ n: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
69
+ e: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
70
+ d: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
71
+ p: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
72
+ q: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
73
+ dp: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
74
+ dq: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
75
+ qi: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
76
+ x: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
77
+ y: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
78
+ crv: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
79
+ }, import("zod/v4/core").$loose>>;
80
+ }, import("zod/v4/core").$strip>;
81
+ }, import("zod/v4/core").$strip>;
83
82
  /**
84
83
  * Zod schema for AnyKeyData (discriminated union).
85
84
  */
86
- export declare const anyKeyDataSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
87
- kid: z.ZodString;
88
- createdAt: z.ZodNumber;
89
- version: z.ZodNumber;
90
- type: z.ZodLiteral<"secret">;
91
- secret: z.ZodString;
92
- bytes: z.ZodNumber;
93
- }, z.core.$strip>, z.ZodObject<{
94
- kid: z.ZodString;
95
- createdAt: z.ZodNumber;
96
- version: z.ZodNumber;
97
- type: z.ZodLiteral<"asymmetric">;
98
- alg: z.ZodEnum<{
85
+ export declare const anyKeyDataSchema: import("@frontmcp/lazy-zod").ZodDiscriminatedUnion<[import("@frontmcp/lazy-zod").ZodObject<{
86
+ kid: import("@frontmcp/lazy-zod").ZodString;
87
+ createdAt: import("@frontmcp/lazy-zod").ZodNumber;
88
+ version: import("@frontmcp/lazy-zod").ZodNumber;
89
+ type: import("@frontmcp/lazy-zod").ZodLiteral<"secret">;
90
+ secret: import("@frontmcp/lazy-zod").ZodString;
91
+ bytes: import("@frontmcp/lazy-zod").ZodNumber;
92
+ }, import("zod/v4/core").$strip>, import("@frontmcp/lazy-zod").ZodObject<{
93
+ kid: import("@frontmcp/lazy-zod").ZodString;
94
+ createdAt: import("@frontmcp/lazy-zod").ZodNumber;
95
+ version: import("@frontmcp/lazy-zod").ZodNumber;
96
+ type: import("@frontmcp/lazy-zod").ZodLiteral<"asymmetric">;
97
+ alg: import("@frontmcp/lazy-zod").ZodEnum<{
99
98
  RS256: "RS256";
100
99
  RS384: "RS384";
101
100
  RS512: "RS512";
@@ -103,43 +102,43 @@ export declare const anyKeyDataSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
103
102
  ES384: "ES384";
104
103
  ES512: "ES512";
105
104
  }>;
106
- privateKey: z.ZodObject<{
107
- kty: z.ZodOptional<z.ZodString>;
108
- use: z.ZodOptional<z.ZodString>;
109
- alg: z.ZodOptional<z.ZodString>;
110
- kid: z.ZodOptional<z.ZodString>;
111
- n: z.ZodOptional<z.ZodString>;
112
- e: z.ZodOptional<z.ZodString>;
113
- d: z.ZodOptional<z.ZodString>;
114
- p: z.ZodOptional<z.ZodString>;
115
- q: z.ZodOptional<z.ZodString>;
116
- dp: z.ZodOptional<z.ZodString>;
117
- dq: z.ZodOptional<z.ZodString>;
118
- qi: z.ZodOptional<z.ZodString>;
119
- x: z.ZodOptional<z.ZodString>;
120
- y: z.ZodOptional<z.ZodString>;
121
- crv: z.ZodOptional<z.ZodString>;
122
- }, z.core.$loose>;
123
- publicJwk: z.ZodObject<{
124
- keys: z.ZodArray<z.ZodObject<{
125
- kty: z.ZodOptional<z.ZodString>;
126
- use: z.ZodOptional<z.ZodString>;
127
- alg: z.ZodOptional<z.ZodString>;
128
- kid: z.ZodOptional<z.ZodString>;
129
- n: z.ZodOptional<z.ZodString>;
130
- e: z.ZodOptional<z.ZodString>;
131
- d: z.ZodOptional<z.ZodString>;
132
- p: z.ZodOptional<z.ZodString>;
133
- q: z.ZodOptional<z.ZodString>;
134
- dp: z.ZodOptional<z.ZodString>;
135
- dq: z.ZodOptional<z.ZodString>;
136
- qi: z.ZodOptional<z.ZodString>;
137
- x: z.ZodOptional<z.ZodString>;
138
- y: z.ZodOptional<z.ZodString>;
139
- crv: z.ZodOptional<z.ZodString>;
140
- }, z.core.$loose>>;
141
- }, z.core.$strip>;
142
- }, z.core.$strip>], "type">;
105
+ privateKey: import("@frontmcp/lazy-zod").ZodObject<{
106
+ kty: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
107
+ use: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
108
+ alg: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
109
+ kid: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
110
+ n: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
111
+ e: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
112
+ d: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
113
+ p: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
114
+ q: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
115
+ dp: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
116
+ dq: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
117
+ qi: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
118
+ x: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
119
+ y: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
120
+ crv: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
121
+ }, import("zod/v4/core").$loose>;
122
+ publicJwk: import("@frontmcp/lazy-zod").ZodObject<{
123
+ keys: import("@frontmcp/lazy-zod").ZodArray<import("@frontmcp/lazy-zod").ZodObject<{
124
+ kty: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
125
+ use: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
126
+ alg: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
127
+ kid: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
128
+ n: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
129
+ e: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
130
+ d: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
131
+ p: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
132
+ q: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
133
+ dp: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
134
+ dq: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
135
+ qi: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
136
+ x: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
137
+ y: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
138
+ crv: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
139
+ }, import("zod/v4/core").$loose>>;
140
+ }, import("zod/v4/core").$strip>;
141
+ }, import("zod/v4/core").$strip>], "type">;
143
142
  /**
144
143
  * Result of validating key data.
145
144
  */
@@ -3,16 +3,15 @@
3
3
  *
4
4
  * @module @frontmcp/utils/secret-persistence
5
5
  */
6
- import { z } from 'zod';
7
6
  import type { SecretData, SecretValidationResult } from './types';
8
7
  /**
9
8
  * Zod schema for SecretData.
10
9
  */
11
- export declare const secretDataSchema: z.ZodObject<{
12
- secret: z.ZodString;
13
- createdAt: z.ZodNumber;
14
- version: z.ZodNumber;
15
- }, z.core.$strict>;
10
+ export declare const secretDataSchema: import("@frontmcp/lazy-zod").ZodObject<{
11
+ secret: import("@frontmcp/lazy-zod").ZodString;
12
+ createdAt: import("@frontmcp/lazy-zod").ZodNumber;
13
+ version: import("@frontmcp/lazy-zod").ZodNumber;
14
+ }, import("zod/v4/core").$strict>;
16
15
  /**
17
16
  * Validate secret data structure.
18
17
  *
@@ -4,7 +4,6 @@
4
4
  * Returns safe defaults for browser environments.
5
5
  * The isEntryAvailable matcher works identically to the Node version.
6
6
  */
7
- import { z } from 'zod';
8
7
  export interface RuntimeContext {
9
8
  platform: string;
10
9
  runtime: string;
@@ -17,12 +16,12 @@ export interface EntryAvailability {
17
16
  deployment?: string[];
18
17
  env?: string[];
19
18
  }
20
- export declare const entryAvailabilitySchema: z.ZodObject<{
21
- platform: z.ZodOptional<z.ZodArray<z.ZodString>>;
22
- runtime: z.ZodOptional<z.ZodArray<z.ZodString>>;
23
- deployment: z.ZodOptional<z.ZodArray<z.ZodString>>;
24
- env: z.ZodOptional<z.ZodArray<z.ZodString>>;
25
- }, z.core.$strict>;
19
+ export declare const entryAvailabilitySchema: import("@frontmcp/lazy-zod").ZodObject<{
20
+ platform: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodArray<import("@frontmcp/lazy-zod").ZodString>>;
21
+ runtime: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodArray<import("@frontmcp/lazy-zod").ZodString>>;
22
+ deployment: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodArray<import("@frontmcp/lazy-zod").ZodString>>;
23
+ env: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodArray<import("@frontmcp/lazy-zod").ZodString>>;
24
+ }, import("zod/v4/core").$strict>;
26
25
  export declare function isEntryAvailable(availability: EntryAvailability | undefined, ctx: RuntimeContext): boolean;
27
26
  export declare function detectRuntimeContext(): RuntimeContext;
28
27
  export declare function getRuntimeContext(): RuntimeContext;
@@ -7,7 +7,6 @@
7
7
  * - `getRuntimeContext()` — lazy singleton returning the detected context
8
8
  * - `isEntryAvailable()` — pure matcher: does the constraint match the context?
9
9
  */
10
- import { z } from 'zod';
11
10
  /**
12
11
  * Snapshot of the current runtime environment.
13
12
  * Detected once and cached for the lifetime of the process.
@@ -17,7 +16,7 @@ export interface RuntimeContext {
17
16
  platform: string;
18
17
  /** JavaScript runtime: 'node', 'bun', 'deno', 'edge', 'browser' */
19
18
  runtime: string;
20
- /** Deployment mode: 'serverless' or 'standalone' */
19
+ /** Deployment mode: 'distributed', 'serverless', 'standalone', or 'browser' */
21
20
  deployment: string;
22
21
  /** NODE_ENV value: 'production', 'development', 'test', etc. */
23
22
  env: string;
@@ -47,7 +46,7 @@ export interface EntryAvailability {
47
46
  platform?: string[];
48
47
  /** Runtime constraint: 'node', 'browser', 'edge', 'bun', 'deno' */
49
48
  runtime?: string[];
50
- /** Deployment constraint: 'serverless', 'standalone' */
49
+ /** Deployment constraint: 'distributed', 'serverless', 'standalone', 'browser' */
51
50
  deployment?: string[];
52
51
  /** Environment constraint: 'production', 'development', 'test', etc. */
53
52
  env?: string[];
@@ -55,12 +54,12 @@ export interface EntryAvailability {
55
54
  /**
56
55
  * Zod schema for validating EntryAvailability in metadata.
57
56
  */
58
- export declare const entryAvailabilitySchema: z.ZodObject<{
59
- platform: z.ZodOptional<z.ZodArray<z.ZodString>>;
60
- runtime: z.ZodOptional<z.ZodArray<z.ZodString>>;
61
- deployment: z.ZodOptional<z.ZodArray<z.ZodString>>;
62
- env: z.ZodOptional<z.ZodArray<z.ZodString>>;
63
- }, z.core.$strict>;
57
+ export declare const entryAvailabilitySchema: import("@frontmcp/lazy-zod").ZodObject<{
58
+ platform: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodArray<import("@frontmcp/lazy-zod").ZodString>>;
59
+ runtime: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodArray<import("@frontmcp/lazy-zod").ZodString>>;
60
+ deployment: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodArray<import("@frontmcp/lazy-zod").ZodString>>;
61
+ env: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodArray<import("@frontmcp/lazy-zod").ZodString>>;
62
+ }, import("zod/v4/core").$strict>;
64
63
  /**
65
64
  * Check if an entry is available in the given runtime context.
66
65
  *
package/esm/index.mjs CHANGED
@@ -403,7 +403,7 @@ var init_pkce2 = __esm({
403
403
  });
404
404
 
405
405
  // libs/utils/src/crypto/secret-persistence/schema.ts
406
- import { z } from "zod";
406
+ import { z } from "@frontmcp/lazy-zod";
407
407
  function validateSecretData(data) {
408
408
  const result = secretDataSchema.safeParse(data);
409
409
  if (!result.success) {
@@ -690,7 +690,7 @@ var init_hmac_signing = __esm({
690
690
  });
691
691
 
692
692
  // libs/utils/src/crypto/key-persistence/schemas.ts
693
- import { z as z2 } from "zod";
693
+ import { z as z2 } from "@frontmcp/lazy-zod";
694
694
  function validateKeyData(data) {
695
695
  const result = anyKeyDataSchema.safeParse(data);
696
696
  if (!result.success) {
@@ -4199,6 +4199,85 @@ function validateBaseUrl(url) {
4199
4199
  }
4200
4200
  }
4201
4201
 
4202
+ // libs/utils/src/http/cookie.ts
4203
+ init_runtime();
4204
+ var LOCALHOST_PATTERNS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "::1", "0.0.0.0"]);
4205
+ function isLocalhost(host) {
4206
+ if (!host) return false;
4207
+ if (host.startsWith("[")) {
4208
+ const closeBracket = host.indexOf("]");
4209
+ if (closeBracket > 0) {
4210
+ return LOCALHOST_PATTERNS.has(host.slice(1, closeBracket));
4211
+ }
4212
+ }
4213
+ if (LOCALHOST_PATTERNS.has(host)) return true;
4214
+ const lastColon = host.lastIndexOf(":");
4215
+ if (lastColon > 0) {
4216
+ const hostname = host.slice(0, lastColon);
4217
+ return LOCALHOST_PATTERNS.has(hostname);
4218
+ }
4219
+ return false;
4220
+ }
4221
+ function isSecureRequest(req) {
4222
+ if (!req) return false;
4223
+ if (req.protocol === "https") return true;
4224
+ const forwarded = req.headers?.["x-forwarded-proto"];
4225
+ const forwardedStr = (Array.isArray(forwarded) ? forwarded[0] : forwarded)?.split(",")[0]?.trim()?.toLowerCase();
4226
+ if (forwardedStr === "https") return true;
4227
+ if (req.socket?.encrypted) return true;
4228
+ return false;
4229
+ }
4230
+ function buildSetCookie(options, req) {
4231
+ if (!isNode()) return null;
4232
+ const { name, value, path = "/", maxAge = 86400, httpOnly = true, sameSite = "Strict", domain } = options;
4233
+ let secure;
4234
+ if (options.secure !== void 0) {
4235
+ secure = options.secure;
4236
+ } else {
4237
+ const host = req?.headers?.["host"];
4238
+ const hostStr = Array.isArray(host) ? host[0] : host;
4239
+ if (isLocalhost(hostStr)) {
4240
+ secure = false;
4241
+ } else if (req) {
4242
+ secure = isSecureRequest(req);
4243
+ } else {
4244
+ secure = process.env["NODE_ENV"] === "production";
4245
+ }
4246
+ }
4247
+ if (sameSite === "None" && !secure) {
4248
+ secure = true;
4249
+ }
4250
+ const parts = [`${encodeURIComponent(name)}=${encodeURIComponent(value)}`];
4251
+ parts.push(`Path=${path}`);
4252
+ parts.push(`Max-Age=${maxAge}`);
4253
+ if (httpOnly) parts.push("HttpOnly");
4254
+ if (secure) parts.push("Secure");
4255
+ parts.push(`SameSite=${sameSite}`);
4256
+ if (domain) parts.push(`Domain=${domain}`);
4257
+ return parts.join("; ");
4258
+ }
4259
+ function parseCookies(cookieHeader) {
4260
+ const cookies = {};
4261
+ if (!cookieHeader) return cookies;
4262
+ const pairs = cookieHeader.split(";");
4263
+ for (const pair of pairs) {
4264
+ const eqIdx = pair.indexOf("=");
4265
+ if (eqIdx < 0) continue;
4266
+ try {
4267
+ const name = decodeURIComponent(pair.slice(0, eqIdx).trim());
4268
+ const value = decodeURIComponent(pair.slice(eqIdx + 1).trim());
4269
+ if (name) cookies[name] = value;
4270
+ } catch {
4271
+ continue;
4272
+ }
4273
+ }
4274
+ return cookies;
4275
+ }
4276
+ function getCookie(cookieHeader, name) {
4277
+ if (!cookieHeader) return void 0;
4278
+ return parseCookies(cookieHeader)[name];
4279
+ }
4280
+
4202
4281
  // libs/utils/src/index.ts
4203
4282
  init_fs2();
4204
4283
 
@@ -4283,7 +4362,7 @@ import {
4283
4362
  } from "#env";
4284
4363
 
4285
4364
  // libs/utils/src/env/runtime-context.ts
4286
- import { z as z3 } from "zod";
4365
+ import { z as z3 } from "@frontmcp/lazy-zod";
4287
4366
  import { isEdgeRuntime, isServerless } from "#env";
4288
4367
  var entryAvailabilitySchema = z3.object({
4289
4368
  platform: z3.array(z3.string().min(1)).optional(),
@@ -4308,11 +4387,20 @@ function detectRuntime() {
4308
4387
  if (isEdgeRuntime()) return "edge";
4309
4388
  return "node";
4310
4389
  }
4390
+ function detectDeployment(runtime) {
4391
+ const explicit = process.env["FRONTMCP_DEPLOYMENT_MODE"];
4392
+ if (explicit === "distributed") return "distributed";
4393
+ if (explicit === "serverless") return "serverless";
4394
+ if (runtime === "browser") return "browser";
4395
+ if (isServerless()) return "serverless";
4396
+ return "standalone";
4397
+ }
4311
4398
  function detectRuntimeContext() {
4399
+ const runtime = detectRuntime();
4312
4400
  return {
4313
4401
  platform: process.platform,
4314
- runtime: detectRuntime(),
4315
- deployment: isServerless() ? "serverless" : "standalone",
4402
+ runtime,
4403
+ deployment: detectDeployment(runtime),
4316
4404
  env: process.env["NODE_ENV"] || "development"
4317
4405
  };
4318
4406
  }
@@ -5139,6 +5227,87 @@ async function processVercel(info, callTool) {
5139
5227
  const args = info.args != null && typeof info.args === "object" && !Array.isArray(info.args) ? info.args : void 0;
5140
5228
  return callTool(info.toolName, args);
5141
5229
  }
5230
+
5231
+ // libs/utils/src/machine-id/machine-id.ts
5232
+ init_crypto();
5233
+ init_runtime();
5234
+ function getEnvDirect(key) {
5235
+ return typeof process !== "undefined" ? process.env[key] : void 0;
5236
+ }
5237
+ function isProductionDirect() {
5238
+ return getEnvDirect("NODE_ENV") === "production";
5239
+ }
5240
+ var DEFAULT_MACHINE_ID_PATH = ".frontmcp/machine-id";
5241
+ function isDevPersistenceEnabled() {
5242
+ if (isBrowser()) return false;
5243
+ return !isProductionDirect();
5244
+ }
5245
+ function resolveMachineIdPath() {
5246
+ if (isBrowser()) return DEFAULT_MACHINE_ID_PATH;
5247
+ const path = __require("path");
5248
+ const machineIdPath = getEnvDirect("MACHINE_ID_PATH") ?? DEFAULT_MACHINE_ID_PATH;
5249
+ const cwd = typeof process !== "undefined" ? process.cwd() : ".";
5250
+ return path.isAbsolute(machineIdPath) ? machineIdPath : path.resolve(cwd, machineIdPath);
5251
+ }
5252
+ function loadMachineIdSync() {
5253
+ if (!isDevPersistenceEnabled()) return null;
5254
+ const machineIdPath = resolveMachineIdPath();
5255
+ try {
5256
+ const fs = __require("fs");
5257
+ const content = fs.readFileSync(machineIdPath, "utf8").trim();
5258
+ if (/^[0-9a-f-]{32,36}$/i.test(content)) return content;
5259
+ console.warn(`[MachineId] Invalid format at ${machineIdPath}, will regenerate`);
5260
+ return null;
5261
+ } catch (error) {
5262
+ if (error.code !== "ENOENT") {
5263
+ console.warn(`[MachineId] Failed to load from ${machineIdPath}: ${error.message}`);
5264
+ }
5265
+ return null;
5266
+ }
5267
+ }
5268
+ function saveMachineIdAsync(machineId2) {
5269
+ if (!isDevPersistenceEnabled()) return;
5270
+ const machineIdPath = resolveMachineIdPath();
5271
+ const path = __require("path");
5272
+ const dir = path.dirname(machineIdPath);
5273
+ (async () => {
5274
+ try {
5275
+ const fsp = __require("fs").promises;
5276
+ await fsp.mkdir(dir, { recursive: true, mode: 448 });
5277
+ await fsp.writeFile(machineIdPath, machineId2, { mode: 384 });
5278
+ } catch (error) {
5279
+ console.warn(`[MachineId] Failed to save to ${machineIdPath}: ${error.message}`);
5280
+ }
5281
+ })();
5282
+ }
5283
+ var machineId = (() => {
5284
+ const envMachineId = getEnvDirect("MACHINE_ID");
5285
+ if (envMachineId) return envMachineId;
5286
+ const deploymentMode = getEnvDirect("FRONTMCP_DEPLOYMENT_MODE");
5287
+ if (deploymentMode === "distributed") {
5288
+ const hostname = getEnvDirect("HOSTNAME");
5289
+ if (hostname) return hostname;
5290
+ if (isNode()) {
5291
+ const os = __require("os");
5292
+ return os.hostname();
5293
+ }
5294
+ }
5295
+ if (deploymentMode === "serverless") {
5296
+ return randomUUID();
5297
+ }
5298
+ const loadedId = loadMachineIdSync();
5299
+ if (loadedId) return loadedId;
5300
+ const newId = randomUUID();
5301
+ saveMachineIdAsync(newId);
5302
+ return newId;
5303
+ })();
5304
+ var machineIdOverride;
5305
+ function getMachineId() {
5306
+ return machineIdOverride ?? machineId;
5307
+ }
5308
+ function setMachineIdOverride(id) {
5309
+ machineIdOverride = id;
5310
+ }
5142
5311
  export {
5143
5312
  AsyncLocalStorage,
5144
5313
  BaseStorageAdapter,
@@ -5182,6 +5351,7 @@ export {
5182
5351
  base64urlEncode,
5183
5352
  basename,
5184
5353
  buildPrefix,
5354
+ buildSetCookie,
5185
5355
  bytesToHex,
5186
5356
  clearCachedSecret,
5187
5357
  collapseChar,
@@ -5226,11 +5396,13 @@ export {
5226
5396
  generateCodeVerifier,
5227
5397
  generatePkcePair,
5228
5398
  generateSecret,
5399
+ getCookie,
5229
5400
  getCrypto,
5230
5401
  getCwd2 as getCwd,
5231
5402
  getDetectedStorageType,
5232
5403
  getEnv2 as getEnv,
5233
5404
  getEnvFlag,
5405
+ getMachineId,
5234
5406
  getOrCreateSecret,
5235
5407
  getRuntimeContext,
5236
5408
  globToRegex,
@@ -5248,6 +5420,7 @@ export {
5248
5420
  isEntryAvailable,
5249
5421
  isExpired,
5250
5422
  isInputLengthSafe,
5423
+ isLocalhost,
5251
5424
  isNode,
5252
5425
  isPatternSafe,
5253
5426
  isProduction,
@@ -5255,6 +5428,7 @@ export {
5255
5428
  isSecretCached,
5256
5429
  isSecretKeyData,
5257
5430
  isSecretPersistenceEnabled,
5431
+ isSecureRequest,
5258
5432
  isServerless2 as isServerless,
5259
5433
  isSignedData,
5260
5434
  isUriTemplate,
@@ -5271,6 +5445,7 @@ export {
5271
5445
  mkdir,
5272
5446
  mkdtemp,
5273
5447
  normalizeTTL,
5448
+ parseCookies,
5274
5449
  parseKeyData,
5275
5450
  parseSecretData,
5276
5451
  parseUriTemplate,
@@ -5303,6 +5478,7 @@ export {
5303
5478
  sepFor,
5304
5479
  serializeBlob,
5305
5480
  setEnv,
5481
+ setMachineIdOverride,
5306
5482
  sha256,
5307
5483
  sha256Base64url,
5308
5484
  sha256Hex,
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Cookie Utilities
3
+ *
4
+ * Browser-safe cookie building, parsing, and extraction.
5
+ * Auto-detects Secure flag based on environment (localhost, HTTPS, browser).
6
+ */
7
+ /**
8
+ * Options for building a Set-Cookie header value.
9
+ */
10
+ export interface CookieOptions {
11
+ /** Cookie name */
12
+ name: string;
13
+ /** Cookie value */
14
+ value: string;
15
+ /** Cookie path (default: '/') */
16
+ path?: string;
17
+ /** Max age in seconds (default: 86400 = 24h) */
18
+ maxAge?: number;
19
+ /** HttpOnly flag — prevents JS access (default: true) */
20
+ httpOnly?: boolean;
21
+ /** SameSite policy (default: 'Strict') */
22
+ sameSite?: 'Strict' | 'Lax' | 'None';
23
+ /** Secure flag — if omitted, auto-detected from request context */
24
+ secure?: boolean;
25
+ /** Domain for the cookie (default: omitted = current domain) */
26
+ domain?: string;
27
+ }
28
+ /**
29
+ * Check if a host string is localhost.
30
+ * Matches: localhost, 127.0.0.1, ::1, 0.0.0.0 (with or without port).
31
+ */
32
+ export declare function isLocalhost(host: string | undefined): boolean;
33
+ /**
34
+ * Minimal request shape for secure detection.
35
+ * Works with Express, Koa, raw Node.js, and plain objects.
36
+ */
37
+ export interface SecureDetectionRequest {
38
+ headers?: Record<string, string | string[] | undefined>;
39
+ protocol?: string;
40
+ socket?: {
41
+ encrypted?: boolean;
42
+ };
43
+ }
44
+ /**
45
+ * Detect if a request was made over HTTPS.
46
+ * Checks (in order): protocol field, X-Forwarded-Proto header, socket.encrypted.
47
+ */
48
+ export declare function isSecureRequest(req?: SecureDetectionRequest): boolean;
49
+ /**
50
+ * Build a Set-Cookie header value.
51
+ *
52
+ * Auto-detects the Secure flag based on environment:
53
+ * - Browser: returns `null` (server-side cookies don't apply)
54
+ * - localhost/127.0.0.1: omits Secure (dev mode works over HTTP)
55
+ * - HTTPS request: sets Secure
56
+ * - No request context: sets Secure in production, omits in development
57
+ *
58
+ * @param options - Cookie options
59
+ * @param req - Optional request for auto-detecting Secure and localhost
60
+ * @returns Set-Cookie header value, or `null` if cookies don't apply (browser-only environment)
61
+ */
62
+ export declare function buildSetCookie(options: CookieOptions, req?: SecureDetectionRequest): string | null;
63
+ /**
64
+ * Parse a Cookie header string into key-value pairs.
65
+ * Works in both Node.js and browser environments.
66
+ *
67
+ * @param cookieHeader - The Cookie header value (e.g., "name=value; other=123")
68
+ * @returns Record of cookie name to value
69
+ */
70
+ export declare function parseCookies(cookieHeader: string): Record<string, string>;
71
+ /**
72
+ * Extract a specific cookie value from a Cookie header string.
73
+ *
74
+ * @param cookieHeader - The Cookie header value
75
+ * @param name - Cookie name to find
76
+ * @returns The cookie value, or undefined if not found
77
+ */
78
+ export declare function getCookie(cookieHeader: string | undefined, name: string): string | undefined;
package/http/index.d.ts CHANGED
@@ -1 +1,3 @@
1
1
  export { validateBaseUrl } from './http';
2
+ export { buildSetCookie, parseCookies, getCookie, isLocalhost, isSecureRequest } from './cookie';
3
+ export type { CookieOptions, SecureDetectionRequest } from './cookie';
package/index.d.ts CHANGED
@@ -11,7 +11,8 @@ export { isValidMcpUri, extractUriScheme, isValidMcpUriTemplate, parseUriTemplat
11
11
  export type { ParsedUriTemplate } from './uri';
12
12
  export { trimSlashes, joinPath, pathResolve, pathJoin, basename, dirname, extname } from './path';
13
13
  export { sanitizeToJson, inferMimeType } from './content';
14
- export { validateBaseUrl } from './http';
14
+ export { validateBaseUrl, buildSetCookie, parseCookies, getCookie, isLocalhost, isSecureRequest } from './http';
15
+ export type { CookieOptions, SecureDetectionRequest } from './http';
15
16
  export { readFile, readFileSync, readFileBuffer, writeFile, mkdir, rename, unlink, stat, copyFile, cp, readdir, rm, mkdtemp, access, fileExists, readJSON, writeJSON, ensureDir, isDirEmpty, runCmd, } from './fs';
16
17
  export { escapeHtml, escapeHtmlAttr, escapeJsString, escapeScriptClose, safeJsonForScript } from './escape';
17
18
  export { safeStringify } from './serialization';
@@ -26,3 +27,4 @@ export { createStorage, createMemoryStorage, getDetectedStorageType, NamespacedS
26
27
  export type { StorageAdapter, NamespacedStorage, RootStorage, SetOptions, SetEntry, MessageHandler, Unsubscribe, MemoryAdapterOptions, RedisAdapterOptions, VercelKvAdapterOptions, UpstashAdapterOptions, StorageType, StorageConfig, } from './storage';
27
28
  export { processPlatformToolCalls } from './llm';
28
29
  export type { CallToolFn, OpenAIToolCallItem, OpenAIToolResponse, ClaudeToolUseBlock, ClaudeToolResultBlock, VercelToolCallInfo, PlatformToolCallsInput, PlatformToolCallsOutput, SupportedPlatform, } from './llm';
30
+ export { getMachineId, setMachineIdOverride } from './machine-id';
package/index.js CHANGED
@@ -433,16 +433,16 @@ function parseSecretData(data) {
433
433
  }
434
434
  return data;
435
435
  }
436
- var import_zod, secretDataSchema, MAX_CLOCK_DRIFT_MS, MAX_SECRET_AGE_MS;
436
+ var import_lazy_zod, secretDataSchema, MAX_CLOCK_DRIFT_MS, MAX_SECRET_AGE_MS;
437
437
  var init_schema = __esm({
438
438
  "libs/utils/src/crypto/secret-persistence/schema.ts"() {
439
439
  "use strict";
440
- import_zod = require("zod");
441
- secretDataSchema = import_zod.z.object({
442
- secret: import_zod.z.string().base64url().length(43),
440
+ import_lazy_zod = require("@frontmcp/lazy-zod");
441
+ secretDataSchema = import_lazy_zod.z.object({
442
+ secret: import_lazy_zod.z.string().base64url().length(43),
443
443
  // base64url of 32 bytes is exactly 43 chars
444
- createdAt: import_zod.z.number().positive().int(),
445
- version: import_zod.z.number().positive().int()
444
+ createdAt: import_lazy_zod.z.number().positive().int(),
445
+ version: import_lazy_zod.z.number().positive().int()
446
446
  }).strict();
447
447
  MAX_CLOCK_DRIFT_MS = 6e4;
448
448
  MAX_SECRET_AGE_MS = 100 * 365 * 24 * 60 * 60 * 1e3;
@@ -726,50 +726,50 @@ function isSecretKeyData(data) {
726
726
  function isAsymmetricKeyData(data) {
727
727
  return data.type === "asymmetric";
728
728
  }
729
- var import_zod2, MAX_CLOCK_DRIFT_MS2, MAX_KEY_AGE_MS, asymmetricAlgSchema, baseKeyDataSchema, jsonWebKeySchema, secretKeyDataSchema, asymmetricKeyDataSchema, anyKeyDataSchema;
729
+ var import_lazy_zod2, MAX_CLOCK_DRIFT_MS2, MAX_KEY_AGE_MS, asymmetricAlgSchema, baseKeyDataSchema, jsonWebKeySchema, secretKeyDataSchema, asymmetricKeyDataSchema, anyKeyDataSchema;
730
730
  var init_schemas = __esm({
731
731
  "libs/utils/src/crypto/key-persistence/schemas.ts"() {
732
732
  "use strict";
733
- import_zod2 = require("zod");
733
+ import_lazy_zod2 = require("@frontmcp/lazy-zod");
734
734
  MAX_CLOCK_DRIFT_MS2 = 6e4;
735
735
  MAX_KEY_AGE_MS = 100 * 365 * 24 * 60 * 60 * 1e3;
736
- asymmetricAlgSchema = import_zod2.z.enum(["RS256", "RS384", "RS512", "ES256", "ES384", "ES512"]);
737
- baseKeyDataSchema = import_zod2.z.object({
738
- kid: import_zod2.z.string().min(1),
739
- createdAt: import_zod2.z.number().positive().int(),
740
- version: import_zod2.z.number().positive().int()
736
+ asymmetricAlgSchema = import_lazy_zod2.z.enum(["RS256", "RS384", "RS512", "ES256", "ES384", "ES512"]);
737
+ baseKeyDataSchema = import_lazy_zod2.z.object({
738
+ kid: import_lazy_zod2.z.string().min(1),
739
+ createdAt: import_lazy_zod2.z.number().positive().int(),
740
+ version: import_lazy_zod2.z.number().positive().int()
741
741
  });
742
- jsonWebKeySchema = import_zod2.z.object({
743
- kty: import_zod2.z.string().optional(),
744
- use: import_zod2.z.string().optional(),
745
- alg: import_zod2.z.string().optional(),
746
- kid: import_zod2.z.string().optional(),
747
- n: import_zod2.z.string().optional(),
748
- e: import_zod2.z.string().optional(),
749
- d: import_zod2.z.string().optional(),
750
- p: import_zod2.z.string().optional(),
751
- q: import_zod2.z.string().optional(),
752
- dp: import_zod2.z.string().optional(),
753
- dq: import_zod2.z.string().optional(),
754
- qi: import_zod2.z.string().optional(),
755
- x: import_zod2.z.string().optional(),
756
- y: import_zod2.z.string().optional(),
757
- crv: import_zod2.z.string().optional()
742
+ jsonWebKeySchema = import_lazy_zod2.z.object({
743
+ kty: import_lazy_zod2.z.string().optional(),
744
+ use: import_lazy_zod2.z.string().optional(),
745
+ alg: import_lazy_zod2.z.string().optional(),
746
+ kid: import_lazy_zod2.z.string().optional(),
747
+ n: import_lazy_zod2.z.string().optional(),
748
+ e: import_lazy_zod2.z.string().optional(),
749
+ d: import_lazy_zod2.z.string().optional(),
750
+ p: import_lazy_zod2.z.string().optional(),
751
+ q: import_lazy_zod2.z.string().optional(),
752
+ dp: import_lazy_zod2.z.string().optional(),
753
+ dq: import_lazy_zod2.z.string().optional(),
754
+ qi: import_lazy_zod2.z.string().optional(),
755
+ x: import_lazy_zod2.z.string().optional(),
756
+ y: import_lazy_zod2.z.string().optional(),
757
+ crv: import_lazy_zod2.z.string().optional()
758
758
  }).passthrough();
759
759
  secretKeyDataSchema = baseKeyDataSchema.extend({
760
- type: import_zod2.z.literal("secret"),
761
- secret: import_zod2.z.string().min(1),
762
- bytes: import_zod2.z.number().positive().int()
760
+ type: import_lazy_zod2.z.literal("secret"),
761
+ secret: import_lazy_zod2.z.string().min(1),
762
+ bytes: import_lazy_zod2.z.number().positive().int()
763
763
  });
764
764
  asymmetricKeyDataSchema = baseKeyDataSchema.extend({
765
- type: import_zod2.z.literal("asymmetric"),
765
+ type: import_lazy_zod2.z.literal("asymmetric"),
766
766
  alg: asymmetricAlgSchema,
767
767
  privateKey: jsonWebKeySchema,
768
- publicJwk: import_zod2.z.object({
769
- keys: import_zod2.z.array(jsonWebKeySchema).min(1)
768
+ publicJwk: import_lazy_zod2.z.object({
769
+ keys: import_lazy_zod2.z.array(jsonWebKeySchema).min(1)
770
770
  })
771
771
  });
772
- anyKeyDataSchema = import_zod2.z.discriminatedUnion("type", [secretKeyDataSchema, asymmetricKeyDataSchema]);
772
+ anyKeyDataSchema = import_lazy_zod2.z.discriminatedUnion("type", [secretKeyDataSchema, asymmetricKeyDataSchema]);
773
773
  }
774
774
  });
775
775
 
@@ -3764,6 +3764,7 @@ __export(index_exports, {
3764
3764
  base64urlEncode: () => base64urlEncode,
3765
3765
  basename: () => import_path.basename,
3766
3766
  buildPrefix: () => buildPrefix,
3767
+ buildSetCookie: () => buildSetCookie,
3767
3768
  bytesToHex: () => bytesToHex,
3768
3769
  clearCachedSecret: () => clearCachedSecret,
3769
3770
  collapseChar: () => collapseChar,
@@ -3808,11 +3809,13 @@ __export(index_exports, {
3808
3809
  generateCodeVerifier: () => generateCodeVerifier,
3809
3810
  generatePkcePair: () => generatePkcePair,
3810
3811
  generateSecret: () => generateSecret,
3812
+ getCookie: () => getCookie,
3811
3813
  getCrypto: () => getCrypto,
3812
3814
  getCwd: () => import_env3.getCwd,
3813
3815
  getDetectedStorageType: () => getDetectedStorageType,
3814
3816
  getEnv: () => import_env3.getEnv,
3815
3817
  getEnvFlag: () => import_env3.getEnvFlag,
3818
+ getMachineId: () => getMachineId,
3816
3819
  getOrCreateSecret: () => getOrCreateSecret,
3817
3820
  getRuntimeContext: () => getRuntimeContext,
3818
3821
  globToRegex: () => globToRegex,
@@ -3830,6 +3833,7 @@ __export(index_exports, {
3830
3833
  isEntryAvailable: () => isEntryAvailable,
3831
3834
  isExpired: () => isExpired,
3832
3835
  isInputLengthSafe: () => isInputLengthSafe,
3836
+ isLocalhost: () => isLocalhost,
3833
3837
  isNode: () => isNode,
3834
3838
  isPatternSafe: () => isPatternSafe,
3835
3839
  isProduction: () => import_env3.isProduction,
@@ -3837,6 +3841,7 @@ __export(index_exports, {
3837
3841
  isSecretCached: () => isSecretCached,
3838
3842
  isSecretKeyData: () => isSecretKeyData,
3839
3843
  isSecretPersistenceEnabled: () => isSecretPersistenceEnabled,
3844
+ isSecureRequest: () => isSecureRequest,
3840
3845
  isServerless: () => import_env3.isServerless,
3841
3846
  isSignedData: () => isSignedData,
3842
3847
  isUriTemplate: () => isUriTemplate,
@@ -3853,6 +3858,7 @@ __export(index_exports, {
3853
3858
  mkdir: () => mkdir,
3854
3859
  mkdtemp: () => mkdtemp,
3855
3860
  normalizeTTL: () => normalizeTTL,
3861
+ parseCookies: () => parseCookies,
3856
3862
  parseKeyData: () => parseKeyData,
3857
3863
  parseSecretData: () => parseSecretData,
3858
3864
  parseUriTemplate: () => parseUriTemplate,
@@ -3885,6 +3891,7 @@ __export(index_exports, {
3885
3891
  sepFor: () => sepFor,
3886
3892
  serializeBlob: () => serializeBlob,
3887
3893
  setEnv: () => import_env3.setEnv,
3894
+ setMachineIdOverride: () => setMachineIdOverride,
3888
3895
  sha256: () => sha256,
3889
3896
  sha256Base64url: () => sha256Base64url,
3890
3897
  sha256Hex: () => sha256Hex,
@@ -4404,6 +4411,85 @@ function validateBaseUrl(url) {
4404
4411
  }
4405
4412
  }
4406
4413
 
4414
+ // libs/utils/src/http/cookie.ts
4415
+ init_runtime();
4416
+ var LOCALHOST_PATTERNS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "::1", "0.0.0.0"]);
4417
+ function isLocalhost(host) {
4418
+ if (!host) return false;
4419
+ if (host.startsWith("[")) {
4420
+ const closeBracket = host.indexOf("]");
4421
+ if (closeBracket > 0) {
4422
+ return LOCALHOST_PATTERNS.has(host.slice(1, closeBracket));
4423
+ }
4424
+ }
4425
+ if (LOCALHOST_PATTERNS.has(host)) return true;
4426
+ const lastColon = host.lastIndexOf(":");
4427
+ if (lastColon > 0) {
4428
+ const hostname = host.slice(0, lastColon);
4429
+ return LOCALHOST_PATTERNS.has(hostname);
4430
+ }
4431
+ return false;
4432
+ }
4433
+ function isSecureRequest(req) {
4434
+ if (!req) return false;
4435
+ if (req.protocol === "https") return true;
4436
+ const forwarded = req.headers?.["x-forwarded-proto"];
4437
+ const forwardedStr = (Array.isArray(forwarded) ? forwarded[0] : forwarded)?.split(",")[0]?.trim()?.toLowerCase();
4438
+ if (forwardedStr === "https") return true;
4439
+ if (req.socket?.encrypted) return true;
4440
+ return false;
4441
+ }
4442
+ function buildSetCookie(options, req) {
4443
+ if (!isNode()) return null;
4444
+ const { name, value, path = "/", maxAge = 86400, httpOnly = true, sameSite = "Strict", domain } = options;
4445
+ let secure;
4446
+ if (options.secure !== void 0) {
4447
+ secure = options.secure;
4448
+ } else {
4449
+ const host = req?.headers?.["host"];
4450
+ const hostStr = Array.isArray(host) ? host[0] : host;
4451
+ if (isLocalhost(hostStr)) {
4452
+ secure = false;
4453
+ } else if (req) {
4454
+ secure = isSecureRequest(req);
4455
+ } else {
4456
+ secure = process.env["NODE_ENV"] === "production";
4457
+ }
4458
+ }
4459
+ if (sameSite === "None" && !secure) {
4460
+ secure = true;
4461
+ }
4462
+ const parts = [`${encodeURIComponent(name)}=${encodeURIComponent(value)}`];
4463
+ parts.push(`Path=${path}`);
4464
+ parts.push(`Max-Age=${maxAge}`);
4465
+ if (httpOnly) parts.push("HttpOnly");
4466
+ if (secure) parts.push("Secure");
4467
+ parts.push(`SameSite=${sameSite}`);
4468
+ if (domain) parts.push(`Domain=${domain}`);
4469
+ return parts.join("; ");
4470
+ }
4471
+ function parseCookies(cookieHeader) {
4472
+ const cookies = {};
4473
+ if (!cookieHeader) return cookies;
4474
+ const pairs = cookieHeader.split(";");
4475
+ for (const pair of pairs) {
4476
+ const eqIdx = pair.indexOf("=");
4477
+ if (eqIdx < 0) continue;
4478
+ try {
4479
+ const name = decodeURIComponent(pair.slice(0, eqIdx).trim());
4480
+ const value = decodeURIComponent(pair.slice(eqIdx + 1).trim());
4481
+ if (name) cookies[name] = value;
4482
+ } catch {
4483
+ continue;
4484
+ }
4485
+ }
4486
+ return cookies;
4487
+ }
4488
+ function getCookie(cookieHeader, name) {
4489
+ if (!cookieHeader) return void 0;
4490
+ return parseCookies(cookieHeader)[name];
4491
+ }
4492
+
4407
4493
  // libs/utils/src/index.ts
4408
4494
  init_fs2();
4409
4495
 
@@ -4477,13 +4563,13 @@ var import_event_emitter2 = require("#event-emitter");
4477
4563
  var import_env3 = require("#env");
4478
4564
 
4479
4565
  // libs/utils/src/env/runtime-context.ts
4480
- var import_zod3 = require("zod");
4566
+ var import_lazy_zod3 = require("@frontmcp/lazy-zod");
4481
4567
  var import_env2 = require("#env");
4482
- var entryAvailabilitySchema = import_zod3.z.object({
4483
- platform: import_zod3.z.array(import_zod3.z.string().min(1)).optional(),
4484
- runtime: import_zod3.z.array(import_zod3.z.string().min(1)).optional(),
4485
- deployment: import_zod3.z.array(import_zod3.z.string().min(1)).optional(),
4486
- env: import_zod3.z.array(import_zod3.z.string().min(1)).optional()
4568
+ var entryAvailabilitySchema = import_lazy_zod3.z.object({
4569
+ platform: import_lazy_zod3.z.array(import_lazy_zod3.z.string().min(1)).optional(),
4570
+ runtime: import_lazy_zod3.z.array(import_lazy_zod3.z.string().min(1)).optional(),
4571
+ deployment: import_lazy_zod3.z.array(import_lazy_zod3.z.string().min(1)).optional(),
4572
+ env: import_lazy_zod3.z.array(import_lazy_zod3.z.string().min(1)).optional()
4487
4573
  }).strict();
4488
4574
  function isEntryAvailable(availability, ctx) {
4489
4575
  if (!availability) return true;
@@ -4502,11 +4588,20 @@ function detectRuntime() {
4502
4588
  if ((0, import_env2.isEdgeRuntime)()) return "edge";
4503
4589
  return "node";
4504
4590
  }
4591
+ function detectDeployment(runtime) {
4592
+ const explicit = process.env["FRONTMCP_DEPLOYMENT_MODE"];
4593
+ if (explicit === "distributed") return "distributed";
4594
+ if (explicit === "serverless") return "serverless";
4595
+ if (runtime === "browser") return "browser";
4596
+ if ((0, import_env2.isServerless)()) return "serverless";
4597
+ return "standalone";
4598
+ }
4505
4599
  function detectRuntimeContext() {
4600
+ const runtime = detectRuntime();
4506
4601
  return {
4507
4602
  platform: process.platform,
4508
- runtime: detectRuntime(),
4509
- deployment: (0, import_env2.isServerless)() ? "serverless" : "standalone",
4603
+ runtime,
4604
+ deployment: detectDeployment(runtime),
4510
4605
  env: process.env["NODE_ENV"] || "development"
4511
4606
  };
4512
4607
  }
@@ -5333,6 +5428,87 @@ async function processVercel(info, callTool) {
5333
5428
  const args = info.args != null && typeof info.args === "object" && !Array.isArray(info.args) ? info.args : void 0;
5334
5429
  return callTool(info.toolName, args);
5335
5430
  }
5431
+
5432
+ // libs/utils/src/machine-id/machine-id.ts
5433
+ init_crypto();
5434
+ init_runtime();
5435
+ function getEnvDirect(key) {
5436
+ return typeof process !== "undefined" ? process.env[key] : void 0;
5437
+ }
5438
+ function isProductionDirect() {
5439
+ return getEnvDirect("NODE_ENV") === "production";
5440
+ }
5441
+ var DEFAULT_MACHINE_ID_PATH = ".frontmcp/machine-id";
5442
+ function isDevPersistenceEnabled() {
5443
+ if (isBrowser()) return false;
5444
+ return !isProductionDirect();
5445
+ }
5446
+ function resolveMachineIdPath() {
5447
+ if (isBrowser()) return DEFAULT_MACHINE_ID_PATH;
5448
+ const path = require("path");
5449
+ const machineIdPath = getEnvDirect("MACHINE_ID_PATH") ?? DEFAULT_MACHINE_ID_PATH;
5450
+ const cwd = typeof process !== "undefined" ? process.cwd() : ".";
5451
+ return path.isAbsolute(machineIdPath) ? machineIdPath : path.resolve(cwd, machineIdPath);
5452
+ }
5453
+ function loadMachineIdSync() {
5454
+ if (!isDevPersistenceEnabled()) return null;
5455
+ const machineIdPath = resolveMachineIdPath();
5456
+ try {
5457
+ const fs = require("fs");
5458
+ const content = fs.readFileSync(machineIdPath, "utf8").trim();
5459
+ if (/^[0-9a-f-]{32,36}$/i.test(content)) return content;
5460
+ console.warn(`[MachineId] Invalid format at ${machineIdPath}, will regenerate`);
5461
+ return null;
5462
+ } catch (error) {
5463
+ if (error.code !== "ENOENT") {
5464
+ console.warn(`[MachineId] Failed to load from ${machineIdPath}: ${error.message}`);
5465
+ }
5466
+ return null;
5467
+ }
5468
+ }
5469
+ function saveMachineIdAsync(machineId2) {
5470
+ if (!isDevPersistenceEnabled()) return;
5471
+ const machineIdPath = resolveMachineIdPath();
5472
+ const path = require("path");
5473
+ const dir = path.dirname(machineIdPath);
5474
+ (async () => {
5475
+ try {
5476
+ const fsp = require("fs").promises;
5477
+ await fsp.mkdir(dir, { recursive: true, mode: 448 });
5478
+ await fsp.writeFile(machineIdPath, machineId2, { mode: 384 });
5479
+ } catch (error) {
5480
+ console.warn(`[MachineId] Failed to save to ${machineIdPath}: ${error.message}`);
5481
+ }
5482
+ })();
5483
+ }
5484
+ var machineId = (() => {
5485
+ const envMachineId = getEnvDirect("MACHINE_ID");
5486
+ if (envMachineId) return envMachineId;
5487
+ const deploymentMode = getEnvDirect("FRONTMCP_DEPLOYMENT_MODE");
5488
+ if (deploymentMode === "distributed") {
5489
+ const hostname = getEnvDirect("HOSTNAME");
5490
+ if (hostname) return hostname;
5491
+ if (isNode()) {
5492
+ const os = require("os");
5493
+ return os.hostname();
5494
+ }
5495
+ }
5496
+ if (deploymentMode === "serverless") {
5497
+ return randomUUID();
5498
+ }
5499
+ const loadedId = loadMachineIdSync();
5500
+ if (loadedId) return loadedId;
5501
+ const newId = randomUUID();
5502
+ saveMachineIdAsync(newId);
5503
+ return newId;
5504
+ })();
5505
+ var machineIdOverride;
5506
+ function getMachineId() {
5507
+ return machineIdOverride ?? machineId;
5508
+ }
5509
+ function setMachineIdOverride(id) {
5510
+ machineIdOverride = id;
5511
+ }
5336
5512
  // Annotate the CommonJS export names for ESM import in node:
5337
5513
  0 && (module.exports = {
5338
5514
  AsyncLocalStorage,
@@ -5377,6 +5553,7 @@ async function processVercel(info, callTool) {
5377
5553
  base64urlEncode,
5378
5554
  basename,
5379
5555
  buildPrefix,
5556
+ buildSetCookie,
5380
5557
  bytesToHex,
5381
5558
  clearCachedSecret,
5382
5559
  collapseChar,
@@ -5421,11 +5598,13 @@ async function processVercel(info, callTool) {
5421
5598
  generateCodeVerifier,
5422
5599
  generatePkcePair,
5423
5600
  generateSecret,
5601
+ getCookie,
5424
5602
  getCrypto,
5425
5603
  getCwd,
5426
5604
  getDetectedStorageType,
5427
5605
  getEnv,
5428
5606
  getEnvFlag,
5607
+ getMachineId,
5429
5608
  getOrCreateSecret,
5430
5609
  getRuntimeContext,
5431
5610
  globToRegex,
@@ -5443,6 +5622,7 @@ async function processVercel(info, callTool) {
5443
5622
  isEntryAvailable,
5444
5623
  isExpired,
5445
5624
  isInputLengthSafe,
5625
+ isLocalhost,
5446
5626
  isNode,
5447
5627
  isPatternSafe,
5448
5628
  isProduction,
@@ -5450,6 +5630,7 @@ async function processVercel(info, callTool) {
5450
5630
  isSecretCached,
5451
5631
  isSecretKeyData,
5452
5632
  isSecretPersistenceEnabled,
5633
+ isSecureRequest,
5453
5634
  isServerless,
5454
5635
  isSignedData,
5455
5636
  isUriTemplate,
@@ -5466,6 +5647,7 @@ async function processVercel(info, callTool) {
5466
5647
  mkdir,
5467
5648
  mkdtemp,
5468
5649
  normalizeTTL,
5650
+ parseCookies,
5469
5651
  parseKeyData,
5470
5652
  parseSecretData,
5471
5653
  parseUriTemplate,
@@ -5498,6 +5680,7 @@ async function processVercel(info, callTool) {
5498
5680
  sepFor,
5499
5681
  serializeBlob,
5500
5682
  setEnv,
5683
+ setMachineIdOverride,
5501
5684
  sha256,
5502
5685
  sha256Base64url,
5503
5686
  sha256Hex,
@@ -0,0 +1 @@
1
+ export { getMachineId, setMachineIdOverride } from './machine-id';
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Machine ID Utility
3
+ *
4
+ * Single source of truth for the machine ID used across session management,
5
+ * transport session affinity, and HA features.
6
+ *
7
+ * Resolution depends on deployment mode (set by `frontmcp build -t {target}`):
8
+ *
9
+ * **Distributed** (`FRONTMCP_DEPLOYMENT_MODE=distributed`):
10
+ * 1. MACHINE_ID env var (explicit override)
11
+ * 2. HOSTNAME env var (K8s pod name — auto-set by Kubernetes)
12
+ * 3. os.hostname() (non-K8s distributed)
13
+ *
14
+ * **Serverless** (`FRONTMCP_DEPLOYMENT_MODE=serverless`):
15
+ * 1. MACHINE_ID env var (explicit override)
16
+ * 2. Random UUID (ephemeral — no file persistence)
17
+ *
18
+ * **Standalone** (default — `node` or `cli` build targets):
19
+ * 1. MACHINE_ID env var (explicit override)
20
+ * 2. File persistence at `.frontmcp/machine-id` (dev mode)
21
+ * 3. Random UUID (production)
22
+ */
23
+ /**
24
+ * Get the current machine ID.
25
+ * Returns the override (if set via `setMachineIdOverride`) or the computed value.
26
+ */
27
+ export declare function getMachineId(): string;
28
+ /**
29
+ * Set a process-wide machine ID override.
30
+ * Pass `undefined` to clear the override and revert to the computed value.
31
+ */
32
+ export declare function setMachineIdOverride(id: string | undefined): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontmcp/utils",
3
- "version": "1.0.4",
3
+ "version": "1.1.0",
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",
@@ -29,12 +29,12 @@
29
29
  "dependencies": {
30
30
  "@noble/hashes": "^2.0.1",
31
31
  "@noble/ciphers": "^2.1.1",
32
- "@enclave-vm/ast": "^2.13.0",
33
- "zod": "^4.0.0"
32
+ "@enclave-vm/ast": "^2.13.0"
34
33
  },
35
34
  "peerDependencies": {
36
35
  "@vercel/kv": "^2.0.0 || ^3.0.0",
37
- "ioredis": "^5.0.0"
36
+ "ioredis": "^5.0.0",
37
+ "@frontmcp/lazy-zod": "1.1.0"
38
38
  },
39
39
  "peerDependenciesMeta": {
40
40
  "@vercel/kv": {
@@ -4,8 +4,8 @@
4
4
  * Type definitions for the EncryptedTypedStorage wrapper that provides
5
5
  * transparent encryption/decryption with key rotation support.
6
6
  */
7
+ import type { z } from '@frontmcp/lazy-zod';
7
8
  import type { SetOptions } from './types';
8
- import type { z } from 'zod';
9
9
  /**
10
10
  * Encryption key with identifier for key rotation support.
11
11
  */
@@ -4,8 +4,8 @@
4
4
  * Type definitions for the TypedStorage wrapper that provides
5
5
  * type-safe JSON serialization on top of StorageAdapter.
6
6
  */
7
+ import type { z } from '@frontmcp/lazy-zod';
7
8
  import type { SetOptions } from './types';
8
- import type { z } from 'zod';
9
9
  /**
10
10
  * Options for TypedStorage wrapper
11
11
  */
@@ -52,9 +52,12 @@ export declare function matchUriTemplate(template: string, uri: string): Record<
52
52
  /**
53
53
  * Expand a URI template with the given parameters.
54
54
  *
55
+ * Parameter values are **percent-encoded** per RFC 6570 Level 1 using
56
+ * `encodeURIComponent()`. Use {@link matchUriTemplate} to decode them back.
57
+ *
55
58
  * @param template - The URI template
56
- * @param params - Object with parameter values
57
- * @returns Expanded URI with parameters substituted
59
+ * @param params - Object with parameter values (raw, unencoded)
60
+ * @returns Expanded URI with parameters percent-encoded and substituted
58
61
  * @throws Error if a required parameter is missing
59
62
  *
60
63
  * @example
@@ -63,6 +66,10 @@ export declare function matchUriTemplate(template: string, uri: string): Record<
63
66
  *
64
67
  * expandUriTemplate("users/{userId}/posts/{postId}", { userId: "123", postId: "456" })
65
68
  * // "users/123/posts/456"
69
+ *
70
+ * // Special characters are percent-encoded:
71
+ * expandUriTemplate("notes://{id}", { id: "x-coredata://ABC/Note/1" })
72
+ * // "notes://x-coredata%3A%2F%2FABC%2FNote%2F1"
66
73
  */
67
74
  export declare function expandUriTemplate(template: string, params: Record<string, string>): string;
68
75
  /**