@webmcp-auto-ui/sdk 2.5.26 → 2.5.27
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/package.json +1 -1
- package/src/hyperskills.ts +51 -3
package/package.json
CHANGED
package/src/hyperskills.ts
CHANGED
|
@@ -2,16 +2,64 @@
|
|
|
2
2
|
* Typed wrapper around the pure-JS `hyperskills` package.
|
|
3
3
|
* This avoids "no declaration file" errors in strict TS
|
|
4
4
|
* without requiring hyperskills to ship its own types.
|
|
5
|
+
*
|
|
6
|
+
* `encode` is overridden locally with a chunked base64url implementation
|
|
7
|
+
* to avoid O(n²) string concat on mobile for large payloads, and to
|
|
8
|
+
* surface a clear error when CompressionStream is unavailable
|
|
9
|
+
* (e.g. iOS Safari < 16.4).
|
|
5
10
|
*/
|
|
6
11
|
|
|
7
12
|
// @ts-ignore — hyperskills is intentionally pure JS
|
|
8
13
|
import * as hs from 'hyperskills';
|
|
9
14
|
|
|
10
|
-
|
|
15
|
+
// Chunked base64url — avoids char-by-char concat (quadratic on iOS Safari)
|
|
16
|
+
function toBase64urlChunked(bytes: Uint8Array): string {
|
|
17
|
+
const CHUNK = 0x8000;
|
|
18
|
+
let binary = '';
|
|
19
|
+
for (let i = 0; i < bytes.length; i += CHUNK) {
|
|
20
|
+
binary += String.fromCharCode.apply(
|
|
21
|
+
null,
|
|
22
|
+
Array.from(bytes.subarray(i, i + CHUNK)) as number[],
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
return btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function compressGzip(bytes: Uint8Array): Promise<Uint8Array> {
|
|
29
|
+
if (!('CompressionStream' in globalThis)) {
|
|
30
|
+
throw new Error('CompressionStream indisponible (iOS 16.4+ requis)');
|
|
31
|
+
}
|
|
32
|
+
// @ts-ignore — CompressionStream is part of the DOM lib but may be missing in older TS targets
|
|
33
|
+
const cs = new CompressionStream('gzip');
|
|
34
|
+
const writer = cs.writable.getWriter();
|
|
35
|
+
writer.write(bytes);
|
|
36
|
+
writer.close();
|
|
37
|
+
return new Uint8Array(await new Response(cs.readable).arrayBuffer());
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function encode(
|
|
11
41
|
sourceUrl: string,
|
|
12
42
|
content: string,
|
|
13
|
-
options
|
|
14
|
-
)
|
|
43
|
+
options: { compress?: 'gz' | 'br' | 'none' } = {},
|
|
44
|
+
): Promise<string> {
|
|
45
|
+
const compress = options.compress ?? 'gz';
|
|
46
|
+
const bytes = new TextEncoder().encode(content);
|
|
47
|
+
let param: string;
|
|
48
|
+
|
|
49
|
+
if (compress === 'gz') {
|
|
50
|
+
const compressed = await compressGzip(bytes);
|
|
51
|
+
param = 'gz.' + toBase64urlChunked(compressed);
|
|
52
|
+
} else if (compress === 'br') {
|
|
53
|
+
// Delegate to the upstream JS implementation (Node-only path).
|
|
54
|
+
return hs.encode(sourceUrl, content, options);
|
|
55
|
+
} else {
|
|
56
|
+
param = toBase64urlChunked(bytes);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const url = new URL(sourceUrl);
|
|
60
|
+
url.searchParams.set('hs', param);
|
|
61
|
+
return url.toString();
|
|
62
|
+
}
|
|
15
63
|
|
|
16
64
|
export const decode: (
|
|
17
65
|
urlOrParam: string,
|