tywrap 0.2.1 → 0.4.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 (144) hide show
  1. package/README.md +100 -32
  2. package/dist/cli.js +70 -5
  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 +62 -20
  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 +46 -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/dev.d.ts +57 -0
  29. package/dist/dev.d.ts.map +1 -0
  30. package/dist/dev.js +743 -0
  31. package/dist/dev.js.map +1 -0
  32. package/dist/index.d.ts +8 -7
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +4 -4
  35. package/dist/index.js.map +1 -1
  36. package/dist/runtime/bridge-core.d.ts +1 -0
  37. package/dist/runtime/bridge-core.d.ts.map +1 -1
  38. package/dist/runtime/bridge-core.js +52 -17
  39. package/dist/runtime/bridge-core.js.map +1 -1
  40. package/dist/runtime/bridge-protocol.d.ts +17 -0
  41. package/dist/runtime/bridge-protocol.d.ts.map +1 -1
  42. package/dist/runtime/bridge-protocol.js +97 -0
  43. package/dist/runtime/bridge-protocol.js.map +1 -1
  44. package/dist/runtime/errors.d.ts +10 -0
  45. package/dist/runtime/errors.d.ts.map +1 -1
  46. package/dist/runtime/errors.js +9 -0
  47. package/dist/runtime/errors.js.map +1 -1
  48. package/dist/runtime/http-io.d.ts.map +1 -1
  49. package/dist/runtime/http-io.js.map +1 -1
  50. package/dist/runtime/http.d.ts +1 -0
  51. package/dist/runtime/http.d.ts.map +1 -1
  52. package/dist/runtime/http.js +6 -0
  53. package/dist/runtime/http.js.map +1 -1
  54. package/dist/runtime/node.d.ts.map +1 -1
  55. package/dist/runtime/node.js +206 -32
  56. package/dist/runtime/node.js.map +1 -1
  57. package/dist/runtime/optimized-node.d.ts +6 -5
  58. package/dist/runtime/optimized-node.d.ts.map +1 -1
  59. package/dist/runtime/optimized-node.js +6 -5
  60. package/dist/runtime/optimized-node.js.map +1 -1
  61. package/dist/runtime/pooled-transport.d.ts +4 -0
  62. package/dist/runtime/pooled-transport.d.ts.map +1 -1
  63. package/dist/runtime/pooled-transport.js +2 -0
  64. package/dist/runtime/pooled-transport.js.map +1 -1
  65. package/dist/runtime/process-io.d.ts +5 -0
  66. package/dist/runtime/process-io.d.ts.map +1 -1
  67. package/dist/runtime/process-io.js +64 -30
  68. package/dist/runtime/process-io.js.map +1 -1
  69. package/dist/runtime/pyodide-io.d.ts +4 -5
  70. package/dist/runtime/pyodide-io.d.ts.map +1 -1
  71. package/dist/runtime/pyodide-io.js +99 -37
  72. package/dist/runtime/pyodide-io.js.map +1 -1
  73. package/dist/runtime/safe-codec.d.ts +25 -3
  74. package/dist/runtime/safe-codec.d.ts.map +1 -1
  75. package/dist/runtime/safe-codec.js +231 -57
  76. package/dist/runtime/safe-codec.js.map +1 -1
  77. package/dist/runtime/transport.d.ts +6 -1
  78. package/dist/runtime/transport.d.ts.map +1 -1
  79. package/dist/runtime/transport.js.map +1 -1
  80. package/dist/runtime/validators.d.ts +0 -11
  81. package/dist/runtime/validators.d.ts.map +1 -1
  82. package/dist/runtime/validators.js +13 -3
  83. package/dist/runtime/validators.js.map +1 -1
  84. package/dist/runtime/worker-pool.d.ts +17 -0
  85. package/dist/runtime/worker-pool.d.ts.map +1 -1
  86. package/dist/runtime/worker-pool.js +97 -22
  87. package/dist/runtime/worker-pool.js.map +1 -1
  88. package/dist/types/index.d.ts +51 -8
  89. package/dist/types/index.d.ts.map +1 -1
  90. package/dist/tywrap.d.ts +6 -0
  91. package/dist/tywrap.d.ts.map +1 -1
  92. package/dist/tywrap.js +237 -331
  93. package/dist/tywrap.js.map +1 -1
  94. package/dist/utils/cache.d.ts.map +1 -1
  95. package/dist/utils/cache.js +53 -5
  96. package/dist/utils/cache.js.map +1 -1
  97. package/dist/utils/codec.d.ts.map +1 -1
  98. package/dist/utils/codec.js +10 -16
  99. package/dist/utils/codec.js.map +1 -1
  100. package/dist/utils/ir-cache.d.ts +28 -0
  101. package/dist/utils/ir-cache.d.ts.map +1 -0
  102. package/dist/utils/ir-cache.js +29 -0
  103. package/dist/utils/ir-cache.js.map +1 -0
  104. package/dist/utils/parallel-processor.d.ts +1 -1
  105. package/dist/utils/parallel-processor.d.ts.map +1 -1
  106. package/dist/utils/parallel-processor.js +111 -40
  107. package/dist/utils/parallel-processor.js.map +1 -1
  108. package/dist/utils/runtime.d.ts +5 -1
  109. package/dist/utils/runtime.d.ts.map +1 -1
  110. package/dist/utils/runtime.js +112 -18
  111. package/dist/utils/runtime.js.map +1 -1
  112. package/package.json +47 -21
  113. package/runtime/python_bridge.py +78 -12
  114. package/src/cli.ts +85 -5
  115. package/src/config/index.ts +91 -32
  116. package/src/core/analyzer.ts +51 -15
  117. package/src/core/annotation-parser.ts +500 -0
  118. package/src/core/discovery.ts +26 -12
  119. package/src/core/generator.ts +956 -116
  120. package/src/core/mapper.ts +158 -51
  121. package/src/dev.ts +983 -0
  122. package/src/index.ts +35 -6
  123. package/src/runtime/bridge-core.ts +58 -18
  124. package/src/runtime/bridge-protocol.ts +164 -0
  125. package/src/runtime/errors.ts +14 -0
  126. package/src/runtime/http-io.ts +2 -1
  127. package/src/runtime/http.ts +7 -0
  128. package/src/runtime/node.ts +312 -46
  129. package/src/runtime/optimized-node.ts +9 -5
  130. package/src/runtime/pooled-transport.ts +12 -1
  131. package/src/runtime/process-io.ts +83 -55
  132. package/src/runtime/pyodide-io.ts +110 -44
  133. package/src/runtime/safe-codec.ts +290 -82
  134. package/src/runtime/transport.ts +6 -1
  135. package/src/runtime/validators.ts +14 -3
  136. package/src/runtime/worker-pool.ts +120 -24
  137. package/src/types/global.d.ts +11 -1
  138. package/src/types/index.ts +63 -8
  139. package/src/tywrap.ts +296 -361
  140. package/src/utils/cache.ts +59 -5
  141. package/src/utils/codec.ts +11 -15
  142. package/src/utils/ir-cache.ts +51 -0
  143. package/src/utils/parallel-processor.ts +119 -43
  144. package/src/utils/runtime.ts +129 -18
