@frontmcp/utils 0.12.2 → 1.0.0-beta.10

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.
Files changed (48) hide show
  1. package/async-context/browser-async-context.d.ts +12 -0
  2. package/async-context/browser-async-context.js +49 -0
  3. package/async-context/index.d.ts +1 -0
  4. package/async-context/node-async-context.d.ts +1 -0
  5. package/async-context/node-async-context.js +30 -0
  6. package/crypto/browser.d.ts +16 -0
  7. package/crypto/browser.js +160 -0
  8. package/crypto/index.d.ts +15 -6
  9. package/crypto/jwt-alg.d.ts +5 -0
  10. package/crypto/key-persistence/factory.d.ts +8 -1
  11. package/crypto/key-persistence/types.d.ts +10 -2
  12. package/crypto/node.d.ts +2 -0
  13. package/crypto/node.js +185 -0
  14. package/env/browser-env.d.ts +17 -0
  15. package/env/browser-env.js +78 -0
  16. package/env/index.d.ts +1 -0
  17. package/env/node-env.d.ts +14 -0
  18. package/env/node-env.js +85 -0
  19. package/esm/async-context/browser-async-context.mjs +24 -0
  20. package/esm/async-context/node-async-context.mjs +5 -0
  21. package/esm/crypto/browser.mjs +131 -0
  22. package/esm/crypto/node.mjs +143 -0
  23. package/esm/env/browser-env.mjs +44 -0
  24. package/esm/env/node-env.mjs +51 -0
  25. package/esm/event-emitter/browser-event-emitter.mjs +49 -0
  26. package/esm/event-emitter/node-event-emitter.mjs +5 -0
  27. package/esm/index.mjs +3887 -3064
  28. package/event-emitter/browser-event-emitter.d.ts +19 -0
  29. package/event-emitter/browser-event-emitter.js +74 -0
  30. package/event-emitter/index.d.ts +1 -0
  31. package/event-emitter/node-event-emitter.d.ts +1 -0
  32. package/event-emitter/node-event-emitter.js +30 -0
  33. package/index.d.ts +14 -5
  34. package/index.js +4144 -3314
  35. package/llm/index.d.ts +2 -0
  36. package/llm/llm-tool-handler.types.d.ts +48 -0
  37. package/llm/llm-tool-handlers.d.ts +10 -0
  38. package/naming/index.d.ts +2 -1
  39. package/package.json +24 -2
  40. package/path/browser-path.d.ts +5 -0
  41. package/path/index.d.ts +1 -0
  42. package/path/node-path.d.ts +1 -0
  43. package/storage/adapters/index.d.ts +4 -0
  44. package/storage/adapters/indexeddb.d.ts +77 -0
  45. package/storage/adapters/localstorage.d.ts +84 -0
  46. package/storage/index.d.ts +2 -2
  47. package/uri/index.d.ts +2 -1
  48. package/esm/package.json +0 -69
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Browser polyfill for AsyncLocalStorage.
3
+ *
4
+ * Uses a simple stack-based approach, which is safe in single-threaded
5
+ * browser environments. Does not support `enterWith()` or `disable()`
6
+ * (neither is used in the FrontMCP codebase).
7
+ */
8
+ export declare class AsyncLocalStorage<T> {
9
+ private stack;
10
+ run<R>(store: T, callback: (...args: unknown[]) => R, ...args: unknown[]): R;
11
+ getStore(): T | undefined;
12
+ }
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // libs/utils/src/async-context/browser-async-context.ts
21
+ var browser_async_context_exports = {};
22
+ __export(browser_async_context_exports, {
23
+ AsyncLocalStorage: () => AsyncLocalStorage
24
+ });
25
+ module.exports = __toCommonJS(browser_async_context_exports);
26
+ var AsyncLocalStorage = class {
27
+ stack = [];
28
+ run(store, callback, ...args) {
29
+ this.stack.push(store);
30
+ try {
31
+ const result = callback(...args);
32
+ if (result instanceof Promise) {
33
+ return result.finally(() => this.stack.pop());
34
+ }
35
+ this.stack.pop();
36
+ return result;
37
+ } catch (err) {
38
+ this.stack.pop();
39
+ throw err;
40
+ }
41
+ }
42
+ getStore() {
43
+ return this.stack.length > 0 ? this.stack[this.stack.length - 1] : void 0;
44
+ }
45
+ };
46
+ // Annotate the CommonJS export names for ESM import in node:
47
+ 0 && (module.exports = {
48
+ AsyncLocalStorage
49
+ });
@@ -0,0 +1 @@
1
+ export { AsyncLocalStorage } from '#async-context';
@@ -0,0 +1 @@
1
+ export { AsyncLocalStorage } from 'node:async_hooks';
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // libs/utils/src/async-context/node-async-context.ts
21
+ var node_async_context_exports = {};
22
+ __export(node_async_context_exports, {
23
+ AsyncLocalStorage: () => import_node_async_hooks.AsyncLocalStorage
24
+ });
25
+ module.exports = __toCommonJS(node_async_context_exports);
26
+ var import_node_async_hooks = require("node:async_hooks");
27
+ // Annotate the CommonJS export names for ESM import in node:
28
+ 0 && (module.exports = {
29
+ AsyncLocalStorage
30
+ });
@@ -9,3 +9,19 @@ import type { CryptoProvider } from './types';
9
9
  * Browser-compatible crypto provider using @noble libraries.
