@frontmcp/utils 1.9.2 → 1.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/class-brand/class-brand.d.ts +37 -0
- package/class-brand/index.d.ts +1 -0
- package/crypto/browser.d.ts +5 -0
- package/crypto/browser.js +33 -5
- package/crypto/node.d.ts +1 -1
- package/esm/crypto/browser.mjs +27 -4
- package/esm/index.mjs +159 -238
- package/fs/fs.d.ts +20 -0
- package/fs/index.d.ts +1 -1
- package/index.d.ts +3 -2
- package/index.js +164 -240
- package/package.json +6 -2
- package/storage/adapters/redis.d.ts +9 -1
- package/storage/index.d.ts +1 -1
- package/storage/redis-url.d.ts +25 -3
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Class identity shared by every copy of a package loaded in one process.
|
|
3
|
+
*
|
|
4
|
+
* A process can hold two copies of a FrontMCP package: in an ES-module project `@frontmcp/sdk`'s ESM
|
|
5
|
+
* build loads `@frontmcp/observability` with `require()`, which resolves observability's CommonJS
|
|
6
|
+
* build, which in turn loads the CommonJS builds of the SDK and of its dependencies. Each copy has its
|
|
7
|
+
* own classes, so a plain `instanceof` in one copy does not recognise an instance made by the other:
|
|
8
|
+
* an error the client was answered with as a `PublicMcpError` was recorded as an internal error with
|
|
9
|
+
* a new id (#802).
|
|
10
|
+
*
|
|
11
|
+
* A branded class answers `instanceof` for its own instances as usual, and also for an instance of
|
|
12
|
+
* the class with the same brand from another copy. The brand is an own property of the class, so a
|
|
13
|
+
* subclass is recognised only through a brand of its own: an unbranded subclass keeps the plain
|
|
14
|
+
* check, and never matches a different subclass that happens to share a branded parent.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* export class GuardError extends Error {
|
|
19
|
+
* static override [Symbol.hasInstance](value: unknown): boolean {
|
|
20
|
+
* return isBrandedInstance(this, value);
|
|
21
|
+
* }
|
|
22
|
+
* }
|
|
23
|
+
* brandClass(GuardError, '@frontmcp/guard:GuardError');
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Give `klass` a process-wide brand. The same class in another copy of its package carries the same
|
|
28
|
+
* brand, so each recognises the other's instances through {@link isBrandedInstance}. Namespace the
|
|
29
|
+
* brand with the package name (`'@frontmcp/sdk:McpError'`).
|
|
30
|
+
*/
|
|
31
|
+
export declare function brandClass(klass: object, brand: string): void;
|
|
32
|
+
/**
|
|
33
|
+
* `value instanceof klass`, also true when `value` is an instance of the class that carries `klass`'s
|
|
34
|
+
* own brand in another copy of the package. Meant as the `static [Symbol.hasInstance]` of a branded
|
|
35
|
+
* class (subclasses inherit it, and match through their own brand or the plain check).
|
|
36
|
+
*/
|
|
37
|
+
export declare function isBrandedInstance(klass: object, value: unknown): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { brandClass, isBrandedInstance } from './class-brand';
|
package/crypto/browser.d.ts
CHANGED
|
@@ -11,6 +11,11 @@ import type { CryptoProvider } from './types';
|
|
|
11
11
|
export declare const browserCrypto: CryptoProvider;
|
|
12
12
|
/** Alias for conditional import resolution via `#crypto-provider`. */
|
|
13
13
|
export { browserCrypto as cryptoProvider };
|
|
14
|
+
export declare function rsaVerify(): boolean;
|
|
15
|
+
export declare function rsaSignBase64Url(): string;
|
|
16
|
+
export declare function rsaVerifySync(): boolean;
|
|
17
|
+
export declare function pemToPublicJwk(): JsonWebKey;
|
|
18
|
+
export declare function generateRsaKeyPair(): never;
|
|
14
19
|
export { isRsaPssAlg, jwtAlgToWebCryptoAlg } from './jwt-alg';
|
|
15
20
|
/**
|
|
16
21
|
* Verify an RSA signature using WebCrypto.
|
package/crypto/browser.js
CHANGED
|
@@ -22,16 +22,21 @@ var browser_exports = {};
|
|
|
22
22
|
__export(browser_exports, {
|
|
23
23
|
browserCrypto: () => browserCrypto,
|
|
24
24
|
cryptoProvider: () => browserCrypto,
|
|
25
|
+
generateRsaKeyPair: () => generateRsaKeyPair,
|
|
25
26
|
isRsaPssAlg: () => isRsaPssAlg,
|
|
26
27
|
jwtAlgToWebCryptoAlg: () => jwtAlgToWebCryptoAlg,
|
|
27
|
-
|
|
28
|
+
pemToPublicJwk: () => pemToPublicJwk,
|
|
29
|
+
rsaSignBase64Url: () => rsaSignBase64Url,
|
|
30
|
+
rsaVerify: () => rsaVerify,
|
|
31
|
+
rsaVerifyBrowser: () => rsaVerifyBrowser,
|
|
32
|
+
rsaVerifySync: () => rsaVerifySync
|
|
28
33
|
});
|
|
29
34
|
module.exports = __toCommonJS(browser_exports);
|
|
30
|
-
var
|
|
31
|
-
var import_hmac = require("@noble/hashes/hmac.js");
|
|
35
|
+
var import_aes = require("@noble/ciphers/aes.js");
|
|
32
36
|
var import_hkdf = require("@noble/hashes/hkdf.js");
|
|
37
|
+
var import_hmac = require("@noble/hashes/hmac.js");
|
|
38
|
+
var import_sha2 = require("@noble/hashes/sha2.js");
|
|
33
39
|
var import_utils = require("@noble/hashes/utils.js");
|
|
34
|
-
var import_aes = require("@noble/ciphers/aes.js");
|
|
35
40
|
|
|
36
41
|
// libs/utils/src/crypto/jwt-alg.ts
|
|
37
42
|
function isRsaPssAlg(jwtAlg) {
|
|
@@ -119,6 +124,24 @@ var browserCrypto = {
|
|
|
119
124
|
return constantTimeEqual(a, b);
|
|
120
125
|
}
|
|
121
126
|
};
|
|
127
|
+
function nodeOnly(name) {
|
|
128
|
+
throw new Error(`${name} is only available in Node.js runtimes`);
|
|
129
|
+
}
|
|
130
|
+
function rsaVerify() {
|
|
131
|
+
return nodeOnly("rsaVerify");
|
|
132
|
+
}
|
|
133
|
+
function rsaSignBase64Url() {
|
|
134
|
+
return nodeOnly("rsaSignBase64Url");
|
|
135
|
+
}
|
|
136
|
+
function rsaVerifySync() {
|
|
137
|
+
return nodeOnly("rsaVerifySync");
|
|
138
|
+
}
|
|
139
|
+
function pemToPublicJwk() {
|
|
140
|
+
return nodeOnly("pemToPublicJwk");
|
|
141
|
+
}
|
|
142
|
+
function generateRsaKeyPair() {
|
|
143
|
+
return nodeOnly("generateRsaKeyPair");
|
|
144
|
+
}
|
|
122
145
|
async function rsaVerifyBrowser(jwtAlg, data, publicJwk, signature) {
|
|
123
146
|
if (typeof globalThis.crypto?.subtle === "undefined") {
|
|
124
147
|
throw new Error("WebCrypto API (crypto.subtle) is not available in this environment");
|
|
@@ -154,7 +177,12 @@ function getSaltLength(jwtAlg) {
|
|
|
154
177
|
0 && (module.exports = {
|
|
155
178
|
browserCrypto,
|
|
156
179
|
cryptoProvider,
|
|
180
|
+
generateRsaKeyPair,
|
|
157
181
|
isRsaPssAlg,
|
|
158
182
|
jwtAlgToWebCryptoAlg,
|
|
159
|
-
|
|
183
|
+
pemToPublicJwk,
|
|
184
|
+
rsaSignBase64Url,
|
|
185
|
+
rsaVerify,
|
|
186
|
+
rsaVerifyBrowser,
|
|
187
|
+
rsaVerifySync
|
|
160
188
|
});
|
package/crypto/node.d.ts
CHANGED
|
@@ -48,7 +48,7 @@ export declare function generateRsaKeyPair(modulusLength?: number, alg?: string)
|
|
|
48
48
|
* For RSA-PSS (PS256/PS384/PS512), callers must pass appropriate padding/saltLength options.
|
|
49
49
|
*/
|
|
50
50
|
export declare function rsaSign(algorithm: string, data: Buffer, privateKey: crypto.KeyObject, options?: Omit<crypto.SignKeyObjectInput, 'key'>): Buffer;
|
|
51
|
-
export declare function rsaVerify(jwtAlg: string, data: Buffer, publicJwk: JsonWebKey, signature: Buffer): boolean;
|
|
51
|
+
export declare function rsaVerify(jwtAlg: string, data: Buffer | Uint8Array, publicJwk: JsonWebKey, signature: Buffer | Uint8Array): boolean;
|
|
52
52
|
/**
|
|
53
53
|
* Sign data with an RSA private JWK and return a base64url-encoded signature.
|
|
54
54
|
*
|
package/esm/crypto/browser.mjs
CHANGED
|
@@ -2,11 +2,11 @@ var __frontmcpModule = typeof process !== "undefined" && typeof process.getBuilt
|
|
|
2
2
|
const require = __frontmcpModule ? __frontmcpModule.createRequire(import.meta.url || 'file:///') : undefined;
|
|
3
3
|
// __frontmcpCreateRequire
|
|
4
4
|
// libs/utils/src/crypto/browser.ts
|
|
5
|
-
import {
|
|
6
|
-
import { hmac } from "@noble/hashes/hmac.js";
|
|
5
|
+
import { gcm } from "@noble/ciphers/aes.js";
|
|
7
6
|
import { hkdf } from "@noble/hashes/hkdf.js";
|
|
7
|
+
import { hmac } from "@noble/hashes/hmac.js";
|
|
8
|
+
import { sha256 as sha256Hash } from "@noble/hashes/sha2.js";
|
|
8
9
|
import { randomBytes as nobleRandomBytes } from "@noble/hashes/utils.js";
|
|
9
|
-
import { gcm } from "@noble/ciphers/aes.js";
|
|
10
10
|
|
|
11
11
|
// libs/utils/src/crypto/jwt-alg.ts
|
|
12
12
|
function isRsaPssAlg(jwtAlg) {
|
|
@@ -94,6 +94,24 @@ var browserCrypto = {
|
|
|
94
94
|
return constantTimeEqual(a, b);
|
|
95
95
|
}
|
|
96
96
|
};
|
|
97
|
+
function nodeOnly(name) {
|
|
98
|
+
throw new Error(`${name} is only available in Node.js runtimes`);
|
|
99
|
+
}
|
|
100
|
+
function rsaVerify() {
|
|
101
|
+
return nodeOnly("rsaVerify");
|
|
102
|
+
}
|
|
103
|
+
function rsaSignBase64Url() {
|
|
104
|
+
return nodeOnly("rsaSignBase64Url");
|
|
105
|
+
}
|
|
106
|
+
function rsaVerifySync() {
|
|
107
|
+
return nodeOnly("rsaVerifySync");
|
|
108
|
+
}
|
|
109
|
+
function pemToPublicJwk() {
|
|
110
|
+
return nodeOnly("pemToPublicJwk");
|
|
111
|
+
}
|
|
112
|
+
function generateRsaKeyPair() {
|
|
113
|
+
return nodeOnly("generateRsaKeyPair");
|
|
114
|
+
}
|
|
97
115
|
async function rsaVerifyBrowser(jwtAlg, data, publicJwk, signature) {
|
|
98
116
|
if (typeof globalThis.crypto?.subtle === "undefined") {
|
|
99
117
|
throw new Error("WebCrypto API (crypto.subtle) is not available in this environment");
|
|
@@ -128,7 +146,12 @@ function getSaltLength(jwtAlg) {
|
|
|
128
146
|
export {
|
|
129
147
|
browserCrypto,
|
|
130
148
|
browserCrypto as cryptoProvider,
|
|
149
|
+
generateRsaKeyPair,
|
|
131
150
|
isRsaPssAlg,
|
|
132
151
|
jwtAlgToWebCryptoAlg,
|
|
133
|
-
|
|
152
|
+
pemToPublicJwk,
|
|
153
|
+
rsaSignBase64Url,
|
|
154
|
+
rsaVerify,
|
|
155
|
+
rsaVerifyBrowser,
|
|
156
|
+
rsaVerifySync
|
|
134
157
|
};
|