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
@@ -432,7 +432,8 @@ export const processUtils = {
432
432
  */
433
433
  async exec(
434
434
  command: string,
435
- args: string[] = []
435
+ args: string[] = [],
436
+ options: { timeoutMs?: number; env?: Record<string, string | undefined>; cwd?: string } = {}
436
437
  ): Promise<{ stdout: string; stderr: string; code: number }> {
437
438
  const runtime = detectRuntime();
438
439
 
@@ -441,28 +442,88 @@ export const processUtils = {
441
442
  }
442
443
 
443
444
  if (runtime.name === 'deno' && Deno) {
444
- const cmd = new Deno.Command(command, { args });
445
- const { code, stdout, stderr } = await cmd.output();
445
+ const timeoutMs = options.timeoutMs;
446
+ const controller =
447
+ typeof timeoutMs === 'number' && timeoutMs > 0 ? new AbortController() : undefined;
448
+ const timeout =
449
+ controller && typeof timeoutMs === 'number'
450
+ ? setTimeout(() => controller.abort(), timeoutMs)
451
+ : undefined;
452
+ const env: Record<string, string> | undefined =
453
+ options.env && Object.keys(options.env).length > 0
454
+ ? Object.fromEntries(
455
+ Object.entries(options.env)
456
+ .filter(([, value]) => typeof value === 'string')
457
+ .map(([key, value]) => [key, value as string])
458
+ )
459
+ : undefined;
446
460
 
447
- return {
448
- code,
449
- stdout: new TextDecoder().decode(stdout),
450
- stderr: new TextDecoder().decode(stderr),
451
- };
461
+ try {
462
+ const cmd = new Deno.Command(command, {
463
+ args,
464
+ ...(options.cwd ? { cwd: options.cwd } : {}),
465
+ ...(env ? { env } : {}),
466
+ ...(controller ? { signal: controller.signal } : {}),
467
+ });
468
+ const { code, stdout, stderr } = await cmd.output();
469
+
470
+ return {
471
+ code,
472
+ stdout: new TextDecoder().decode(stdout),
473
+ stderr: new TextDecoder().decode(stderr),
474
+ };
475
+ } catch (error: unknown) {
476
+ if (controller?.signal.aborted && typeof timeoutMs === 'number') {
477
+ throw new Error(`Command "${command}" timed out after ${timeoutMs}ms`);
478
+ }
479
+ throw error;
480
+ } finally {
481
+ if (timeout) {
482
+ clearTimeout(timeout);
483
+ }
484
+ }
452
485
  }
453
486
 
454
487
  if (runtime.name === 'bun' && Bun) {
488
+ const timeoutMs = options.timeoutMs;
489
+ const mergedEnv: Record<string, string> | undefined = options.env
490
+ ? Object.fromEntries(
491
+ Object.entries({
492
+ ...(typeof process !== 'undefined' ? process.env : {}),
493
+ ...options.env,
494
+ })
495
+ .filter(([, value]) => typeof value === 'string')
496
+ .map(([key, value]) => [key, value as string])
497
+ )
498
+ : undefined;
455
499
  const proc = Bun.spawn([command, ...args], {
456
500
  stdout: 'pipe',
457
501
  stderr: 'pipe',
502
+ ...(options.cwd ? { cwd: options.cwd } : {}),
503
+ ...(mergedEnv ? { env: mergedEnv } : {}),
458
504
  });
459
505
 
506
+ let timedOut = false;
507
+ const timeout =
508
+ typeof timeoutMs === 'number' && timeoutMs > 0
509
+ ? setTimeout(() => {
510
+ timedOut = true;
511
+ proc.kill?.('SIGKILL');
512
+ }, timeoutMs)
513
+ : undefined;
514
+
460
515
  const [stdout, stderr] = await Promise.all([
461
516
  new Response(proc.stdout).text(),
462
517
  new Response(proc.stderr).text(),
463
518
  ]);
464
519
 
465
520
  await proc.exited;
521
+ if (timeout) {
522
+ clearTimeout(timeout);
523
+ }
524
+ if (timedOut && typeof timeoutMs === 'number') {
525
+ throw new Error(`Command "${command}" timed out after ${timeoutMs}ms`);
526
+ }
466
527
 
467
528
  return {
468
529
  code: proc.exitCode ?? 0,
@@ -476,15 +537,51 @@ export const processUtils = {
476
537
  const { delimiter } = await import('node:path');
477
538
 
478
539
  return new Promise((resolve, reject) => {
479
- const extraPyPath = pathUtils.join(process.cwd(), 'tywrap_ir');
480
- const existingPyPath = process.env.PYTHONPATH;
481
- const env = {
482
- ...process.env,
483
- PYTHONPATH: existingPyPath ? `${extraPyPath}${delimiter}${existingPyPath}` : extraPyPath,
484
- };
485
- const child = spawn(command, args, { env });
540
+ const cwd = options.cwd ?? process.cwd();
541
+ const extraPyPath = pathUtils.join(cwd, 'tywrap_ir');
542
+ const env: Record<string, string> = Object.create(null) as Record<string, string>;
543
+ Object.entries(process.env).forEach(([key, value]) => {
544
+ if (value !== undefined) {
545
+ // eslint-disable-next-line security/detect-object-injection -- environment variable keys are user/runtime supplied
546
+ env[key] = value;
547
+ }
548
+ });
549
+ Object.entries(options.env ?? {}).forEach(([key, value]) => {
550
+ if (value === undefined) {
551
+ // eslint-disable-next-line security/detect-object-injection -- environment variable keys are user/runtime supplied
552
+ delete env[key];
553
+ return;
554
+ }
555
+ // eslint-disable-next-line security/detect-object-injection -- environment variable keys are user/runtime supplied
556
+ env[key] = value;
557
+ });
558
+ const existingPyPath = env.PYTHONPATH;
559
+ env.PYTHONPATH = existingPyPath
560
+ ? `${extraPyPath}${delimiter}${existingPyPath}`
561
+ : extraPyPath;
562
+ const child = spawn(command, args, { env, cwd: options.cwd });
486
563
  let stdout = '';
487
564
  let stderr = '';
565
+ let settled = false;
566
+ let timedOut = false;
567
+ const timeout =
568
+ typeof options.timeoutMs === 'number' && options.timeoutMs > 0
569
+ ? setTimeout(() => {
570
+ timedOut = true;
571
+ child.kill('SIGKILL');
572
+ }, options.timeoutMs)
573
+ : undefined;
574
+
575
+ const finish = (fn: () => void): void => {
576
+ if (settled) {
577
+ return;
578
+ }
579
+ settled = true;
580
+ if (timeout) {
581
+ clearTimeout(timeout);
582
+ }
583
+ fn();
584
+ };
488
585
 
489
586
  child.stdout?.on('data', data => {
490
587
  stdout += data.toString();
@@ -495,10 +592,23 @@ export const processUtils = {
495
592
  });
496
593
 
497
594
  child.on('close', code => {
498
- resolve({ code: code ?? 0, stdout, stderr });
595
+ if (timedOut) {
596
+ const timeoutMs = options.timeoutMs;
597
+ finish(() =>
598
+ reject(
599
+ new Error(
600
+ `Command "${command}" timed out after ${typeof timeoutMs === 'number' ? timeoutMs : 0}ms`
601
+ )
602
+ )
603
+ );
604
+ return;
605
+ }
606
+ finish(() => resolve({ code: code ?? 0, stdout, stderr }));
499
607
  });
500
608
 
501
- child.on('error', reject);
609
+ child.on('error', error => {
610
+ finish(() => reject(error));
611
+ });
502
612
  });
503
613
  }
504
614
 
@@ -611,6 +721,7 @@ export const hashUtils = {
611
721
  hash = (hash << 5) + hash + text.charCodeAt(i);
612
722
  hash |= 0;
613
723
  }
614
- return Math.abs(hash).toString(16);
724
+ // Match sha256 hex shape (64 chars) so callers can rely on fixed-length output.
725
+ return Math.abs(hash).toString(16).padStart(64, '0');
615
726
  },
616
727
  };