tywrap 0.2.0 → 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.
Files changed (88) hide show
  1. package/README.md +1 -1
  2. package/dist/index.d.ts +20 -4
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +22 -2
  5. package/dist/index.js.map +1 -1
  6. package/dist/runtime/base.d.ts +17 -7
  7. package/dist/runtime/base.d.ts.map +1 -1
  8. package/dist/runtime/base.js +18 -1
  9. package/dist/runtime/base.js.map +1 -1
  10. package/dist/runtime/bounded-context.d.ts +252 -0
  11. package/dist/runtime/bounded-context.d.ts.map +1 -0
  12. package/dist/runtime/bounded-context.js +454 -0
  13. package/dist/runtime/bounded-context.js.map +1 -0
  14. package/dist/runtime/bridge-protocol.d.ts +167 -0
  15. package/dist/runtime/bridge-protocol.d.ts.map +1 -0
  16. package/dist/runtime/bridge-protocol.js +247 -0
  17. package/dist/runtime/bridge-protocol.js.map +1 -0
  18. package/dist/runtime/disposable.d.ts +40 -0
  19. package/dist/runtime/disposable.d.ts.map +1 -0
  20. package/dist/runtime/disposable.js +49 -0
  21. package/dist/runtime/disposable.js.map +1 -0
  22. package/dist/runtime/http-io.d.ts +91 -0
  23. package/dist/runtime/http-io.d.ts.map +1 -0
  24. package/dist/runtime/http-io.js +195 -0
  25. package/dist/runtime/http-io.js.map +1 -0
  26. package/dist/runtime/http.d.ts +47 -13
  27. package/dist/runtime/http.d.ts.map +1 -1
  28. package/dist/runtime/http.js +55 -74
  29. package/dist/runtime/http.js.map +1 -1
  30. package/dist/runtime/node.d.ts +97 -130
  31. package/dist/runtime/node.d.ts.map +1 -1
  32. package/dist/runtime/node.js +256 -523
  33. package/dist/runtime/node.js.map +1 -1
  34. package/dist/runtime/pooled-transport.d.ts +131 -0
  35. package/dist/runtime/pooled-transport.d.ts.map +1 -0
  36. package/dist/runtime/pooled-transport.js +175 -0
  37. package/dist/runtime/pooled-transport.js.map +1 -0
  38. package/dist/runtime/process-io.d.ts +204 -0
  39. package/dist/runtime/process-io.d.ts.map +1 -0
  40. package/dist/runtime/process-io.js +695 -0
  41. package/dist/runtime/process-io.js.map +1 -0
  42. package/dist/runtime/pyodide-io.d.ts +155 -0
  43. package/dist/runtime/pyodide-io.d.ts.map +1 -0
  44. package/dist/runtime/pyodide-io.js +397 -0
  45. package/dist/runtime/pyodide-io.js.map +1 -0
  46. package/dist/runtime/pyodide.d.ts +51 -19
  47. package/dist/runtime/pyodide.d.ts.map +1 -1
  48. package/dist/runtime/pyodide.js +57 -186
  49. package/dist/runtime/pyodide.js.map +1 -1
  50. package/dist/runtime/safe-codec.d.ts +81 -0
  51. package/dist/runtime/safe-codec.d.ts.map +1 -0
  52. package/dist/runtime/safe-codec.js +345 -0
  53. package/dist/runtime/safe-codec.js.map +1 -0
  54. package/dist/runtime/transport.d.ts +186 -0
  55. package/dist/runtime/transport.d.ts.map +1 -0
  56. package/dist/runtime/transport.js +86 -0
  57. package/dist/runtime/transport.js.map +1 -0
  58. package/dist/runtime/validators.d.ts +131 -0
  59. package/dist/runtime/validators.d.ts.map +1 -0
  60. package/dist/runtime/validators.js +219 -0
  61. package/dist/runtime/validators.js.map +1 -0
  62. package/dist/runtime/worker-pool.d.ts +196 -0
  63. package/dist/runtime/worker-pool.d.ts.map +1 -0
  64. package/dist/runtime/worker-pool.js +371 -0
  65. package/dist/runtime/worker-pool.js.map +1 -0
  66. package/dist/utils/codec.d.ts.map +1 -1
  67. package/dist/utils/codec.js +120 -1
  68. package/dist/utils/codec.js.map +1 -1
  69. package/package.json +2 -2
  70. package/runtime/python_bridge.py +30 -3
  71. package/runtime/safe_codec.py +344 -0
  72. package/src/index.ts +48 -5
  73. package/src/runtime/base.ts +18 -26
  74. package/src/runtime/bounded-context.ts +608 -0
  75. package/src/runtime/bridge-protocol.ts +319 -0
  76. package/src/runtime/disposable.ts +65 -0
  77. package/src/runtime/http-io.ts +244 -0
  78. package/src/runtime/http.ts +71 -117
  79. package/src/runtime/node.ts +358 -691
  80. package/src/runtime/pooled-transport.ts +252 -0
  81. package/src/runtime/process-io.ts +902 -0
  82. package/src/runtime/pyodide-io.ts +485 -0
  83. package/src/runtime/pyodide.ts +75 -215
  84. package/src/runtime/safe-codec.ts +443 -0
  85. package/src/runtime/transport.ts +273 -0
  86. package/src/runtime/validators.ts +241 -0
  87. package/src/runtime/worker-pool.ts +498 -0
  88. package/src/utils/codec.ts +126 -1
