tywrap 0.3.0 → 0.5.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 (101) hide show
  1. package/README.md +40 -5
  2. package/dist/cli.js +24 -6
  3. package/dist/cli.js.map +1 -1
  4. package/dist/config/index.d.ts.map +1 -1
  5. package/dist/config/index.js +19 -13
  6. package/dist/config/index.js.map +1 -1
  7. package/dist/core/analyzer.d.ts.map +1 -1
  8. package/dist/core/analyzer.js +0 -1
  9. package/dist/core/analyzer.js.map +1 -1
  10. package/dist/dev.d.ts +57 -0
  11. package/dist/dev.d.ts.map +1 -0
  12. package/dist/dev.js +743 -0
  13. package/dist/dev.js.map +1 -0
  14. package/dist/index.d.ts +5 -4
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +6 -6
  17. package/dist/index.js.map +1 -1
  18. package/dist/runtime/base.d.ts +7 -7
  19. package/dist/runtime/base.js +8 -8
  20. package/dist/runtime/bounded-context.d.ts +15 -31
  21. package/dist/runtime/bounded-context.d.ts.map +1 -1
  22. package/dist/runtime/bounded-context.js +16 -15
  23. package/dist/runtime/bounded-context.js.map +1 -1
  24. package/dist/runtime/http.d.ts +24 -5
  25. package/dist/runtime/http.d.ts.map +1 -1
  26. package/dist/runtime/http.js +57 -12
  27. package/dist/runtime/http.js.map +1 -1
  28. package/dist/runtime/node.d.ts +33 -7
  29. package/dist/runtime/node.d.ts.map +1 -1
  30. package/dist/runtime/node.js +144 -120
  31. package/dist/runtime/node.js.map +1 -1
  32. package/dist/runtime/optimized-node.d.ts +5 -4
  33. package/dist/runtime/optimized-node.d.ts.map +1 -1
  34. package/dist/runtime/optimized-node.js +5 -4
  35. package/dist/runtime/optimized-node.js.map +1 -1
  36. package/dist/runtime/pooled-transport.d.ts +2 -18
  37. package/dist/runtime/pooled-transport.d.ts.map +1 -1
  38. package/dist/runtime/pooled-transport.js +2 -29
  39. package/dist/runtime/pooled-transport.js.map +1 -1
  40. package/dist/runtime/process-io.d.ts +2 -18
  41. package/dist/runtime/process-io.d.ts.map +1 -1
  42. package/dist/runtime/process-io.js +3 -30
  43. package/dist/runtime/process-io.js.map +1 -1
  44. package/dist/runtime/pyodide-bootstrap-core.generated.d.ts +12 -0
  45. package/dist/runtime/pyodide-bootstrap-core.generated.d.ts.map +1 -0
  46. package/dist/runtime/pyodide-bootstrap-core.generated.js +12 -0
  47. package/dist/runtime/pyodide-bootstrap-core.generated.js.map +1 -0
  48. package/dist/runtime/pyodide-io.d.ts +7 -37
  49. package/dist/runtime/pyodide-io.d.ts.map +1 -1
  50. package/dist/runtime/pyodide-io.js +90 -214
  51. package/dist/runtime/pyodide-io.js.map +1 -1
  52. package/dist/runtime/pyodide.d.ts +25 -5
  53. package/dist/runtime/pyodide.d.ts.map +1 -1
  54. package/dist/runtime/pyodide.js +59 -10
  55. package/dist/runtime/pyodide.js.map +1 -1
  56. package/dist/runtime/{bridge-protocol.d.ts → rpc-client.d.ts} +59 -46
  57. package/dist/runtime/rpc-client.d.ts.map +1 -0
  58. package/dist/runtime/{bridge-protocol.js → rpc-client.js} +60 -42
  59. package/dist/runtime/rpc-client.js.map +1 -0
  60. package/dist/runtime/worker-pool.d.ts +8 -20
  61. package/dist/runtime/worker-pool.d.ts.map +1 -1
  62. package/dist/runtime/worker-pool.js +58 -59
  63. package/dist/runtime/worker-pool.js.map +1 -1
  64. package/dist/types/index.d.ts +8 -10
  65. package/dist/types/index.d.ts.map +1 -1
  66. package/dist/tywrap.d.ts +6 -0
  67. package/dist/tywrap.d.ts.map +1 -1
  68. package/dist/tywrap.js +10 -3
  69. package/dist/tywrap.js.map +1 -1
  70. package/package.json +22 -18
  71. package/runtime/__pycache__/safe_codec.cpython-311.pyc +0 -0
  72. package/runtime/__pycache__/tywrap_bridge_core.cpython-311.pyc +0 -0
  73. package/runtime/python_bridge.py +85 -702
  74. package/runtime/safe_codec.py +10 -2
  75. package/runtime/tywrap_bridge_core.py +875 -0
  76. package/src/cli.ts +27 -6
  77. package/src/config/index.ts +28 -15
  78. package/src/core/analyzer.ts +1 -2
  79. package/src/dev.ts +983 -0
  80. package/src/index.ts +7 -7
  81. package/src/runtime/base.ts +8 -8
  82. package/src/runtime/bounded-context.ts +17 -56
  83. package/src/runtime/http.ts +85 -13
  84. package/src/runtime/node.ts +172 -178
  85. package/src/runtime/optimized-node.ts +5 -4
  86. package/src/runtime/pooled-transport.ts +2 -57
  87. package/src/runtime/process-io.ts +3 -55
  88. package/src/runtime/pyodide-bootstrap-core.generated.ts +12 -0
  89. package/src/runtime/pyodide-io.ts +92 -243
  90. package/src/runtime/pyodide.ts +87 -10
  91. package/src/runtime/{bridge-protocol.ts → rpc-client.ts} +76 -49
  92. package/src/runtime/worker-pool.ts +67 -88
  93. package/src/types/index.ts +20 -12
  94. package/src/tywrap.ts +17 -3
  95. package/dist/runtime/bridge-core.d.ts +0 -65
  96. package/dist/runtime/bridge-core.d.ts.map +0 -1
  97. package/dist/runtime/bridge-core.js +0 -379
  98. package/dist/runtime/bridge-core.js.map +0 -1
  99. package/dist/runtime/bridge-protocol.d.ts.map +0 -1
  100. package/dist/runtime/bridge-protocol.js.map +0 -1
  101. package/src/runtime/bridge-core.ts +0 -494