10
10
  */
11
11
  export declare const browserCrypto: CryptoProvider;
12
+ /** Alias for conditional import resolution via `#crypto-provider`. */
13
+ export { browserCrypto as cryptoProvider };
14
+ export { isRsaPssAlg, jwtAlgToWebCryptoAlg } from './jwt-alg';
15
+ /**
16
+ * Verify an RSA signature using WebCrypto.
17
+ *
18
+ * Supports RS256/RS384/RS512 (RSASSA-PKCS1-v1_5) and PS256/PS384/PS512 (RSA-PSS).
19
+ * Works in both browsers and Node.js environments that provide `crypto.subtle`.
20
+ *
21
+ * @param jwtAlg - JWT algorithm identifier (e.g. 'RS256', 'PS256')
22
+ * @param data - The signed data (e.g. `headerB64.payloadB64`)
23
+ * @param publicJwk - Public key in JWK format
24
+ * @param signature - The signature bytes
25
+ * @returns true if the signature is valid
26
+ */
27
+ export declare function rsaVerifyBrowser(jwtAlg: string, data: Uint8Array, publicJwk: JsonWebKey, signature: Uint8Array): Promise<boolean>;
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // libs/utils/src/crypto/browser.ts
21
+ var browser_exports = {};
22
+ __export(browser_exports, {
23
+ browserCrypto: () => browserCrypto,
24
+ cryptoProvider: () => browserCrypto,
25
+ isRsaPssAlg: () => isRsaPssAlg,
26
+ jwtAlgToWebCryptoAlg: () => jwtAlgToWebCryptoAlg,
27
+ rsaVerifyBrowser: () => rsaVerifyBrowser
28
+ });
29
+ module.exports = __toCommonJS(browser_exports);
30
+ var import_sha2 = require("@noble/hashes/sha2.js");
31
+ var import_hmac = require("@noble/hashes/hmac.js");
32
+ var import_hkdf = require("@noble/hashes/hkdf.js");
33
+ var import_utils = require("@noble/hashes/utils.js");
34
+ var import_aes = require("@noble/ciphers/aes.js");
35
+
36
+ // libs/utils/src/crypto/jwt-alg.ts
37
+ function isRsaPssAlg(jwtAlg) {
38
+ return jwtAlg.startsWith("PS");
39
+ }
40
+ var JWT_ALG_TO_WEB_CRYPTO = {
41
+ RS256: "SHA-256",
42
+ RS384: "SHA-384",
43
+ RS512: "SHA-512",
44
+ PS256: "SHA-256",
45
+ PS384: "SHA-384",
46
+ PS512: "SHA-512"
47
+ };
48
+ function jwtAlgToWebCryptoAlg(jwtAlg) {
49
+ const webAlg = JWT_ALG_TO_WEB_CRYPTO[jwtAlg];
50
+ if (!webAlg) {
51
+ throw new Error(`Unsupported JWT algorithm for WebCrypto: ${jwtAlg}`);
52
+ }
53
+ return webAlg;
54
+ }
55
+
56
+ // libs/utils/src/crypto/browser.ts
57
+ function toBytes(data) {
58
+ if (typeof data === "string") {
59
+ return new TextEncoder().encode(data);
60
+ }
61
+ return data;
62
+ }
63
+ function toHex(bytes) {
64
+ return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
65
+ }
66
+ function generateUUID() {
67
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
68
+ return crypto.randomUUID();
69
+ }
70
+ const bytes = (0, import_utils.randomBytes)(16);
71
+ bytes[6] = bytes[6] & 15 | 64;
72
+ bytes[8] = bytes[8] & 63 | 128;
73
+ const hex = toHex(bytes);
74
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
75
+ }
76
+ function constantTimeEqual(a, b) {
77
+ if (a.length !== b.length) return false;
78
+ let result = 0;
79
+ for (let i = 0; i < a.length; i++) {
80
+ result |= a[i] ^ b[i];
81
+ }
82
+ return result === 0;
83
+ }
84
+ var browserCrypto = {
85
+ randomUUID() {
86
+ return generateUUID();
87
+ },
88
+ randomBytes(length) {
89
+ return (0, import_utils.randomBytes)(length);
90
+ },
91
+ sha256(data) {
92
+ return (0, import_sha2.sha256)(toBytes(data));
93
+ },
94
+ sha256Hex(data) {
95
+ return toHex((0, import_sha2.sha256)(toBytes(data)));
96
+ },
97
+ hmacSha256(key, data) {
98
+ return (0, import_hmac.hmac)(import_sha2.sha256, key, data);
99
+ },
100
+ hkdfSha256(ikm, salt, info, length) {
101
+ const effectiveSalt = salt.length > 0 ? salt : new Uint8Array(32);
102
+ return (0, import_hkdf.hkdf)(import_sha2.sha256, ikm, effectiveSalt, info, length);
103
+ },
104
+ encryptAesGcm(key, plaintext, iv) {
105
+ const cipher = (0, import_aes.gcm)(key, iv);
106
+ const sealed = cipher.encrypt(plaintext);
107
+ const ciphertext = sealed.slice(0, -16);
108
+ const tag = sealed.slice(-16);
109
+ return { ciphertext, tag };
110
+ },
111
+ decryptAesGcm(key, ciphertext, iv, tag) {
112
+ const cipher = (0, import_aes.gcm)(key, iv);
113
+ const sealed = new Uint8Array(ciphertext.length + tag.length);
114
+ sealed.set(ciphertext);
115
+ sealed.set(tag, ciphertext.length);
116
+ return cipher.decrypt(sealed);
117
+ },
118
+ timingSafeEqual(a, b) {
119
+ return constantTimeEqual(a, b);
120
+ }
121
+ };
122
+ async function rsaVerifyBrowser(jwtAlg, data, publicJwk, signature) {
123
+ if (typeof globalThis.crypto?.subtle === "undefined") {
124
+ throw new Error("WebCrypto API (crypto.subtle) is not available in this environment");
125
+ }
126
+ const webAlg = jwtAlgToWebCryptoAlg(jwtAlg);
127
+ const isPss = isRsaPssAlg(jwtAlg);
128
+ const algorithm = {
129
+ name: isPss ? "RSA-PSS" : "RSASSA-PKCS1-v1_5",
130
+ hash: { name: webAlg }
131
+ };
132
+ const key = await globalThis.crypto.subtle.importKey("jwk", publicJwk, algorithm, false, ["verify"]);
133
+ const verifyAlgorithm = isPss ? { name: "RSA-PSS", saltLength: getSaltLength(jwtAlg) } : { name: "RSASSA-PKCS1-v1_5" };
134
+ const sigBuf = new Uint8Array(signature).buffer;
135
+ const dataBuf = new Uint8Array(data).buffer;
136
+ return globalThis.crypto.subtle.verify(verifyAlgorithm, key, sigBuf, dataBuf);
137
+ }
138
+ function getSaltLength(jwtAlg) {
139
+ switch (jwtAlg) {
140
+ case "PS256":
141
+ return 32;
142
+ // SHA-256 digest length
143
+ case "PS384":
144
+ return 48;
145
+ // SHA-384 digest length
146
+ case "PS512":
147
+ return 64;
148
+ // SHA-512 digest length
149
+ default:
150
+ return 32;
151
+ }
152
+ }
153
+ // Annotate the CommonJS export names for ESM import in node:
154
+ 0 && (module.exports = {
155
+ browserCrypto,
156
+ cryptoProvider,
157
+ isRsaPssAlg,
158
+ jwtAlgToWebCryptoAlg,
159
+ rsaVerifyBrowser
160
+ });
package/crypto/index.d.ts CHANGED
@@ -5,16 +5,25 @@
5
5
  * Uses native crypto in Node.js and @noble/hashes + @noble/ciphers in browsers.
