eth-compress 0.2.2 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -56
- package/_cjs/index.cjs +1 -2
- package/_cjs/index.cjs.map +4 -4
- package/_cjs/index.node.cjs +1 -2
- package/_cjs/index.node.cjs.map +4 -4
- package/_cjs/jit-compressor.cjs +2 -4
- package/_cjs/jit-compressor.cjs.map +4 -4
- package/_esm/index.js +1 -2
- package/_esm/index.js.map +4 -4
- package/_esm/index.node.js +1 -2
- package/_esm/index.node.js.map +4 -4
- package/_esm/jit-compressor.js +2 -4
- package/_esm/jit-compressor.js.map +4 -4
- package/_types/compiler/constants.d.ts +3 -0
- package/_types/compiler/constants.d.ts.map +1 -0
- package/_types/compiler/index.d.ts +4 -0
- package/_types/compiler/index.d.ts.map +1 -0
- package/_types/compiler/jit.d.ts +9 -0
- package/_types/compiler/jit.d.ts.map +1 -0
- package/_types/compiler/opcodes.d.ts +12 -0
- package/_types/compiler/opcodes.d.ts.map +1 -0
- package/_types/compiler/utils.d.ts +42 -0
- package/_types/compiler/utils.d.ts.map +1 -0
- package/_types/contracts.d.ts +15 -0
- package/_types/contracts.d.ts.map +1 -0
- package/_types/index.d.ts +9 -31
- package/_types/index.d.ts.map +1 -1
- package/_types/jit-compressor.d.ts +0 -1
- package/_types/jit-compressor.d.ts.map +1 -1
- package/index.ts +61 -93
- package/jit-compressor.ts +45 -507
- package/package.json +9 -9
package/index.ts
CHANGED
|
@@ -1,118 +1,86 @@
|
|
|
1
1
|
export const MIN_BODY_SIZE = 1150;
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
|
|
3
|
+
const _hasCS = typeof CompressionStream !== 'undefined';
|
|
4
|
+
const _cache = new Map<string, string | -1>();
|
|
5
|
+
const _enc = ['gzip', 'deflate'] as const;
|
|
6
|
+
type SupportedEncoding = (typeof _enc)[number];
|
|
6
7
|
|
|
7
8
|
export type PayloadTransform = (payload: unknown) => unknown;
|
|
9
|
+
export type CompressionMode = 'passive' | 'proactive' | 'gzip' | 'deflate' | PayloadTransform;
|
|
8
10
|
|
|
9
11
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
12
|
+
* @param input - URL or Request
|
|
13
|
+
* @param init - Request options
|
|
14
|
+
* @param mode - Compression mode:
|
|
15
|
+
* - 'passive' (default): discover support via Accept-Encoding header first
|
|
16
|
+
* - 'proactive': compress with gzip first, adjust if server rejects
|
|
17
|
+
* - 'gzip' | 'deflate': use specified encoding directly (known support)
|
|
18
|
+
* - PayloadTransform function: transform payload, skip HTTP compression
|
|
17
19
|
*/
|
|
18
|
-
//! @__PURE__
|
|
19
20
|
export async function compressModule(
|
|
20
21
|
input: string | URL | Request,
|
|
21
22
|
init?: RequestInit,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
//! @__PURE__
|
|
25
|
-
export async function compressModule(
|
|
26
|
-
input: string | URL | Request,
|
|
27
|
-
init: RequestInit | undefined,
|
|
28
|
-
transformPayload?: PayloadTransform,
|
|
29
|
-
): Promise<Response>;
|
|
30
|
-
|
|
31
|
-
//! @__PURE__
|
|
32
|
-
export async function compressModule(
|
|
33
|
-
input: string | URL | Request,
|
|
34
|
-
init?: RequestInit,
|
|
35
|
-
transformPayload?: PayloadTransform,
|
|
23
|
+
mode?: CompressionMode,
|
|
36
24
|
): Promise<Response> {
|
|
25
|
+
const req = input instanceof Request ? input : null;
|
|
37
26
|
const url =
|
|
38
|
-
typeof input === 'string' ? input : input instanceof
|
|
27
|
+
typeof input === 'string' ? input : input instanceof Request ? input.url : input.toString();
|
|
28
|
+
const bodyStr = typeof init?.body === 'string' ? init.body : null;
|
|
39
29
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (transformPayload && init?.body && typeof init.body === 'string') {
|
|
46
|
-
if (supported === -1 || supported === null) {
|
|
30
|
+
// Custom transform: apply and skip HTTP compression
|
|
31
|
+
if (typeof mode === 'function') {
|
|
32
|
+
if (req && !init) return fetch(req);
|
|
33
|
+
let body = init?.body;
|
|
34
|
+
if (bodyStr)
|
|
47
35
|
try {
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
...init,
|
|
53
|
-
body: JSON.stringify(next),
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
} catch {
|
|
57
|
-
// Non-JSON bodies are left untouched.
|
|
58
|
-
}
|
|
59
|
-
}
|
|
36
|
+
const next = mode(JSON.parse(bodyStr));
|
|
37
|
+
if (next !== undefined) body = JSON.stringify(next);
|
|
38
|
+
} catch {}
|
|
39
|
+
return fetch(req ?? url, { ...init, body });
|
|
60
40
|
}
|
|
61
41
|
|
|
62
|
-
const
|
|
42
|
+
const cached = _cache.get(url);
|
|
43
|
+
const known = mode === 'gzip' || mode === 'deflate';
|
|
44
|
+
const encoding = !_hasCS
|
|
45
|
+
? null
|
|
46
|
+
: known
|
|
47
|
+
? (mode as SupportedEncoding)
|
|
48
|
+
: mode === 'proactive'
|
|
49
|
+
? cached === -1
|
|
50
|
+
? null
|
|
51
|
+
: (cached ?? 'gzip')
|
|
52
|
+
: typeof cached === 'string'
|
|
53
|
+
? cached
|
|
54
|
+
: null;
|
|
63
55
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
56
|
+
const shouldCompress = !!encoding && !!bodyStr && bodyStr.length >= MIN_BODY_SIZE;
|
|
57
|
+
const opts: RequestInit = { ...init, priority: 'high' as RequestPriority };
|
|
58
|
+
const headers = new Headers(opts.headers);
|
|
59
|
+
if (shouldCompress) {
|
|
60
|
+
opts.body = await new Response(
|
|
61
|
+
new Blob([bodyStr!])
|
|
67
62
|
.stream()
|
|
68
|
-
.pipeThrough(new CompressionStream(
|
|
63
|
+
.pipeThrough(new CompressionStream(encoding as CompressionFormat)),
|
|
69
64
|
).blob();
|
|
70
|
-
|
|
71
|
-
...init,
|
|
72
|
-
body: compressed,
|
|
73
|
-
headers: { ...(init && init.headers), 'Content-Encoding': supported },
|
|
74
|
-
};
|
|
65
|
+
headers.set('Content-Encoding', encoding);
|
|
75
66
|
}
|
|
76
|
-
|
|
67
|
+
opts.headers = headers;
|
|
68
|
+
|
|
69
|
+
const response = await fetch(req ?? url, opts);
|
|
77
70
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
71
|
+
// Cache discovery for passive/proactive (not known modes)
|
|
72
|
+
if (!known && cached === undefined) {
|
|
73
|
+
const header = response.headers.get('Accept-Encoding');
|
|
74
|
+
const discovered =
|
|
75
|
+
header
|
|
76
|
+
?.split(',')
|
|
77
|
+
.map((e) => e.trim())
|
|
78
|
+
.find((e): e is SupportedEncoding => _enc.includes(e as SupportedEncoding)) ?? -1;
|
|
79
|
+
_cache.set(
|
|
80
|
+
url,
|
|
81
|
+
mode === 'proactive' && shouldCompress ? (response.ok ? encoding! : discovered) : discovered,
|
|
82
|
+
);
|
|
84
83
|
}
|
|
85
84
|
|
|
86
85
|
return response;
|
|
87
86
|
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Combines HTTP compression with EVM JIT compression.
|
|
91
|
-
* Just pass this as `fetchFn` to viem's http transport.
|
|
92
|
-
*
|
|
93
|
-
* @param input - The resource URL or Request object
|
|
94
|
-
* @param init - Optional request initialization options
|
|
95
|
-
* @returns A Promise that resolves to the Response
|
|
96
|
-
*
|
|
97
|
-
* @example
|
|
98
|
-
* ```ts
|
|
99
|
-
* const client = createPublicClient({
|
|
100
|
-
* transport: http(rpcUrl, { fetchFn: compressModuleWithJIT })
|
|
101
|
-
* })
|
|
102
|
-
* ```
|
|
103
|
-
*
|
|
104
|
-
* If the target RPC endpoint and runtime support native HTTP compression,
|
|
105
|
-
* this helper prefers that path and will not apply JIT calldata compression;
|
|
106
|
-
* the JIT-based transform is used as a legacy/fallback path when HTTP
|
|
107
|
-
* content-encoding is unavailable.
|
|
108
|
-
* @pure
|
|
109
|
-
*/
|
|
110
|
-
//! @__PURE__
|
|
111
|
-
export const compressModuleWithJIT = (
|
|
112
|
-
input: RequestInfo | URL,
|
|
113
|
-
init?: RequestInit,
|
|
114
|
-
): Promise<Response> => {
|
|
115
|
-
return import('./jit-compressor').then(({ compress_call }) =>
|
|
116
|
-
compressModule(input, init, compress_call),
|
|
117
|
-
);
|
|
118
|
-
};
|