@@ -1,27 +1,59 @@
1
1
  /**
2
- * Pyodide runtime bridge (browser)
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
- indexURL: string;
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
- export declare class PyodideBridge extends RuntimeBridge {
10
- private readonly indexURL;
11
- private readonly packages;
12
- private py?;
13
- private initPromise?;
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;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAYD,qBAAa,aAAc,SAAQ,aAAa;IAC9C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;IAC7C,OAAO,CAAC,EAAE,CAAC,CAAkB;IAC7B,OAAO,CAAC,WAAW,CAAC,CAAgB;gBAExB,OAAO,GAAE,oBAAwE;YAM/E,WAAW;YAaX,MAAM;IAYd,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAIb,kBAAkB;YAmBlB,gBAAgB;IA8BxB,IAAI,CAAC,CAAC,GAAG,OAAO,EACpB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,OAAO,EAAE,EACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC;IAuBP,WAAW,CAAC,CAAC,GAAG,OAAO,EAC3B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,OAAO,EAAE,EACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC;IAuBP,UAAU,CAAC,CAAC,GAAG,OAAO,EAC1B,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,OAAO,EAAE,EACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC;IAuBP,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB9C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAK9B,OAAO,CAAC,cAAc;CASvB"}
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"}
@@ -1,191 +1,62 @@
1
1
  /**
2
- * Pyodide runtime bridge (browser)
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 { RuntimeBridge } from './base.js';
5
- export class PyodideBridge extends RuntimeBridge {
6
- indexURL;
7
- packages;
8
- py;
9
- initPromise;
10
- constructor(options = { indexURL: 'https://cdn.jsdelivr.net/pyodide/' }) {
11
- super();
12
- this.indexURL = options.indexURL;
13
- this.packages = [...(options.packages ?? [])];
14
- }
15
- async ensureReady() {
16
- if (this.py) {
17
- return;
18
- }
19
- // If already initializing, wait for that promise
20
- if (this.initPromise) {
21
- return this.initPromise;
22
- }
23
- // Start initialization and store the promise to prevent concurrent initialization
24
- this.initPromise = this.doInit();
25
- return this.initPromise;
26
- }
27
- async doInit() {
28
- const loadPyodideFn = await this.resolveLoadPyodide();
29
- if (!loadPyodideFn) {
30
- throw new Error('Pyodide is not available in this environment');
31
- }
32
- this.py = await loadPyodideFn({ indexURL: this.indexURL });
33
- if (this.packages.length > 0) {
34
- await this.py.loadPackage([...this.packages]);
35
- }
36
- await this.bootstrapHelpers();
37
- }
38
- async init() {
39
- await this.ensureReady();
40
- }
41
- async resolveLoadPyodide() {
42
- // Prefer global loadPyodide when present (browser script tag include)
43
- const g = globalThis ?? {};
44
- if (typeof g.loadPyodide === 'function') {
45
- return g.loadPyodide;
46
- }
47
- try {
48
- // Attempt dynamic import if available
49
- const mod = (await import('pyodide'));
50
- if (typeof mod.loadPyodide === 'function') {
51
- return mod.loadPyodide;
52
- }
53
- }
54
- catch {
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":"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"}
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"}