6
6
  */
7
7
  import type { CryptoProvider, EncBlob } from './types';
8
- export { isRsaPssAlg, jwtAlgToNodeAlg } from './jwt-alg';
8
+ export { isRsaPssAlg, jwtAlgToNodeAlg, jwtAlgToWebCryptoAlg } from './jwt-alg';
9
9
  /**
10
10
  * Get the crypto provider for the current runtime environment.
11
- * Lazily initializes the provider.
12
- *
13
- * Note: this module intentionally avoids importing any Node-only crypto modules
14
- * at module-load time so it can be used in browser builds without pulling them in.
11
+ * Resolved at build time via the `#crypto-provider` conditional import.
15
12
  */
16
13
  export declare function getCrypto(): CryptoProvider;
17
- export declare function rsaVerify(jwtAlg: string, data: Buffer, publicJwk: JsonWebKey, signature: Buffer): boolean;
14
+ /**
15
+ * Verify an RSA signature.
16
+ *
17
+ * Cross-platform: uses Node.js `crypto` module in Node environments,
18
+ * and WebCrypto `crypto.subtle.verify()` in browsers.
19
+ *
20
+ * @param jwtAlg - JWT algorithm identifier (e.g. 'RS256', 'PS256')
21
+ * @param data - The signed data bytes
22
+ * @param publicJwk - Public key in JWK format
23
+ * @param signature - The signature bytes
24
+ * @returns Promise resolving to true if the signature is valid
25
+ */
26
+ export declare function rsaVerify(jwtAlg: string, data: Buffer | Uint8Array, publicJwk: JsonWebKey, signature: Buffer | Uint8Array): Promise<boolean>;
18
27
  /**
19
28
  * Generate a UUID v4 string.
20
29
  */