package/src/cli.ts CHANGED
@@ -287,7 +287,9 @@ async function main(): Promise<void> {
287
287
  }
288
288
 
289
289
  const res = await generate(options, { check: argv.check });
290
+ const failures = res.failures ?? [];
290
291
  const warnings = res.warnings ?? [];
292
+ const hasFailures = failures.length > 0;
291
293
  const moduleCount = Object.keys(options.pythonModules ?? {}).length;
292
294
 
293
295
  const emitWarnings = (): void => {
@@ -301,24 +303,43 @@ async function main(): Promise<void> {
301
303
  process.stderr.write('\n');
302
304
  };
303
305
 
306
+ const emitFailures = (): void => {
307
+ if (failures.length === 0) {
308
+ return;
309
+ }
310
+ process.stderr.write(`Failures (count ${failures.length}):\n`);
311
+ for (const failure of failures) {
312
+ process.stderr.write(`- ${failure.message}\n`);
313
+ }
314
+ process.stderr.write('\n');
315
+ };
316
+
317
+ emitWarnings();
318
+
304
319
  if (argv.check) {
320
+ if (hasFailures) {
321
+ emitFailures();
322
+ process.exit(1);
323
+ }
324
+
305
325
  const outOfDate = res.outOfDate ?? [];
306
326
  if (outOfDate.length === 0) {
307
- emitWarnings();
308
327
  process.stdout.write('Generated wrappers are up to date.\n');
309
328
  } else {
310
- emitWarnings();
311
329
  process.stderr.write('Generated wrappers are out of date:\n');
312
330
  for (const file of outOfDate) {
313
331
  process.stderr.write(`- ${file}\n`);
314
332
  }
315
333
  process.stderr.write('\nRun `tywrap generate` to update.\n');
316
- if (!(argv.failOnWarn && res.warnings.length > 0)) {
334
+ if (!(argv.failOnWarn && warnings.length > 0)) {
317
335
  process.exit(3);
318
336
  }
319
337
  }
320
338
  } else {
321
- emitWarnings();
339
+ if (hasFailures) {
340
+ emitFailures();
341
+ process.exit(1);
342
+ }
322
343
 
323
344
  const written = res.written ?? [];
324
345
  if (written.length === 0) {
@@ -355,9 +376,9 @@ async function main(): Promise<void> {
355
376
  process.stdout.write(`- ${file}\n`);
356
377
  }
357
378
  }
358
- if (argv.failOnWarn && res.warnings.length > 0) {
379
+ if (argv.failOnWarn && warnings.length > 0) {
359
380
  log.error(
360
- `Warnings encountered (count ${res.warnings.length}). Failing due to --fail-on-warn.`
381
+ `Warnings encountered (count ${warnings.length}). Failing due to --fail-on-warn.`
361
382
  );
362
383
  process.exit(2);
363
384
  }
@@ -17,7 +17,6 @@ import type {
17
17
  OutputConfig,
18
18
  RuntimeConfig,
19
19
  PerformanceConfig,
20
- DevelopmentConfig,
21
20
  } from '../types/index.js';
22
21
  import { getDefaultPythonPath } from '../utils/python.js';
23
22
 
@@ -48,11 +47,16 @@ const DEFAULT_CONFIG: ResolvedTywrapConfig = {
48
47
  output: { dir: './generated', format: 'esm', declaration: false, sourceMap: false },
49
48
  runtime: { node: { pythonPath: getDefaultPythonPath(), timeout: 30000 } },
50
49
  performance: { caching: false, batching: false, compression: 'none' },
51
- development: { hotReload: false, sourceMap: false, validation: 'none' },
52
50
  types: { presets: [] },
53
51
  debug: false,
54
52
  };
55
53
 
54
+ const LEGACY_DEVELOPMENT_MESSAGE =
55
+ 'Legacy config field "development" is no longer supported. Use createBridgeReloader() or startNodeWatchSession() from "tywrap/dev" instead.';
56
+
57
+ const LEGACY_MODULE_WATCH_MESSAGE =
58
+ 'Legacy config field "pythonModules.<module>.watch" is no longer supported. Use startNodeWatchSession() from "tywrap/dev" instead.';
59
+
56
60
  /**
57
61
  * Recursively merge two configuration objects. Arrays are overwritten by
58
62
  * overrides instead of concatenated.
@@ -89,17 +93,38 @@ function safeExists(path: string): boolean {
89
93
  return existsSync(path);
90
94
  }
91
95
 
96
+ function detectLegacyFields(config: TywrapConfig): void {
97
+ const rawConfig = config as unknown as Record<string, unknown>;
98
+ if (Object.prototype.hasOwnProperty.call(rawConfig, 'development')) {
99
+ throw new Error(LEGACY_DEVELOPMENT_MESSAGE);
100
+ }
101
+
102
+ const pythonModules = rawConfig.pythonModules;
103
+ if (!isPlainObject(pythonModules)) {
104
+ return;
105
+ }
106
+
107
+ for (const moduleConfig of Object.values(pythonModules)) {
108
+ if (
109
+ isPlainObject(moduleConfig) &&
110
+ Object.prototype.hasOwnProperty.call(moduleConfig, 'watch')
111
+ ) {
112
+ throw new Error(LEGACY_MODULE_WATCH_MESSAGE);
113
+ }
114
+ }
115
+ }
116
+
92
117
  /**
93
118
  * Validate configuration values and throw user-friendly errors when invalid.
94
119
  */
95
120
  function validateConfig(config: ResolvedTywrapConfig): void {
121
+ detectLegacyFields(config);
96
122
  const allowedTopLevel = new Set([
97
123
  'pythonModules',
98
124
  'pythonImportPath',
99
125
  'output',
100
126
  'runtime',
101
127
  'performance',
102
- 'development',
103
128
  'types',
104
129
  'debug',
105
130
  ]);
@@ -153,18 +178,6 @@ function validateConfig(config: ResolvedTywrapConfig): void {
153
178
  throw new Error(`performance.compression must be one of ${validCompression.join(', ')}`);
154
179
  }
155
180
 
156
- const dev: DevelopmentConfig = config.development;
157
- if (typeof dev.hotReload !== 'boolean') {
158
- throw new Error('development.hotReload must be a boolean');
159
- }
160
- if (typeof dev.sourceMap !== 'boolean') {
161
- throw new Error('development.sourceMap must be a boolean');
162
- }
163
- const validValidation = ['runtime', 'compile', 'both', 'none'];
164
- if (!validValidation.includes(dev.validation)) {
165
- throw new Error(`development.validation must be one of ${validValidation.join(', ')}`);
166
- }
167
-
168
181
  if (config.types) {
169
182
  const presets = config.types.presets;
170
183
  const validPresets = new Set([
@@ -26,8 +26,7 @@ import { getComponentLogger } from '../utils/logger.js';
26
26
  const log = getComponentLogger('Analyzer');
27
27
 
28
28
  const UNKNOWN_TYPE: PythonType = { kind: 'custom', name: 'Any', module: 'typing' };
29
- // tree-sitter-python >=0.25 updates its typings, but Parser#setLanguage still expects the package export at runtime.
30
- const PYTHON_LANGUAGE = Python as unknown as Parser.Language;
29
+ const PYTHON_LANGUAGE = Python as unknown as Parameters<Parser['setLanguage']>[0];
31
30
 
32
31
  export class PyAnalyzer {
33
32
  private parser: Parser;