tywrap 0.2.0 → 0.3.0

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 (163) hide show
  1. package/README.md +65 -31
  2. package/dist/cli.js +49 -2
  3. package/dist/cli.js.map +1 -1
  4. package/dist/config/index.d.ts +11 -7
  5. package/dist/config/index.d.ts.map +1 -1
  6. package/dist/config/index.js +43 -7
  7. package/dist/config/index.js.map +1 -1
  8. package/dist/core/analyzer.d.ts +1 -0
  9. package/dist/core/analyzer.d.ts.map +1 -1
  10. package/dist/core/analyzer.js +47 -12
  11. package/dist/core/analyzer.js.map +1 -1
  12. package/dist/core/annotation-parser.d.ts +8 -0
  13. package/dist/core/annotation-parser.d.ts.map +1 -0
  14. package/dist/core/annotation-parser.js +409 -0
  15. package/dist/core/annotation-parser.js.map +1 -0
  16. package/dist/core/discovery.d.ts +1 -0
  17. package/dist/core/discovery.d.ts.map +1 -1
  18. package/dist/core/discovery.js +9 -9
  19. package/dist/core/discovery.js.map +1 -1
  20. package/dist/core/generator.d.ts +9 -1
  21. package/dist/core/generator.d.ts.map +1 -1
  22. package/dist/core/generator.js +738 -104
  23. package/dist/core/generator.js.map +1 -1
  24. package/dist/core/mapper.d.ts +9 -7
  25. package/dist/core/mapper.d.ts.map +1 -1
  26. package/dist/core/mapper.js +129 -44
  27. package/dist/core/mapper.js.map +1 -1
  28. package/dist/index.d.ts +23 -7
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +23 -3
  31. package/dist/index.js.map +1 -1
  32. package/dist/runtime/base.d.ts +17 -7
  33. package/dist/runtime/base.d.ts.map +1 -1
  34. package/dist/runtime/base.js +18 -1
  35. package/dist/runtime/base.js.map +1 -1
  36. package/dist/runtime/bounded-context.d.ts +252 -0
  37. package/dist/runtime/bounded-context.d.ts.map +1 -0
  38. package/dist/runtime/bounded-context.js +454 -0
  39. package/dist/runtime/bounded-context.js.map +1 -0
  40. package/dist/runtime/bridge-core.d.ts +1 -0
  41. package/dist/runtime/bridge-core.d.ts.map +1 -1
  42. package/dist/runtime/bridge-core.js +52 -17
  43. package/dist/runtime/bridge-core.js.map +1 -1
  44. package/dist/runtime/bridge-protocol.d.ts +184 -0
  45. package/dist/runtime/bridge-protocol.d.ts.map +1 -0
  46. package/dist/runtime/bridge-protocol.js +344 -0
  47. package/dist/runtime/bridge-protocol.js.map +1 -0
  48. package/dist/runtime/disposable.d.ts +40 -0
  49. package/dist/runtime/disposable.d.ts.map +1 -0
  50. package/dist/runtime/disposable.js +49 -0
  51. package/dist/runtime/disposable.js.map +1 -0
  52. package/dist/runtime/errors.d.ts +10 -0
  53. package/dist/runtime/errors.d.ts.map +1 -1
  54. package/dist/runtime/errors.js +9 -0
  55. package/dist/runtime/errors.js.map +1 -1
  56. package/dist/runtime/http-io.d.ts +91 -0
  57. package/dist/runtime/http-io.d.ts.map +1 -0
  58. package/dist/runtime/http-io.js +195 -0
  59. package/dist/runtime/http-io.js.map +1 -0
  60. package/dist/runtime/http.d.ts +48 -13
  61. package/dist/runtime/http.d.ts.map +1 -1
  62. package/dist/runtime/http.js +60 -73
  63. package/dist/runtime/http.js.map +1 -1
  64. package/dist/runtime/node.d.ts +97 -130
  65. package/dist/runtime/node.d.ts.map +1 -1
  66. package/dist/runtime/node.js +392 -521
  67. package/dist/runtime/node.js.map +1 -1
  68. package/dist/runtime/optimized-node.d.ts +1 -1
  69. package/dist/runtime/optimized-node.d.ts.map +1 -1
  70. package/dist/runtime/optimized-node.js +1 -1
  71. package/dist/runtime/optimized-node.js.map +1 -1
  72. package/dist/runtime/pooled-transport.d.ts +135 -0
  73. package/dist/runtime/pooled-transport.d.ts.map +1 -0
  74. package/dist/runtime/pooled-transport.js +177 -0
  75. package/dist/runtime/pooled-transport.js.map +1 -0
  76. package/dist/runtime/process-io.d.ts +209 -0
  77. package/dist/runtime/process-io.d.ts.map +1 -0
  78. package/dist/runtime/process-io.js +729 -0
  79. package/dist/runtime/process-io.js.map +1 -0
  80. package/dist/runtime/pyodide-io.d.ts +154 -0
  81. package/dist/runtime/pyodide-io.d.ts.map +1 -0
  82. package/dist/runtime/pyodide-io.js +459 -0
  83. package/dist/runtime/pyodide-io.js.map +1 -0
  84. package/dist/runtime/pyodide.d.ts +51 -19
  85. package/dist/runtime/pyodide.d.ts.map +1 -1
  86. package/dist/runtime/pyodide.js +57 -186
  87. package/dist/runtime/pyodide.js.map +1 -1
  88. package/dist/runtime/safe-codec.d.ts +103 -0
  89. package/dist/runtime/safe-codec.d.ts.map +1 -0
  90. package/dist/runtime/safe-codec.js +519 -0
  91. package/dist/runtime/safe-codec.js.map +1 -0
  92. package/dist/runtime/transport.d.ts +191 -0
  93. package/dist/runtime/transport.d.ts.map +1 -0
  94. package/dist/runtime/transport.js +86 -0
  95. package/dist/runtime/transport.js.map +1 -0
  96. package/dist/runtime/validators.d.ts +120 -0
  97. package/dist/runtime/validators.d.ts.map +1 -0
  98. package/dist/runtime/validators.js +229 -0
  99. package/dist/runtime/validators.js.map +1 -0
  100. package/dist/runtime/worker-pool.d.ts +208 -0
  101. package/dist/runtime/worker-pool.d.ts.map +1 -0
  102. package/dist/runtime/worker-pool.js +419 -0
  103. package/dist/runtime/worker-pool.js.map +1 -0
  104. package/dist/types/index.d.ts +51 -1
  105. package/dist/types/index.d.ts.map +1 -1
  106. package/dist/tywrap.d.ts.map +1 -1
  107. package/dist/tywrap.js +227 -328
  108. package/dist/tywrap.js.map +1 -1
  109. package/dist/utils/cache.d.ts.map +1 -1
  110. package/dist/utils/cache.js +53 -5
  111. package/dist/utils/cache.js.map +1 -1
  112. package/dist/utils/codec.d.ts.map +1 -1
  113. package/dist/utils/codec.js +114 -1
  114. package/dist/utils/codec.js.map +1 -1
  115. package/dist/utils/ir-cache.d.ts +28 -0
  116. package/dist/utils/ir-cache.d.ts.map +1 -0
  117. package/dist/utils/ir-cache.js +29 -0
  118. package/dist/utils/ir-cache.js.map +1 -0
  119. package/dist/utils/parallel-processor.d.ts +1 -1
  120. package/dist/utils/parallel-processor.d.ts.map +1 -1
  121. package/dist/utils/parallel-processor.js +111 -40
  122. package/dist/utils/parallel-processor.js.map +1 -1
  123. package/dist/utils/runtime.d.ts +5 -1
  124. package/dist/utils/runtime.d.ts.map +1 -1
  125. package/dist/utils/runtime.js +112 -18
  126. package/dist/utils/runtime.js.map +1 -1
  127. package/package.json +40 -18
  128. package/runtime/python_bridge.py +108 -15
  129. package/runtime/safe_codec.py +344 -0
  130. package/src/cli.ts +61 -2
  131. package/src/config/index.ts +63 -17
  132. package/src/core/analyzer.ts +52 -15
  133. package/src/core/annotation-parser.ts +500 -0
  134. package/src/core/discovery.ts +26 -12
  135. package/src/core/generator.ts +956 -116
  136. package/src/core/mapper.ts +158 -51
  137. package/src/index.ts +78 -6
  138. package/src/runtime/base.ts +18 -26
  139. package/src/runtime/bounded-context.ts +608 -0
  140. package/src/runtime/bridge-core.ts +58 -18
  141. package/src/runtime/bridge-protocol.ts +483 -0
  142. package/src/runtime/disposable.ts +65 -0
  143. package/src/runtime/errors.ts +14 -0
  144. package/src/runtime/http-io.ts +245 -0
  145. package/src/runtime/http.ts +76 -115
  146. package/src/runtime/node.ts +563 -676
  147. package/src/runtime/optimized-node.ts +4 -1
  148. package/src/runtime/pooled-transport.ts +263 -0
  149. package/src/runtime/process-io.ts +930 -0
  150. package/src/runtime/pyodide-io.ts +551 -0
  151. package/src/runtime/pyodide.ts +75 -215
  152. package/src/runtime/safe-codec.ts +651 -0
  153. package/src/runtime/transport.ts +278 -0
  154. package/src/runtime/validators.ts +252 -0
  155. package/src/runtime/worker-pool.ts +559 -0
  156. package/src/types/global.d.ts +11 -1
  157. package/src/types/index.ts +63 -0
  158. package/src/tywrap.ts +279 -358
  159. package/src/utils/cache.ts +59 -5
  160. package/src/utils/codec.ts +122 -1
  161. package/src/utils/ir-cache.ts +51 -0
  162. package/src/utils/parallel-processor.ts +119 -43
  163. package/src/utils/runtime.ts +129 -18
