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.
Files changed (93) hide show
  1. package/README.md +11 -4
  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 +142 -28
  31. package/dist/runtime/node.d.ts.map +1 -1
  32. package/dist/runtime/node.js +321 -168
  33. package/dist/runtime/node.js.map +1 -1
  34. package/dist/runtime/optimized-node.d.ts +19 -125
  35. package/dist/runtime/optimized-node.d.ts.map +1 -1
  36. package/dist/runtime/optimized-node.js +19 -550
  37. package/dist/runtime/optimized-node.js.map +1 -1
  38. package/dist/runtime/pooled-transport.d.ts +131 -0
  39. package/dist/runtime/pooled-transport.d.ts.map +1 -0
  40. package/dist/runtime/pooled-transport.js +175 -0
  41. package/dist/runtime/pooled-transport.js.map +1 -0
  42. package/dist/runtime/process-io.d.ts +204 -0
  43. package/dist/runtime/process-io.d.ts.map +1 -0
  44. package/dist/runtime/process-io.js +695 -0
  45. package/dist/runtime/process-io.js.map +1 -0
  46. package/dist/runtime/pyodide-io.d.ts +155 -0
  47. package/dist/runtime/pyodide-io.d.ts.map +1 -0
  48. package/dist/runtime/pyodide-io.js +397 -0
  49. package/dist/runtime/pyodide-io.js.map +1 -0
  50. package/dist/runtime/pyodide.d.ts +51 -19
  51. package/dist/runtime/pyodide.d.ts.map +1 -1
  52. package/dist/runtime/pyodide.js +57 -186
  53. package/dist/runtime/pyodide.js.map +1 -1
  54. package/dist/runtime/safe-codec.d.ts +81 -0
  55. package/dist/runtime/safe-codec.d.ts.map +1 -0
  56. package/dist/runtime/safe-codec.js +345 -0
  57. package/dist/runtime/safe-codec.js.map +1 -0
  58. package/dist/runtime/transport.d.ts +186 -0
  59. package/dist/runtime/transport.d.ts.map +1 -0
  60. package/dist/runtime/transport.js +86 -0
  61. package/dist/runtime/transport.js.map +1 -0
  62. package/dist/runtime/validators.d.ts +131 -0
  63. package/dist/runtime/validators.d.ts.map +1 -0
  64. package/dist/runtime/validators.js +219 -0
  65. package/dist/runtime/validators.js.map +1 -0
  66. package/dist/runtime/worker-pool.d.ts +196 -0
  67. package/dist/runtime/worker-pool.d.ts.map +1 -0
  68. package/dist/runtime/worker-pool.js +371 -0
  69. package/dist/runtime/worker-pool.js.map +1 -0
  70. package/dist/utils/codec.d.ts.map +1 -1
  71. package/dist/utils/codec.js +120 -1
  72. package/dist/utils/codec.js.map +1 -1
  73. package/package.json +2 -2
  74. package/runtime/python_bridge.py +30 -3
  75. package/runtime/safe_codec.py +344 -0
  76. package/src/index.ts +48 -5
  77. package/src/runtime/base.ts +18 -26
  78. package/src/runtime/bounded-context.ts +608 -0
  79. package/src/runtime/bridge-protocol.ts +319 -0
  80. package/src/runtime/disposable.ts +65 -0
  81. package/src/runtime/http-io.ts +244 -0
  82. package/src/runtime/http.ts +71 -117
  83. package/src/runtime/node.ts +460 -217
  84. package/src/runtime/optimized-node.ts +19 -761
  85. package/src/runtime/pooled-transport.ts +252 -0
  86. package/src/runtime/process-io.ts +902 -0
  87. package/src/runtime/pyodide-io.ts +485 -0
  88. package/src/runtime/pyodide.ts +75 -215
  89. package/src/runtime/safe-codec.ts +443 -0
  90. package/src/runtime/transport.ts +273 -0
  91. package/src/runtime/validators.ts +241 -0
  92. package/src/runtime/worker-pool.ts +498 -0
  93. package/src/utils/codec.ts +126 -1
@@ -1,132 +1,86 @@
1
1
  /**
2
- * HTTP runtime bridge
2
+ * HTTP runtime bridge for BridgeProtocol.
3
+ *
4
+ * HttpBridge extends BridgeProtocol and uses HttpIO transport for
5
+ * stateless HTTP POST-based communication with a Python server.
6
+ *
7
+ * @see https://github.com/bbopen/tywrap/issues/149
3
8
  */
4
9
 
5
- import { decodeValueAsync } from '../utils/codec.js';
10
+ import { BridgeProtocol, type BridgeProtocolOptions } from './bridge-protocol.js';
11
+ import { HttpIO } from './http-io.js';
12
+ import type { CodecOptions } from './safe-codec.js';
6
13
 
7
- import { RuntimeBridge } from './base.js';
14
+ // =============================================================================
15
+ // OPTIONS
16
+ // =============================================================================
8
17
 
18
+ /**
19
+ * Configuration options for HttpBridge.
20
+ */
9
21
  export interface HttpBridgeOptions {
22
+ /** Base URL for the Python server (e.g., 'http://localhost:8000') */
10
23
  baseURL: string;
11
- headers?: Record<string, string>;
12
- timeoutMs?: number;
13
- }
14
-
15
- interface HttpCallPayload {
16
- module: string;
17
- functionName: string;
18
- args: unknown[];
19
- kwargs?: Record<string, unknown>;
20
- }
21
24
 
22
- interface HttpInstantiatePayload {
23
- module: string;
24
- className: string;
25
- args: unknown[];
26
- kwargs?: Record<string, unknown>;
27
- }
25
+ /** Additional headers to include in each request */
26
+ headers?: Record<string, string>;
28
27
 
