tywrap 0.1.2 → 0.2.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 +11 -4
- package/dist/index.d.ts +20 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -2
- package/dist/index.js.map +1 -1
- package/dist/runtime/base.d.ts +17 -7
- package/dist/runtime/base.d.ts.map +1 -1
- package/dist/runtime/base.js +18 -1
- package/dist/runtime/base.js.map +1 -1
- package/dist/runtime/bounded-context.d.ts +252 -0
- package/dist/runtime/bounded-context.d.ts.map +1 -0
- package/dist/runtime/bounded-context.js +454 -0
- package/dist/runtime/bounded-context.js.map +1 -0
- package/dist/runtime/bridge-protocol.d.ts +167 -0
- package/dist/runtime/bridge-protocol.d.ts.map +1 -0
- package/dist/runtime/bridge-protocol.js +247 -0
- package/dist/runtime/bridge-protocol.js.map +1 -0
- package/dist/runtime/disposable.d.ts +40 -0
- package/dist/runtime/disposable.d.ts.map +1 -0
- package/dist/runtime/disposable.js +49 -0
- package/dist/runtime/disposable.js.map +1 -0
- package/dist/runtime/http-io.d.ts +91 -0
- package/dist/runtime/http-io.d.ts.map +1 -0
- package/dist/runtime/http-io.js +195 -0
- package/dist/runtime/http-io.js.map +1 -0
- package/dist/runtime/http.d.ts +47 -13
- package/dist/runtime/http.d.ts.map +1 -1
- package/dist/runtime/http.js +55 -74
- package/dist/runtime/http.js.map +1 -1
- package/dist/runtime/node.d.ts +142 -28
- package/dist/runtime/node.d.ts.map +1 -1
- package/dist/runtime/node.js +321 -168
- package/dist/runtime/node.js.map +1 -1
- package/dist/runtime/optimized-node.d.ts +19 -125
- package/dist/runtime/optimized-node.d.ts.map +1 -1
- package/dist/runtime/optimized-node.js +19 -550
- package/dist/runtime/optimized-node.js.map +1 -1
- package/dist/runtime/pooled-transport.d.ts +131 -0
- package/dist/runtime/pooled-transport.d.ts.map +1 -0
- package/dist/runtime/pooled-transport.js +175 -0
- package/dist/runtime/pooled-transport.js.map +1 -0
- package/dist/runtime/process-io.d.ts +204 -0
- package/dist/runtime/process-io.d.ts.map +1 -0
- package/dist/runtime/process-io.js +695 -0
- package/dist/runtime/process-io.js.map +1 -0
- package/dist/runtime/pyodide-io.d.ts +155 -0
- package/dist/runtime/pyodide-io.d.ts.map +1 -0
- package/dist/runtime/pyodide-io.js +397 -0
- package/dist/runtime/pyodide-io.js.map +1 -0
- package/dist/runtime/pyodide.d.ts +51 -19
- package/dist/runtime/pyodide.d.ts.map +1 -1
- package/dist/runtime/pyodide.js +57 -186
- package/dist/runtime/pyodide.js.map +1 -1
- package/dist/runtime/safe-codec.d.ts +81 -0
- package/dist/runtime/safe-codec.d.ts.map +1 -0
- package/dist/runtime/safe-codec.js +345 -0
- package/dist/runtime/safe-codec.js.map +1 -0
- package/dist/runtime/transport.d.ts +186 -0
- package/dist/runtime/transport.d.ts.map +1 -0
- package/dist/runtime/transport.js +86 -0
- package/dist/runtime/transport.js.map +1 -0
- package/dist/runtime/validators.d.ts +131 -0
- package/dist/runtime/validators.d.ts.map +1 -0
- package/dist/runtime/validators.js +219 -0
- package/dist/runtime/validators.js.map +1 -0
- package/dist/runtime/worker-pool.d.ts +196 -0
- package/dist/runtime/worker-pool.d.ts.map +1 -0
- package/dist/runtime/worker-pool.js +371 -0
- package/dist/runtime/worker-pool.js.map +1 -0
- package/dist/utils/codec.d.ts.map +1 -1
- package/dist/utils/codec.js +120 -1
- package/dist/utils/codec.js.map +1 -1
- package/package.json +2 -2
- package/runtime/python_bridge.py +30 -3
- package/runtime/safe_codec.py +344 -0
- package/src/index.ts +48 -5
- package/src/runtime/base.ts +18 -26
- package/src/runtime/bounded-context.ts +608 -0
- package/src/runtime/bridge-protocol.ts +319 -0
- package/src/runtime/disposable.ts +65 -0
- package/src/runtime/http-io.ts +244 -0
- package/src/runtime/http.ts +71 -117
- package/src/runtime/node.ts +460 -217
- package/src/runtime/optimized-node.ts +19 -761
- package/src/runtime/pooled-transport.ts +252 -0
- package/src/runtime/process-io.ts +902 -0
- package/src/runtime/pyodide-io.ts +485 -0
- package/src/runtime/pyodide.ts +75 -215
- package/src/runtime/safe-codec.ts +443 -0
- package/src/runtime/transport.ts +273 -0
- package/src/runtime/validators.ts +241 -0
- package/src/runtime/worker-pool.ts +498 -0
- package/src/utils/codec.ts +126 -1
|
@@ -1,27 +1,59 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pyodide runtime bridge
|
|
2
|
+
* Pyodide runtime bridge for BridgeProtocol.
|
|
3
|
+
*
|
|
4
|
+
* PyodideBridge extends BridgeProtocol and uses PyodideIO transport for
|
|
5
|
+
* in-memory Python execution in browser environments via WebAssembly.
|
|
6
|
+
*
|
|
7
|
+
* @see https://github.com/bbopen/tywrap/issues/149
|
|
8
|
+
*/
|
|
9
|
+
import { BridgeProtocol } from './bridge-protocol.js';
|
|
10
|
+
import type { CodecOptions } from './safe-codec.js';
|
|
11
|
+
/**
|
|
12
|
+
* Configuration options for PyodideBridge.
|
|
3
13
|
*/
|
|
4
|
-
import { RuntimeBridge } from './base.js';
|
|
5
14
|
export interface PyodideBridgeOptions {
|
|
6
|
-
|
|
15
|
+
/** URL for Pyodide CDN. Default: official CDN */
|
|
16
|
+
indexURL?: string;
|
|
17
|
+
/** Python packages to load during initialization */
|
|
7
18
|
packages?: string[];
|
|
19
|
+
/** Timeout in ms for operations. Default: 30000 (30 seconds) */
|
|
20
|
+
timeoutMs?: number;
|
|
21
|
+
/** Codec options for validation/serialization */
|
|
22
|
+
codec?: CodecOptions;
|
|
8
23
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Browser-based runtime bridge for executing Python code via Pyodide.
|
|
26
|
+
*
|
|
27
|
+
* PyodideBridge provides in-memory Python execution using Pyodide (Python
|
|
28
|
+
* compiled to WebAssembly). This enables running Python directly in the
|
|
29
|
+
* browser without a server.
|
|
30
|
+
*
|
|
31
|
+
* Features:
|
|
32
|
+
* - Zero network overhead (in-memory execution)
|
|
33
|
+
* - Automatic Pyodide loading from CDN or module
|
|
34
|
+
* - Python package loading support
|
|
35
|
+
* - Full SafeCodec validation (NaN/Infinity rejection, key validation)
|
|
36
|
+
* - Proper proxy cleanup to prevent memory leaks
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* const bridge = new PyodideBridge({
|
|
41
|
+
* packages: ['numpy'],
|
|
42
|
+
* });
|
|
43
|
+
* await bridge.init();
|
|
44
|
+
*
|
|
45
|
+
* const result = await bridge.call('math', 'sqrt', [16]);
|
|
46
|
+
* console.log(result); // 4.0
|
|
47
|
+
*
|
|
48
|
+
* await bridge.dispose();
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare class PyodideBridge extends BridgeProtocol {
|
|
52
|
+
/**
|
|
53
|
+
* Create a new PyodideBridge instance.
|
|
54
|
+
*
|
|
55
|
+
* @param options - Configuration options for the bridge
|
|
56
|
+
*/
|
|
14
57
|
constructor(options?: PyodideBridgeOptions);
|
|
15
|
-
private ensureReady;
|
|
16
|
-
private doInit;
|
|
17
|
-
init(): Promise<void>;
|
|
18
|
-
private resolveLoadPyodide;
|
|
19
|
-
private bootstrapHelpers;
|
|
20
|
-
call<T = unknown>(module: string, functionName: string, args: unknown[], kwargs?: Record<string, unknown>): Promise<T>;
|
|
21
|
-
instantiate<T = unknown>(module: string, className: string, args: unknown[], kwargs?: Record<string, unknown>): Promise<T>;
|
|
22
|
-
callMethod<T = unknown>(handle: string, methodName: string, args: unknown[], kwargs?: Record<string, unknown>): Promise<T>;
|
|
23
|
-
disposeInstance(handle: string): Promise<void>;
|
|
24
|
-
dispose(): Promise<void>;
|
|
25
|
-
private destroyPyProxy;
|
|
26
58
|
}
|
|
27
59
|
//# sourceMappingURL=pyodide.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pyodide.d.ts","sourceRoot":"","sources":["../../src/runtime/pyodide.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pyodide.d.ts","sourceRoot":"","sources":["../../src/runtime/pyodide.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,cAAc,EAA8B,MAAM,sBAAsB,CAAC;AAElF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAMpD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAEpB,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,iDAAiD;IACjD,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,aAAc,SAAQ,cAAc;IAC/C;;;;OAIG;gBACS,OAAO,GAAE,oBAAyB;CAgB/C"}
|
package/dist/runtime/pyodide.js
CHANGED
|
@@ -1,191 +1,62 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pyodide runtime bridge
|
|
2
|
+
* Pyodide runtime bridge for BridgeProtocol.
|
|
3
|
+
*
|
|
4
|
+
* PyodideBridge extends BridgeProtocol and uses PyodideIO transport for
|
|
5
|
+
* in-memory Python execution in browser environments via WebAssembly.
|
|
6
|
+
*
|
|
7
|
+
* @see https://github.com/bbopen/tywrap/issues/149
|
|
3
8
|
*/
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Ignore import errors - pyodide may not be installed
|
|
56
|
-
// This is expected in most environments
|
|
57
|
-
}
|
|
58
|
-
return undefined;
|
|
59
|
-
}
|
|
60
|
-
async bootstrapHelpers() {
|
|
61
|
-
if (!this.py) {
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
const helper = [
|
|
65
|
-
'import importlib',
|
|
66
|
-
'__tywrap_instances = {}',
|
|
67
|
-
'def __tywrap_call(module, function_name, args, kwargs):',
|
|
68
|
-
' mod = importlib.import_module(module)',
|
|
69
|
-
' fn = getattr(mod, function_name)',
|
|
70
|
-
' return fn(*args, **(kwargs or {}))',
|
|
71
|
-
'def __tywrap_instantiate(module, class_name, args, kwargs):',
|
|
72
|
-
' mod = importlib.import_module(module)',
|
|
73
|
-
' cls = getattr(mod, class_name)',
|
|
74
|
-
' obj = cls(*args, **(kwargs or {}))',
|
|
75
|
-
' handle = str(id(obj))',
|
|
76
|
-
' __tywrap_instances[handle] = obj',
|
|
77
|
-
' return handle',
|
|
78
|
-
'def __tywrap_call_method(handle, method_name, args, kwargs):',
|
|
79
|
-
' if handle not in __tywrap_instances:',
|
|
80
|
-
' raise KeyError(f"Unknown handle: {handle}")',
|
|
81
|
-
' obj = __tywrap_instances[handle]',
|
|
82
|
-
' fn = getattr(obj, method_name)',
|
|
83
|
-
' return fn(*args, **(kwargs or {}))',
|
|
84
|
-
'def __tywrap_dispose_instance(handle):',
|
|
85
|
-
' return __tywrap_instances.pop(handle, None) is not None',
|
|
86
|
-
].join('\n');
|
|
87
|
-
await this.py.runPythonAsync(helper);
|
|
88
|
-
}
|
|
89
|
-
async call(module, functionName, args, kwargs) {
|
|
90
|
-
await this.ensureReady();
|
|
91
|
-
const py = this.py;
|
|
92
|
-
if (!py) {
|
|
93
|
-
throw new Error('Pyodide not initialized');
|
|
94
|
-
}
|
|
95
|
-
const fn = py.globals.get('__tywrap_call');
|
|
96
|
-
if (!fn) {
|
|
97
|
-
throw new Error('Pyodide helper not initialized');
|
|
98
|
-
}
|
|
99
|
-
const invoke = fn;
|
|
100
|
-
const pyArgs = py.toPy(args ?? []);
|
|
101
|
-
const pyKwargs = py.toPy(kwargs ?? {});
|
|
102
|
-
try {
|
|
103
|
-
const out = invoke(module, functionName, pyArgs, pyKwargs);
|
|
104
|
-
return out;
|
|
105
|
-
}
|
|
106
|
-
finally {
|
|
107
|
-
this.destroyPyProxy(pyArgs);
|
|
108
|
-
this.destroyPyProxy(pyKwargs);
|
|
109
|
-
this.destroyPyProxy(fn);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
async instantiate(module, className, args, kwargs) {
|
|
113
|
-
await this.ensureReady();
|
|
114
|
-
const py = this.py;
|
|
115
|
-
if (!py) {
|
|
116
|
-
throw new Error('Pyodide not initialized');
|
|
117
|
-
}
|
|
118
|
-
const fn = py.globals.get('__tywrap_instantiate');
|
|
119
|
-
if (!fn) {
|
|
120
|
-
throw new Error('Pyodide helper not initialized');
|
|
121
|
-
}
|
|
122
|
-
const invoke = fn;
|
|
123
|
-
const pyArgs = py.toPy(args ?? []);
|
|
124
|
-
const pyKwargs = py.toPy(kwargs ?? {});
|
|
125
|
-
try {
|
|
126
|
-
const out = invoke(module, className, pyArgs, pyKwargs);
|
|
127
|
-
return out;
|
|
128
|
-
}
|
|
129
|
-
finally {
|
|
130
|
-
this.destroyPyProxy(pyArgs);
|
|
131
|
-
this.destroyPyProxy(pyKwargs);
|
|
132
|
-
this.destroyPyProxy(fn);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
async callMethod(handle, methodName, args, kwargs) {
|
|
136
|
-
await this.ensureReady();
|
|
137
|
-
const py = this.py;
|
|
138
|
-
if (!py) {
|
|
139
|
-
throw new Error('Pyodide not initialized');
|
|
140
|
-
}
|
|
141
|
-
const fn = py.globals.get('__tywrap_call_method');
|
|
142
|
-
if (!fn) {
|
|
143
|
-
throw new Error('Pyodide helper not initialized');
|
|
144
|
-
}
|
|
145
|
-
const invoke = fn;
|
|
146
|
-
const pyArgs = py.toPy(args ?? []);
|
|
147
|
-
const pyKwargs = py.toPy(kwargs ?? {});
|
|
148
|
-
try {
|
|
149
|
-
const out = invoke(handle, methodName, pyArgs, pyKwargs);
|
|
150
|
-
return out;
|
|
151
|
-
}
|
|
152
|
-
finally {
|
|
153
|
-
this.destroyPyProxy(pyArgs);
|
|
154
|
-
this.destroyPyProxy(pyKwargs);
|
|
155
|
-
this.destroyPyProxy(fn);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
async disposeInstance(handle) {
|
|
159
|
-
await this.ensureReady();
|
|
160
|
-
const py = this.py;
|
|
161
|
-
if (!py) {
|
|
162
|
-
throw new Error('Pyodide not initialized');
|
|
163
|
-
}
|
|
164
|
-
const fn = py.globals.get('__tywrap_dispose_instance');
|
|
165
|
-
if (!fn) {
|
|
166
|
-
throw new Error('Pyodide helper not initialized');
|
|
167
|
-
}
|
|
168
|
-
const invoke = fn;
|
|
169
|
-
try {
|
|
170
|
-
invoke(handle);
|
|
171
|
-
}
|
|
172
|
-
finally {
|
|
173
|
-
this.destroyPyProxy(fn);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
async dispose() {
|
|
177
|
-
// Pyodide has no explicit dispose for instance; rely on GC
|
|
178
|
-
this.py = undefined;
|
|
179
|
-
}
|
|
180
|
-
destroyPyProxy(value) {
|
|
181
|
-
if (value && typeof value.destroy === 'function') {
|
|
182
|
-
try {
|
|
183
|
-
value.destroy();
|
|
184
|
-
}
|
|
185
|
-
catch {
|
|
186
|
-
// ignore cleanup failures
|
|
187
|
-
}
|
|
188
|
-
}
|
|
9
|
+
import { BridgeProtocol } from './bridge-protocol.js';
|
|
10
|
+
import { PyodideIO } from './pyodide-io.js';
|
|
11
|
+
// =============================================================================
|
|
12
|
+
// PYODIDE BRIDGE
|
|
13
|
+
// =============================================================================
|
|
14
|
+
/**
|
|
15
|
+
* Browser-based runtime bridge for executing Python code via Pyodide.
|
|
16
|
+
*
|
|
17
|
+
* PyodideBridge provides in-memory Python execution using Pyodide (Python
|
|
18
|
+
* compiled to WebAssembly). This enables running Python directly in the
|
|
19
|
+
* browser without a server.
|
|
20
|
+
*
|
|
21
|
+
* Features:
|
|
22
|
+
* - Zero network overhead (in-memory execution)
|
|
23
|
+
* - Automatic Pyodide loading from CDN or module
|
|
24
|
+
* - Python package loading support
|
|
25
|
+
* - Full SafeCodec validation (NaN/Infinity rejection, key validation)
|
|
26
|
+
* - Proper proxy cleanup to prevent memory leaks
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* const bridge = new PyodideBridge({
|
|
31
|
+
* packages: ['numpy'],
|
|
32
|
+
* });
|
|
33
|
+
* await bridge.init();
|
|
34
|
+
*
|
|
35
|
+
* const result = await bridge.call('math', 'sqrt', [16]);
|
|
36
|
+
* console.log(result); // 4.0
|
|
37
|
+
*
|
|
38
|
+
* await bridge.dispose();
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export class PyodideBridge extends BridgeProtocol {
|
|
42
|
+
/**
|
|
43
|
+
* Create a new PyodideBridge instance.
|
|
44
|
+
*
|
|
45
|
+
* @param options - Configuration options for the bridge
|
|
46
|
+
*/
|
|
47
|
+
constructor(options = {}) {
|
|
48
|
+
// Create Pyodide transport
|
|
49
|
+
const transport = new PyodideIO({
|
|
50
|
+
indexURL: options.indexURL,
|
|
51
|
+
packages: options.packages,
|
|
52
|
+
});
|
|
53
|
+
// Initialize BridgeProtocol with transport and codec options
|
|
54
|
+
const protocolOptions = {
|
|
55
|
+
transport,
|
|
56
|
+
codec: options.codec,
|
|
57
|
+
defaultTimeoutMs: options.timeoutMs,
|
|
58
|
+
};
|
|
59
|
+
super(protocolOptions);
|
|
189
60
|
}
|
|
190
61
|
}
|
|
191
62
|
//# sourceMappingURL=pyodide.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pyodide.js","sourceRoot":"","sources":["../../src/runtime/pyodide.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pyodide.js","sourceRoot":"","sources":["../../src/runtime/pyodide.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,cAAc,EAA8B,MAAM,sBAAsB,CAAC;AAClF,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAwB5C,gFAAgF;AAChF,iBAAiB;AACjB,gFAAgF;AAEhF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,OAAO,aAAc,SAAQ,cAAc;IAC/C;;;;OAIG;IACH,YAAY,UAAgC,EAAE;QAC5C,2BAA2B;QAC3B,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC;YAC9B,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ;SAC3B,CAAC,CAAC;QAEH,6DAA6D;QAC7D,MAAM,eAAe,GAA0B;YAC7C,SAAS;YACT,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,gBAAgB,EAAE,OAAO,CAAC,SAAS;SACpC,CAAC;QAEF,KAAK,CAAC,eAAe,CAAC,CAAC;IACzB,CAAC;CACF"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SafeCodec - Unified validation and serialization for JS<->Python boundary crossing.
|
|
3
|
+
*
|
|
4
|
+
* Provides safe encoding/decoding with configurable guardrails for:
|
|
5
|
+
* - Special float rejection (NaN, Infinity)
|
|
6
|
+
* - Non-string key detection
|
|
7
|
+
* - Payload size limits
|
|
8
|
+
* - Binary data handling
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Configuration options for SafeCodec behavior.
|
|
12
|
+
*/
|
|
13
|
+
export interface CodecOptions {
|
|
14
|
+
/** Reject NaN/Infinity in arguments. Default: true */
|
|
15
|
+
rejectSpecialFloats?: boolean;
|
|
16
|
+
/** Reject non-string keys in objects. Default: true */
|
|
17
|
+
rejectNonStringKeys?: boolean;
|
|
18
|
+
/** Max payload size in bytes. Default: 10MB */
|
|
19
|
+
maxPayloadBytes?: number;
|
|
20
|
+
/** How to handle bytes/bytearray. Default: 'base64' */
|
|
21
|
+
bytesHandling?: 'base64' | 'reject' | 'passthrough';
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* SafeCodec provides unified validation and serialization for JS<->Python
|
|
25
|
+
* boundary crossing with configurable guardrails.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const codec = new SafeCodec({ rejectSpecialFloats: true });
|
|
30
|
+
*
|
|
31
|
+
* // Encoding a request
|
|
32
|
+
* const payload = codec.encodeRequest({ data: [1, 2, 3] });
|
|
33
|
+
*
|
|
34
|
+
* // Decoding a response
|
|
35
|
+
* const result = codec.decodeResponse<MyType>(responsePayload);
|
|
36
|
+
*
|
|
37
|
+
* // Async decoding with Arrow support
|
|
38
|
+
* const dataframe = await codec.decodeResponseAsync<ArrowTable>(arrowPayload);
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare class SafeCodec {
|
|
42
|
+
private readonly rejectSpecialFloats;
|
|
43
|
+
private readonly rejectNonStringKeys;
|
|
44
|
+
private readonly maxPayloadBytes;
|
|
45
|
+
private readonly bytesHandling;
|
|
46
|
+
constructor(options?: CodecOptions);
|
|
47
|
+
/**
|
|
48
|
+
* Validate and encode a request payload.
|
|
49
|
+
* Called before sending to Python.
|
|
50
|
+
*
|
|
51
|
+
* @param message - The message to encode
|
|
52
|
+
* @returns JSON string ready to send
|
|
53
|
+
* @throws BridgeProtocolError if validation fails or encoding fails
|
|
54
|
+
*/
|
|
55
|
+
encodeRequest(message: unknown): string;
|
|
56
|
+
/**
|
|
57
|
+
* Decode and validate a response payload.
|
|
58
|
+
* Called after receiving from Python.
|
|
59
|
+
*
|
|
60
|
+
* @param payload - The JSON string received from Python
|
|
61
|
+
* @returns Decoded and validated result
|
|
62
|
+
* @throws BridgeProtocolError if payload is invalid
|
|
63
|
+
* @throws BridgeExecutionError if response contains a Python error
|
|
64
|
+
*/
|
|
65
|
+
decodeResponse<T>(payload: string): T;
|
|
66
|
+
/**
|
|
67
|
+
* Async version that applies Arrow decoders.
|
|
68
|
+
* Use this when the response may contain encoded DataFrames or ndarrays.
|
|
69
|
+
*
|
|
70
|
+
* @param payload - The JSON string received from Python
|
|
71
|
+
* @returns Decoded and validated result with Arrow decoding applied
|
|
72
|
+
* @throws BridgeProtocolError if payload is invalid
|
|
73
|
+
* @throws BridgeExecutionError if response contains a Python error
|
|
74
|
+
*/
|
|
75
|
+
decodeResponseAsync<T>(payload: string): Promise<T>;
|
|
76
|
+
/**
|
|
77
|
+
* Convert Uint8Array to base64 string.
|
|
78
|
+
*/
|
|
79
|
+
private toBase64;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=safe-codec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safe-codec.d.ts","sourceRoot":"","sources":["../../src/runtime/safe-codec.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,sDAAsD;IACtD,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,uDAAuD;IACvD,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,+CAA+C;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uDAAuD;IACvD,aAAa,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,aAAa,CAAC;CACrD;AA2LD;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAU;IAC9C,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAU;IAC9C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAsC;gBAExD,OAAO,GAAE,YAAiB;IAOtC;;;;;;;OAOG;IACH,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM;IAwDvC;;;;;;;;OAQG;IACH,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC;IA4CrC;;;;;;;;OAQG;IACG,mBAAmB,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAsDzD;;OAEG;IACH,OAAO,CAAC,QAAQ;CAUjB"}
|