@@ -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,103 @@
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
+ private readonly reviveValueBound;
47
+ private static readonly base64Pattern;
48
+ constructor(options?: CodecOptions);
49
+ private assertValidBase64;
50
+ /**
51
+ * Convert base64 string to Uint8Array.
52
+ *
53
+ * Why: Python bridge represents bytes/bytearray as base64 envelopes. Decoding them here
54
+ * restores ergonomic JS types at the boundary.
55
+ */
56
+ private fromBase64;
57
+ /**
58
+ * JSON.parse reviver that decodes bytes envelopes.
59
+ *
60
+ * Supported shapes:
61
+ * - { "__tywrap_bytes__": true, "b64": "..." } (JS SafeCodec.encodeRequest; also allowed in responses)
62
+ * - { "__type__": "bytes", "encoding": "base64", "data": "..." } (Python SafeCodec default encoder)
63
+ */
64
+ private reviveValue;
65
+ private toBridgeExecutionError;
66
+ private extractResultFromResponseEnvelope;
67
+ /**
68
+ * Validate and encode a request payload.
69
+ * Called before sending to Python.
70
+ *
71
+ * @param message - The message to encode
72
+ * @returns JSON string ready to send
73
+ * @throws BridgeCodecError if validation fails or encoding fails
74
+ */
75
+ encodeRequest(message: unknown): string;
76
+ /**
77
+ * Decode and validate a response payload.
78
+ * Called after receiving from Python.
79
+ *
80
+ * @param payload - The JSON string received from Python
81
+ * @returns Decoded and validated result
82
+ * @throws BridgeCodecError if payload is invalid or decoding fails
83
+ * @throws BridgeProtocolError if protocol envelope is invalid
84
+ * @throws BridgeExecutionError if response contains a Python error
85
+ */
86
+ decodeResponse<T>(payload: string): T;
87
+ /**
88
+ * Async version that applies Arrow decoders.
89
+ * Use this when the response may contain encoded DataFrames or ndarrays.
90
+ *
91
+ * @param payload - The JSON string received from Python
92
+ * @returns Decoded and validated result with Arrow decoding applied
93
+ * @throws BridgeCodecError if payload is invalid or decoding fails
94
+ * @throws BridgeProtocolError if protocol envelope is invalid
95
+ * @throws BridgeExecutionError if response contains a Python error
96
+ */
97
+ decodeResponseAsync<T>(payload: string): Promise<T>;
98
+ /**
99
+ * Convert Uint8Array to base64 string.
100
+ */
101
+ private toBase64;
102
+ }
103
+ //# 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;AA2QD;;;;;;;;;;;;;;;;;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;IACpE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA2C;IAC5E,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CACgC;gBAEzD,OAAO,GAAE,YAAiB;IAQtC,OAAO,CAAC,iBAAiB;IASzB;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IAkBlB;;;;;;OAMG;IACH,OAAO,CAAC,WAAW;IAiCnB,OAAO,CAAC,sBAAsB;IAM9B,OAAO,CAAC,iCAAiC;IAiCzC;;;;;;;OAOG;IACH,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM;IAgEvC;;;;;;;;;OASG;IACH,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC;IA0CrC;;;;;;;;;OASG;IACG,mBAAmB,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAuDzD;;OAEG;IACH,OAAO,CAAC,QAAQ;CAajB"}