29
- interface HttpCallMethodPayload {
30
- handle: string;
31
- methodName: string;
32
- args: unknown[];
33
- kwargs?: Record<string, unknown>;
34
- }
28
+ /** Timeout in ms for requests. Default: 30000 (30 seconds) */
29
+ timeoutMs?: number;
35
30
 
36
- interface HttpDisposePayload {
37
- handle: string;
31
+ /** Codec options for validation/serialization */
32
+ codec?: CodecOptions;
38
33
  }
39
34
 
40
- export class HttpBridge extends RuntimeBridge {
41
- private readonly baseURL: string;
42
- private readonly headers: Record<string, string>;
43
- private readonly timeoutMs: number;
44
-
45
- constructor(options: HttpBridgeOptions = { baseURL: 'http://localhost:8000' }) {
46
- super();
47
- this.baseURL = options.baseURL.replace(/\/$/, '');
48
- this.headers = { 'content-type': 'application/json', ...(options.headers ?? {}) };
49
- this.timeoutMs = options.timeoutMs ?? 30000;
50
- }
51
-
52
- async call<T = unknown>(
53
- module: string,
54
- functionName: string,
55
- args: unknown[],
56
- kwargs?: Record<string, unknown>
57
- ): Promise<T> {
58
- const payload: HttpCallPayload = { module, functionName, args, kwargs };
59
- const res = await this.post(`${this.baseURL}/call`, payload);
60
- return (await decodeValueAsync(res)) as T;
61
- }
62
-
63
- async instantiate<T = unknown>(
64
- module: string,
65
- className: string,
66
- args: unknown[],
67
- kwargs?: Record<string, unknown>
68
- ): Promise<T> {
69
- const payload: HttpInstantiatePayload = { module, className, args, kwargs };
70
- const res = await this.post(`${this.baseURL}/instantiate`, payload);
71
- return (await decodeValueAsync(res)) as T;
72
- }
73
-
74
- async callMethod<T = unknown>(
75
- handle: string,
76
- methodName: string,
77
- args: unknown[],
78
- kwargs?: Record<string, unknown>
79
- ): Promise<T> {
80
- const payload: HttpCallMethodPayload = { handle, methodName, args, kwargs };
81
- const res = await this.post(`${this.baseURL}/call_method`, payload);
82
- return (await decodeValueAsync(res)) as T;
83
- }
84
-
85
- async disposeInstance(handle: string): Promise<void> {
86
- const payload: HttpDisposePayload = { handle };
87
- await this.post(`${this.baseURL}/dispose_instance`, payload);
88
- }
35
+ // =============================================================================
36
+ // HTTP BRIDGE
37
+ // =============================================================================
89
38
 
90
- async dispose(): Promise<void> {
91
- // stateless
92
- }
93
-
94
- private async post(url: string, body: unknown): Promise<unknown> {
95
- const controller = typeof AbortController !== 'undefined' ? new AbortController() : undefined;
96
- const timer = controller ? setTimeout(() => controller.abort(), this.timeoutMs) : undefined;
97
- try {
98
- const resp = await fetch(url, {
99
- method: 'POST',
100
- headers: this.headers,
101
- body: JSON.stringify(body),
102
- signal: controller?.signal,
103
- });
104
- if (!resp.ok) {
105
- const text = await safeText(resp);
106
- throw new Error(`HTTP ${resp.status}: ${text || resp.statusText}`);
107
- }
108
- const ct = resp.headers.get('content-type') ?? '';
109
- if (ct.includes('application/json')) {
110
- return (await resp.json()) as unknown;
111
- }
112
- const text = await resp.text();
113
- try {
114
- return JSON.parse(text) as unknown;
115
- } catch {
116
- return text as unknown;
117
- }
118
- } finally {
119
- if (timer) {
120
- clearTimeout(timer);
121
- }
122
- }
123
- }
124
- }
125
-
126
- async function safeText(resp: Response): Promise<string> {
127
- try {
128
- return await resp.text();
129
- } catch {
130
- return '';
39
+ /**
40
+ * HTTP-based runtime bridge for executing Python code.
41
+ *
42
+ * HttpBridge provides a stateless HTTP transport for communication with
43
+ * a Python server. Each request is independent - no connection state is
44
+ * maintained between calls.
45
+ *
46
+ * Features:
47
+ * - Stateless HTTP POST communication
48
+ * - Timeout handling via AbortController
49
+ * - Full SafeCodec validation (NaN/Infinity rejection, key validation)
50
+ * - Automatic Arrow decoding for DataFrames/ndarrays
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * const bridge = new HttpBridge({ baseURL: 'http://localhost:8000' });
55
+ * await bridge.init();
56
+ *
57
+ * const result = await bridge.call('math', 'sqrt', [16]);
58
+ * console.log(result); // 4.0
59
+ *
60
+ * await bridge.dispose();
61
+ * ```
62
+ */
63
+ export class HttpBridge extends BridgeProtocol {
64
+ /**
65
+ * Create a new HttpBridge instance.
66
+ *
67
+ * @param options - Configuration options for the bridge
68
+ */
69
+ constructor(options: HttpBridgeOptions) {
70
+ // Create HTTP transport
71
+ const transport = new HttpIO({
72
+ baseURL: options.baseURL,
73
+ headers: options.headers,
74
+ defaultTimeoutMs: options.timeoutMs,
75
+ });
76
+
77
+ // Initialize BridgeProtocol with transport and codec options
78
+ const protocolOptions: BridgeProtocolOptions = {
79
+ transport,
80
+ codec: options.codec,
81
+ defaultTimeoutMs: options.timeoutMs,
82
+ };
83
+
84
+ super(protocolOptions);
131
85
  }
132
86
  }