@@ -6,3 +6,8 @@
6
6
  */
7
7
  export declare function jwtAlgToNodeAlg(jwtAlg: string): string;
8
8
  export declare function isRsaPssAlg(jwtAlg: string): boolean;
9
+ /**
10
+ * Map a JWT algorithm to a WebCrypto hash algorithm name.
11
+ * Used for `crypto.subtle.importKey()` and `crypto.subtle.verify()`.
12
+ */
13
+ export declare function jwtAlgToWebCryptoAlg(jwtAlg: string): string;
@@ -13,7 +13,8 @@ import type { CreateKeyPersistenceOptions } from './types';
13
13
  * Create a KeyPersistence instance with auto-detected storage.
14
14
  *
15
15
  * In Node.js: Uses filesystem storage at `.frontmcp/keys/` by default
16
- * In browser: Uses memory storage (keys lost on refresh)
16
+ * In browser: Uses IndexedDB (persistent) with localStorage fallback
17
+ * Fallback: Memory storage (keys lost on restart)
17
18
  *
18
19
  * @param options - Configuration options
19
20
  * @returns KeyPersistence instance (storage already connected)
@@ -26,6 +27,12 @@ import type { CreateKeyPersistenceOptions } from './types';
26
27
  * // Force memory storage
27
28
  * const memKeys = await createKeyPersistence({ type: 'memory' });
28
29
  *
30
+ * // Force IndexedDB (browser)
31
+ * const idbKeys = await createKeyPersistence({ type: 'indexeddb' });
32
+ *
33
+ * // Force localStorage (browser)
34
+ * const lsKeys = await createKeyPersistence({ type: 'localstorage' });
35
+ *
29
36
  * // Custom directory for filesystem