@@ -39,6 +39,13 @@ export interface WorkerPoolOptions {
39
39
  * Use this for per-worker warmup (e.g., importing modules, running setup).
40
40
  */
41
41
  onWorkerReady?: (worker: PooledWorker) => Promise<void>;
42
+
43
+ /**
44
+ * Optional callback used only for background replacement workers after a
45
+ * fatal timeout/crash. This lets callers publish a replacement only after it
46
+ * is proven ready, without charging hidden work to normal request startup.
47
+ */
48
+ onReplacementWorkerReady?: (worker: PooledWorker) => Promise<void>;
42
49
  }
43
50
 
44
51
  /**
@@ -99,8 +106,12 @@ interface QueuedWaiter {
99
106
  * ```
100
107
  */
101
108
  export class WorkerPool extends BoundedContext {
102
- private readonly options: Omit<Required<WorkerPoolOptions>, 'onWorkerReady'> & {
109
+ private readonly options: Omit<
110
+ Required<WorkerPoolOptions>,
111
+ 'onWorkerReady' | 'onReplacementWorkerReady'
112
+ > & {
103
113
  onWorkerReady?: (worker: PooledWorker) => Promise<void>;
114
+ onReplacementWorkerReady?: (worker: PooledWorker) => Promise<void>;
104
115
  };
105
116
  private readonly workers: PooledWorker[] = [];
106
117
  private readonly waitQueue: QueuedWaiter[] = [];
@@ -135,6 +146,7 @@ export class WorkerPool extends BoundedContext {
135
146
  queueTimeoutMs: options.queueTimeoutMs ?? 30000,
136
147
  maxConcurrentPerWorker: options.maxConcurrentPerWorker ?? 1,
137
148
  onWorkerReady: options.onWorkerReady,
149
+ onReplacementWorkerReady: options.onReplacementWorkerReady,
138
150
  };
139
151
  }
140
152
 
@@ -150,13 +162,7 @@ export class WorkerPool extends BoundedContext {
150
162
  */
151
163
  protected async doInit(): Promise<void> {
152
164
  // Pre-spawn minimum workers if configured
153
- if (this.options.minWorkers > 0) {
154
- const spawns: Promise<PooledWorker>[] = [];
155
- for (let i = 0; i < this.options.minWorkers; i++) {
156
- spawns.push(this.createWorker());
157
- }
158
- await Promise.all(spawns);
159
- }
165
+ await this.fillToMinimumWorkers();
160
166
  }
161
167
 
162
168
  /**
@@ -212,7 +218,7 @@ export class WorkerPool extends BoundedContext {
212
218
  */
213
219
  async acquire(): Promise<PooledWorker> {
214
220
  // Check for disposed state
215
- if (this.isDisposed) {
221
+ if (this.isDisposed || this.state === 'disposing') {
216
222
  throw new BridgeExecutionError('Pool has been disposed');
217
223
  }
218
224
 
@@ -231,7 +237,12 @@ export class WorkerPool extends BoundedContext {
231
237
  this.pendingCreations++;
232
238
  try {
233
239
  const newWorker = await this.createWorker();
240
+ if (this.isShuttingDown()) {
241
+ this.removeWorker(newWorker);
242
+ throw new BridgeExecutionError('Pool has been disposed');
243
+ }
234
244
  newWorker.inFlightCount++;
245
+ this.publishAvailableWorker(newWorker);
235
246
  return newWorker;
236
247
  } finally {
237
248
  this.pendingCreations--;
@@ -258,16 +269,7 @@ export class WorkerPool extends BoundedContext {
258
269
 
259
270
  // Decrement in-flight count (minimum 0)
260
271
  worker.inFlightCount = Math.max(0, worker.inFlightCount - 1);
261
-
262
- // If there are waiters and this worker has capacity, fulfill the first waiter
263
- if (this.waitQueue.length > 0 && worker.inFlightCount < this.options.maxConcurrentPerWorker) {
264
- const waiter = this.waitQueue.shift();
265
- if (waiter) {
266
- clearTimeout(waiter.timer);
267
- worker.inFlightCount++;
268
- waiter.resolve(worker);
269
- }
270
- }
272
+ this.publishAvailableWorker(worker);
271
273
  }
272
274
 
273
275
  /**
@@ -347,6 +349,9 @@ export class WorkerPool extends BoundedContext {
347
349
  worker.transport.dispose().catch(() => {
348
350
  // Ignore disposal errors for dead workers
349
351
  });
352
+ if (this.state === 'ready') {
353
+ this.scheduleReplacementWorker();
354
+ }
350
355
  }
351
356
  }
352
357
 
@@ -386,13 +391,89 @@ export class WorkerPool extends BoundedContext {
386
391
  return this.workers.find(w => w.inFlightCount < this.options.maxConcurrentPerWorker);
387
392
  }
388
393
 
394
+ private getMinimumWorkerDeficit(): number {
395
+ return Math.max(0, this.options.minWorkers - (this.workers.length + this.pendingCreations));
396
+ }
397
+
398
+ private isShuttingDown(): boolean {
399
+ return this.isDisposed || this.state === 'disposing';
400
+ }
401
+
402
+ private async fillToMinimumWorkers(): Promise<void> {
403
+ await this.spawnWorkers(this.getMinimumWorkerDeficit());
404
+ }
405
+
406
+ private async spawnWorkers(count: number): Promise<void> {
407
+ if (count === 0) {
408
+ return;
409
+ }
410
+ this.pendingCreations += count;
411
+ try {
412
+ await Promise.all(Array.from({ length: count }, () => this.spawnWorkerToPool()));
413
+ } finally {
414
+ this.pendingCreations = Math.max(0, this.pendingCreations - count);
415
+ }
416
+ }
417
+
418
+ /**
419
+ * Replace a removed worker in the background so the next caller does not pay
420
+ * the full worker cold-start penalty after a timeout or crash.
421
+ */
422
+ private scheduleReplacementWorker(): void {
423
+ if (this.state !== 'ready') {
424
+ return;
425
+ }
426
+ if (this.workers.length + this.pendingCreations >= this.options.maxWorkers) {
427
+ return;
428
+ }
429
+
430
+ this.pendingCreations++;
431
+ const replacementReady = this.options.onReplacementWorkerReady ?? this.options.onWorkerReady;
432
+ this.spawnWorkerToPool(replacementReady)
433
+ .catch(() => {
434
+ // Ignore background replacement failures. A later acquire() can retry.
435
+ })
436
+ .finally(() => {
437
+ this.pendingCreations = Math.max(0, this.pendingCreations - 1);
438
+ });
439
+ }
440
+
441
+ private async spawnWorkerToPool(onWorkerReady = this.options.onWorkerReady): Promise<void> {
442
+ if (this.isShuttingDown()) {
443
+ return;
444
+ }
445
+
446
+ const worker = await this.createWorker(onWorkerReady);
447
+ if (this.isShuttingDown()) {
448
+ this.removeWorker(worker);
449
+ return;
450
+ }
451
+
452
+ this.publishAvailableWorker(worker);
453
+ }
454
+
455
+ private publishAvailableWorker(worker: PooledWorker): void {
456
+ while (
457
+ this.waitQueue.length > 0 &&
458
+ worker.inFlightCount < this.options.maxConcurrentPerWorker
459
+ ) {
460
+ const waiter = this.waitQueue.shift();
461
+ if (!waiter) {
462
+ return;
463
+ }
464
+ clearTimeout(waiter.timer);
465
+ worker.inFlightCount++;
466
+ waiter.resolve(worker);
467
+ }
468
+ }
469
+
389
470
  /**
390
471
  * Create a new worker and add it to the pool.
391
472
  *
392
473
  * If onWorkerReady is configured, calls it after the transport is initialized.
393
474
  * This is useful for per-worker warmup (importing modules, running setup).
394
475
  */
395
- private async createWorker(): Promise<PooledWorker> {
476
+ private async createWorker(onWorkerReady = this.options.onWorkerReady): Promise<PooledWorker> {
396
477
  const transport = this.options.createTransport();
397
478
 
398
479
  // Initialize the transport
@@ -403,13 +484,28 @@ export class WorkerPool extends BoundedContext {
403
484
  inFlightCount: 0,
404
485
  };
405
486
 
406
- this.workers.push(worker);
487
+ try {
488
+ // Call onWorkerReady callback if provided
489
+ if (onWorkerReady) {
490
+ await onWorkerReady(worker);
491
+ }
492
+ } catch (error) {
493
+ // Ensure partially initialized workers do not leak when warmup fails.
494
+ await transport.dispose().catch(() => {
495
+ // Ignore disposal failures during warmup failure handling.
496
+ });
497
+ throw error;
498
+ }
407
499
 
408
- // Call onWorkerReady callback if provided
409
- if (this.options.onWorkerReady) {
410
- await this.options.onWorkerReady(worker);
500
+ if (this.state === 'disposing' || this.state === 'disposed') {
501
+ await transport.dispose().catch(() => {
502
+ // Ignore disposal failures if the pool was torn down mid-creation.
503
+ });
504
+ throw new BridgeExecutionError('Pool disposed during worker creation');
411
505
  }
412
506
 
507
+ this.workers.push(worker);
508
+
413
509
  return worker;
414
510
  }
415
511
 
@@ -8,13 +8,20 @@ declare namespace DenoTypes {
8
8
  deno: string;
9
9
  }
10
10
 
11
+ interface CommandOptions {
12
+ args?: string[];
13
+ cwd?: string;
14
+ env?: Record<string, string>;
15
+ signal?: AbortSignal;
16
+ }
17
+
11
18
  interface DenoGlobal {
12
19
  version: Version;
13
20
  readTextFile(path: string): Promise<string>;
14
21
  writeTextFile(path: string, content: string): Promise<void>;
15
22
  Command: new (
16
23
  cmd: string,
17
- options?: { args?: string[] }
24
+ options?: CommandOptions
18
25
  ) => {
19
26
  output(): Promise<{ code: number; stdout: Uint8Array; stderr: Uint8Array }>;
20
27
  };
@@ -37,12 +44,15 @@ declare namespace BunTypes {
37
44
  options?: {
38
45
  stdout?: string;
39
46
  stderr?: string;
47
+ cwd?: string;
48
+ env?: Record<string, string>;
40
49
  }
41
50
  ): {
42
51
  stdout: ReadableStream;
43
52
  stderr: ReadableStream;
44
53
  exitCode?: number;
45
54
  exited: Promise<void>;
55
+ kill(signal?: number | string): void;
46
56
  };
47
57
  }
48
58
  }
@@ -8,6 +8,7 @@ export interface PythonModule {
8
8
  version?: string;
9
9
  functions: PythonFunction[];
10
10
  classes: PythonClass[];
11
+ typeAliases?: PythonTypeAlias[];
11
12
  imports: PythonImport[];
12
13
  exports: string[];
13
14
  }
@@ -19,6 +20,7 @@ export interface PythonFunction {
19
20
  decorators: string[];
20
21
  isAsync: boolean;
21
22
  isGenerator: boolean;
23
+ typeParameters?: PythonGenericParameter[];
22
24
  returnType: PythonType;
23
25
  parameters: Parameter[];
24
26
  }
@@ -31,6 +33,23 @@ export interface PythonClass {
31
33
  docstring?: string;
32
34
  decorators: string[];
33
35
  kind?: 'class' | 'protocol' | 'typed_dict' | 'namedtuple' | 'dataclass' | 'pydantic';
36
+ typeParameters?: PythonGenericParameter[];
37
+ }
38
+
39
+ export interface PythonTypeAlias {
40
+ name: string;
41
+ type: PythonType;
42
+ typeParameters?: PythonGenericParameter[];
43
+ }
44
+
45
+ export type PythonGenericParameterKind = 'typevar' | 'paramspec' | 'typevartuple';
46
+
47
+ export interface PythonGenericParameter {
48
+ name: string;
49
+ kind: PythonGenericParameterKind;
50
+ bound?: PythonType;
51
+ constraints?: PythonType[];
52
+ variance?: 'covariant' | 'contravariant' | 'invariant';
34
53
  }
35
54
 
36
55
  export interface PythonImport {
@@ -47,12 +66,15 @@ export interface Parameter {
47
66
  defaultValue?: unknown;
48
67
  varArgs: boolean;
49
68
  kwArgs: boolean;
69
+ positionalOnly?: boolean;
70
+ keywordOnly?: boolean;
50
71
  }
51
72
 
52
73
  export interface Property {
53
74
  name: string;
54
75
  type: PythonType;
55
76
  readonly: boolean;
77
+ optional?: boolean;
56
78
  setter?: boolean;
57
79
  getter?: boolean;
58
80
  }
@@ -76,6 +98,11 @@ export type PythonType =
76
98
  | AnnotatedType
77
99
  | CustomType
78
100
  | TypeVarType
101
+ | ParamSpecType
102
+ | ParamSpecArgsType
103
+ | ParamSpecKwargsType
104
+ | TypeVarTupleType
105
+ | UnpackType
79
106
  | FinalType
80
107
  | ClassVarType;
81
108
 
@@ -103,6 +130,7 @@ export interface OptionalType {
103
130
  export interface GenericType {
104
131
  kind: 'generic';
105
132
  name: string;
133
+ module?: string;
106
134
  typeArgs: PythonType[];
107
135
  }
108
136
 
@@ -115,6 +143,7 @@ export interface CustomType {
115
143
  export interface CallableType {
116
144
  kind: 'callable';
117
145
  parameters: PythonType[];
146
+ parameterSpec?: ParamSpecType;
118
147
  returnType: PythonType;
119
148
  }
120
149
 
@@ -137,6 +166,31 @@ export interface TypeVarType {
137
166
  variance?: 'covariant' | 'contravariant' | 'invariant';
138
167
  }
139
168
 
169
+ export interface ParamSpecType {
170
+ kind: 'paramspec';
171
+ name: string;
172
+ }
173
+
174
+ export interface ParamSpecArgsType {
175
+ kind: 'paramspec_args';
176
+ name: string;
177
+ }
178
+
179
+ export interface ParamSpecKwargsType {
180
+ kind: 'paramspec_kwargs';
181
+ name: string;
182
+ }
183
+
184
+ export interface TypeVarTupleType {
185
+ kind: 'typevartuple';
186
+ name: string;
187
+ }
188
+
189
+ export interface UnpackType {
190
+ kind: 'unpack';
191
+ type: PythonType;
192
+ }
193
+
140
194
  export interface FinalType {
141
195
  kind: 'final';
142
196
  type: PythonType;
@@ -242,10 +296,14 @@ export type RuntimeStrategy = 'pyodide' | 'node' | 'http' | 'auto';
242
296
 
243
297
  export interface TywrapOptions {
244
298
  pythonModules: Record<string, PythonModuleConfig>;
299
+ /**
300
+ * Additional Python import paths to prepend to PYTHONPATH during code generation
301
+ * and discovery (IR extraction). Useful for local modules not installed in site-packages.
302
+ */
303
+ pythonImportPath?: string[];
245
304
  output: OutputConfig;
246
305
  runtime: RuntimeConfig;
247
306
  performance: PerformanceConfig;
248
- development: DevelopmentConfig;
249
307
  types?: TypeMappingConfig;
250
308
  debug?: boolean;
251
309
  }
@@ -255,9 +313,12 @@ export interface PythonModuleConfig {
255
313
  runtime: RuntimeStrategy;
256
314
  functions?: string[];
257
315
  classes?: string[];
316
+ /** Exclude specific exports by exact name. */
317
+ exclude?: string[];
318
+ /** Exclude exports matching one or more regex patterns (JavaScript RegExp source). */
319
+ excludePatterns?: string[];
258
320
  alias?: string;
259
321
  typeHints: 'strict' | 'loose' | 'ignore';
260
- watch?: boolean;
261
322
  }
262
323
 
263
324
  export interface OutputConfig {
@@ -297,12 +358,6 @@ export interface PerformanceConfig {
297
358
  compression: 'auto' | 'gzip' | 'brotli' | 'none';
298
359
  }
299
360
 
300
- export interface DevelopmentConfig {
301
- hotReload: boolean;
302
- sourceMap: boolean;
303
- validation: 'runtime' | 'compile' | 'both' | 'none';
304
- }
305
-
306
361
  export type TypePreset = 'numpy' | 'pandas' | 'pydantic' | 'stdlib' | 'scipy' | 'torch' | 'sklearn';
307
362
 
308
363
  export interface TypeMappingConfig {