30
37
  * const fsKeys = await createKeyPersistence({
31
38
  * type: 'filesystem',
@@ -75,12 +75,14 @@ export interface KeyPersistenceOptions {
75
75
  export interface CreateKeyPersistenceOptions {
76
76
  /**
77
77
  * Storage type.
78
- * - 'auto': Auto-detect based on environment (filesystem in Node.js, memory in browser)
78
+ * - 'auto': Auto-detect based on environment (filesystem in Node.js, indexeddb in browser)
79
79
  * - 'memory': Always use memory (keys lost on restart)
80
80
  * - 'filesystem': Always use filesystem (Node.js only)
81
+ * - 'indexeddb': Use IndexedDB (browser only, persistent)
82
+ * - 'localstorage': Use localStorage (browser only, persistent, ~5MB limit)
81
83
  * @default 'auto'
82
84
  */
83
- type?: 'auto' | 'memory' | 'filesystem';
85
+ type?: 'auto' | 'memory' | 'filesystem' | 'indexeddb' | 'localstorage';
84
86
  /**
85
87
  * Base directory for filesystem storage.
86
88
  * Only used when type is 'filesystem' or 'auto' in Node.js.
@@ -97,6 +99,12 @@ export interface CreateKeyPersistenceOptions {
97
99
  * @default true
98
100
  */
99
101
  enableCache?: boolean;
102
+ /**
103
+ * Optional 32-byte AES-256-GCM key for encrypting values at rest in localStorage.
104
+ * Only used when type is 'localstorage' or 'auto' with localStorage fallback.
105
+ * If not provided, HKDF-SHA256 derives a key from a fixed IKM using the page origin.
106
+ */
107
+ encryptionKey?: Uint8Array;
100
108
  }
101
109
  /**
102
110
  * Options for creating a secret key.
package/crypto/node.d.ts CHANGED
@@ -10,6 +10,8 @@ export { isRsaPssAlg, jwtAlgToNodeAlg } from './jwt-alg';
10
10
  * Node.js crypto provider implementation.
11
11
  */
12
12
  export declare const nodeCrypto: CryptoProvider;
13
+ /** Alias for conditional import resolution via `#crypto-provider`. */
14
+ export { nodeCrypto as cryptoProvider };
13
15
  /**
14
16
  * RSA JWK structure for public keys
15
17
  */
package/crypto/node.js ADDED
@@ -0,0 +1,185 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // libs/utils/src/crypto/node.ts
31
+ var node_exports = {};
32
+ __export(node_exports, {
33
+ createSignedJwt: () => createSignedJwt,
34
+ cryptoProvider: () => nodeCrypto,
35
+ generateRsaKeyPair: () => generateRsaKeyPair,
36
+ isRsaPssAlg: () => isRsaPssAlg,
37
+ jwtAlgToNodeAlg: () => jwtAlgToNodeAlg,
38
+ nodeCrypto: () => nodeCrypto,
39
+ rsaSign: () => rsaSign,
40
+ rsaVerify: () => rsaVerify
41
+ });
42
+ module.exports = __toCommonJS(node_exports);
43
+ var import_node_crypto = __toESM(require("node:crypto"));
44
+
45
+ // libs/utils/src/crypto/jwt-alg.ts
46
+ var JWT_ALG_TO_NODE_DIGEST = {
47
+ RS256: "RSA-SHA256",
48
+ RS384: "RSA-SHA384",
49
+ RS512: "RSA-SHA512",
50
+ // For RSA-PSS, Node's crypto.sign/verify uses the digest algorithm + explicit PSS padding options.
51
+ PS256: "RSA-SHA256",
52
+ PS384: "RSA-SHA384",
53
+ PS512: "RSA-SHA512"
54
+ };
55
+ function jwtAlgToNodeAlg(jwtAlg) {
56
+ const nodeAlg = JWT_ALG_TO_NODE_DIGEST[jwtAlg];
57
+ if (!nodeAlg) {
58
+ throw new Error(`Unsupported JWT algorithm: ${jwtAlg}`);
59
+ }
60
+ return nodeAlg;
61
+ }
62
+ function isRsaPssAlg(jwtAlg) {
63
+ return jwtAlg.startsWith("PS");
64
+ }
65
+
66
+ // libs/utils/src/crypto/node.ts
67
+ function toUint8Array(buf) {
68
+ return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
69
+ }
70
+ function toBuffer(data) {
71
+ if (typeof data === "string") {
72
+ return Buffer.from(data, "utf8");
73
+ }
74
+ return Buffer.from(data);
75
+ }
76
+ var nodeCrypto = {
77
+ randomUUID() {
78
+ return import_node_crypto.default.randomUUID();
79
+ },
80
+ randomBytes(length) {
81
+ return toUint8Array(import_node_crypto.default.randomBytes(length));
82
+ },
83
+ sha256(data) {
84
+ const hash = import_node_crypto.default.createHash("sha256").update(toBuffer(data)).digest();
85
+ return toUint8Array(hash);
86
+ },
87
+ sha256Hex(data) {
88
+ return import_node_crypto.default.createHash("sha256").update(toBuffer(data)).digest("hex");
89
+ },
90
+ hmacSha256(key, data) {
91
+ const hmac = import_node_crypto.default.createHmac("sha256", Buffer.from(key)).update(Buffer.from(data)).digest();
92
+ return toUint8Array(hmac);
93
+ },
94
+ hkdfSha256(ikm, salt, info, length) {
95
+ const ikmBuf = Buffer.from(ikm);
96
+ const saltBuf = salt.length > 0 ? Buffer.from(salt) : Buffer.alloc(32);
97
+ const prk = import_node_crypto.default.createHmac("sha256", saltBuf).update(ikmBuf).digest();
98
+ const hashLen = 32;
99
+ const n = Math.ceil(length / hashLen);
100
+ const chunks = [];
101
+ let prev = Buffer.alloc(0);
102
+ for (let i = 1; i <= n; i++) {
103
+ prev = import_node_crypto.default.createHmac("sha256", prk).update(Buffer.concat([prev, Buffer.from(info), Buffer.from([i])])).digest();
104
+ chunks.push(prev);
105
+ }
106
+ return toUint8Array(Buffer.concat(chunks).subarray(0, length));
107
+ },
108
+ encryptAesGcm(key, plaintext, iv) {
109
+ const cipher = import_node_crypto.default.createCipheriv("aes-256-gcm", Buffer.from(key), Buffer.from(iv));
110
+ const encrypted = Buffer.concat([cipher.update(Buffer.from(plaintext)), cipher.final()]);
111
+ const tag = cipher.getAuthTag();
112
+ return {
113
+ ciphertext: toUint8Array(encrypted),
114
+ tag: toUint8Array(tag)
115
+ };
116
+ },
117
+ decryptAesGcm(key, ciphertext, iv, tag) {
118
+ const decipher = import_node_crypto.default.createDecipheriv("aes-256-gcm", Buffer.from(key), Buffer.from(iv));
119
+ decipher.setAuthTag(Buffer.from(tag));
120
+ const decrypted = Buffer.concat([decipher.update(Buffer.from(ciphertext)), decipher.final()]);
121
+ return toUint8Array(decrypted);
122
+ },
123
+ timingSafeEqual(a, b) {
124
+ if (a.length !== b.length) return false;
125
+ return import_node_crypto.default.timingSafeEqual(Buffer.from(a), Buffer.from(b));
126
+ }
127
+ };
128
+ function generateRsaKeyPair(modulusLength = 2048, alg = "RS256") {
129
+ const kid = `rsa-key-${Date.now()}-${import_node_crypto.default.randomBytes(8).toString("hex")}`;
130
+ const { privateKey, publicKey } = import_node_crypto.default.generateKeyPairSync("rsa", {
131
+ modulusLength
132
+ });
133
+ const exported = publicKey.export({ format: "jwk" });
134
+ const publicJwk = {
135
+ ...exported,
136
+ kid,
137
+ alg,
138
+ use: "sig",
139
+ kty: "RSA"
140
+ };
141
+ return { privateKey, publicKey, publicJwk };
142
+ }
143
+ function rsaSign(algorithm, data, privateKey, options) {
144
+ const signingKey = options ? { key: privateKey, ...options } : privateKey;
145
+ return import_node_crypto.default.sign(algorithm, data, signingKey);
146
+ }
147
+ function rsaVerify(jwtAlg, data, publicJwk, signature) {
148
+ const publicKey = import_node_crypto.default.createPublicKey({ key: publicJwk, format: "jwk" });
149
+ const nodeAlgorithm = jwtAlgToNodeAlg(jwtAlg);
150
+ const verifyKey = isRsaPssAlg(jwtAlg) ? {
151
+ key: publicKey,
152
+ padding: import_node_crypto.default.constants.RSA_PKCS1_PSS_PADDING,
153
+ saltLength: import_node_crypto.default.constants.RSA_PSS_SALTLEN_DIGEST
154
+ } : publicKey;
155
+ return import_node_crypto.default.verify(nodeAlgorithm, data, verifyKey, signature);
156
+ }
157
+ function createSignedJwt(payload, privateKey, kid, alg = "RS256") {
158
+ const header = { alg, typ: "JWT", kid };
159
+ const headerB64 = Buffer.from(JSON.stringify(header)).toString("base64url");
160
+ const payloadB64 = Buffer.from(JSON.stringify(payload)).toString("base64url");
161
+ const signatureInput = `${headerB64}.${payloadB64}`;
162
+ const nodeAlgorithm = jwtAlgToNodeAlg(alg);
163
+ const signature = rsaSign(
164
+ nodeAlgorithm,
165
+ Buffer.from(signatureInput),
166
+ privateKey,
167
+ isRsaPssAlg(alg) ? {
168
+ padding: import_node_crypto.default.constants.RSA_PKCS1_PSS_PADDING,
169
+ saltLength: import_node_crypto.default.constants.RSA_PSS_SALTLEN_DIGEST
170
+ } : void 0
171
+ );
172
+ const signatureB64 = signature.toString("base64url");
173
+ return `${headerB64}.${payloadB64}.${signatureB64}`;
174
+ }
175
+ // Annotate the CommonJS export names for ESM import in node:
176
+ 0 && (module.exports = {
177
+ createSignedJwt,
178
+ cryptoProvider,
179
+ generateRsaKeyPair,
180
+ isRsaPssAlg,
181
+ jwtAlgToNodeAlg,
182
+ nodeCrypto,
183
+ rsaSign,
184
+ rsaVerify
185
+ });
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Browser environment stubs.
3
+ *
4
+ * Returns safe defaults when running in a browser context
5
+ * where `process` is not available.
6
+ */
7
+ export declare function getEnv(_key: string): string | undefined;
8
+ export declare function getEnv(_key: string, defaultValue: string): string;
9
+ export declare function getCwd(): string;
10
+ export declare function isProduction(): boolean;
11
+ export declare function isDevelopment(): boolean;
12
+ export declare function getEnvFlag(_key: string): boolean;
13
+ export declare function isDebug(): boolean;
14
+ export declare function setEnv(_key: string, _value: string): void;
15
+ export declare function isEdgeRuntime(): boolean;
16
+ export declare function isServerless(): boolean;
17
+ export declare function supportsAnsi(): boolean;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // libs/utils/src/env/browser-env.ts
21
+ var browser_env_exports = {};
22
+ __export(browser_env_exports, {
23
+ getCwd: () => getCwd,
24
+ getEnv: () => getEnv,
25
+ getEnvFlag: () => getEnvFlag,
26
+ isDebug: () => isDebug,
27
+ isDevelopment: () => isDevelopment,
28
+ isEdgeRuntime: () => isEdgeRuntime,
29
+ isProduction: () => isProduction,
30
+ isServerless: () => isServerless,
31
+ setEnv: () => setEnv,
32
+ supportsAnsi: () => supportsAnsi
33
+ });
34
+ module.exports = __toCommonJS(browser_env_exports);
35
+ function getEnv(_key, defaultValue) {
36
+ return defaultValue;
37
+ }
38
+ function getCwd() {
39
+ return "/";
40
+ }
41
+ function isProduction() {
42
+ return false;
43
+ }
44
+ function isDevelopment() {
45
+ return false;
46
+ }
47
+ function getEnvFlag(_key) {
48
+ return false;
49
+ }
50
+ function isDebug() {
51
+ return false;
52
+ }
53
+ function setEnv(_key, _value) {
54
+ }
55
+ function isEdgeRuntime() {
56
+ if (typeof globalThis !== "undefined" && "EdgeRuntime" in globalThis) return true;
57
+ if (typeof globalThis !== "undefined" && "caches" in globalThis && !("window" in globalThis)) return true;
58
+ return false;
59
+ }
60
+ function isServerless() {
61
+ return false;
62
+ }
63
+ function supportsAnsi() {
64
+ return false;
65
+ }
66
+ // Annotate the CommonJS export names for ESM import in node:
67
+ 0 && (module.exports = {
68
+ getCwd,
69
+ getEnv,
70
+ getEnvFlag,
71
+ isDebug,
72
+ isDevelopment,
73
+ isEdgeRuntime,
74
+ isProduction,
75
+ isServerless,
76
+ setEnv,
77
+ supportsAnsi
78
+ });
package/env/index.d.ts ADDED
@@ -0,0 +1 @@
1
+ export { getEnv, getCwd, isProduction, isDevelopment, getEnvFlag, isDebug, setEnv, isEdgeRuntime, isServerless, supportsAnsi, } from '#env';