@tscircuit/core 0.0.49 → 0.0.51

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.
package/dist/index.d.ts CHANGED
@@ -78,7 +78,7 @@ declare abstract class Renderable implements IRenderable {
78
78
  */
79
79
  runRenderPhase(phase: RenderPhase): void;
80
80
  runRenderPhaseForChildren(phase: RenderPhase): void;
81
- renderError(message: string | PCBTraceError | PCBPlacementError): void;
81
+ renderError(message: string | Omit<PCBTraceError, "pcb_error_id"> | Omit<PCBPlacementError, "pcb_error_id">): void;
82
82
  }
83
83
 
84
84
  interface BaseComponentConfig {
@@ -229,6 +229,7 @@ declare abstract class PrimitiveComponent<ZodProps extends ZodType = any> extend
229
229
  }): PrimitiveComponent | null;
230
230
  getAvailablePcbLayers(): string[];
231
231
  getDescendants(): PrimitiveComponent[];
232
+ renderError(message: Parameters<typeof Renderable.prototype.renderError>[0]): void;
232
233
  getString(): string;
233
234
  get [Symbol.toStringTag](): string;
234
235
  }
package/dist/index.js CHANGED
@@ -125,6 +125,7 @@ var Renderable = class {
125
125
  if (typeof message === "string") {
126
126
  throw new Error(message);
127
127
  }
128
+ throw new Error(JSON.stringify(message, null, 2));
128
129
  }
129
130
  };
130
131
 
@@ -487,6 +488,15 @@ var PrimitiveComponent = class extends Renderable {
487
488
  }
488
489
  return descendants;
489
490
  }
491
+ // TODO we shouldn't need to override this, errors can be rendered and handled
492
+ // by the Renderable class, however, the Renderable class currently doesn't
493
+ // have access to the database or cleanup
494
+ renderError(message) {
495
+ if (typeof message === "string") {
496
+ return super.renderError(message);
497
+ }
498
+ this.root?.db.pcb_error.insert(message);
499
+ }
490
500
  getString() {
491
501
  const { lowercaseComponentName: cname, _parsedProps: props, parent } = this;
492
502
  if (parent?.props?.name && props?.name) {
@@ -2469,6 +2479,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
2469
2479
  });
2470
2480
  const routes = [];
2471
2481
  for (const [a, b] of pairs(orderedRoutePoints)) {
2482
+ const dominantLayer = "via_to_layer" in a ? a.via_to_layer : null;
2472
2483
  const BOUNDS_MARGIN = 2;
2473
2484
  const ijump = new IJumpAutorouter({
2474
2485
  OBSTACLE_MARGIN: 0.3,
@@ -2477,7 +2488,10 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
2477
2488
  connections: [
2478
2489
  {
2479
2490
  name: this.source_trace_id,
2480
- pointsToConnect: [a, b]
2491
+ pointsToConnect: [
2492
+ { ...a, layer: dominantLayer ?? "top" },
2493
+ { ...b, layer: dominantLayer ?? "top" }
2494
+ ]
2481
2495
  }
2482
2496
  ],
2483
2497
  layerCount: 2,
@@ -2491,16 +2505,23 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
2491
2505
  });
2492
2506
  const traces = ijump.solveAndMapToTraces();
2493
2507
  if (traces.length === 0) {
2494
- this.renderError(
2495
- `Could not find a route between ${JSON.stringify(a)} and ${JSON.stringify(b)} for ${this}`
2496
- );
2508
+ this.renderError({
2509
+ type: "pcb_error",
2510
+ error_type: "pcb_trace_error",
2511
+ message: `Could not find a route for ${this}`,
2512
+ source_trace_id: this.source_trace_id,
2513
+ center: { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 },
2514
+ pcb_port_ids: ports.map((p) => p.pcb_port_id),
2515
+ pcb_trace_id: this.pcb_trace_id,
2516
+ pcb_component_ids: ports.map((p) => p.pcb_component_id)
2517
+ });
2497
2518
  return;
2498
2519
  }
2499
2520
  const [trace] = traces;
2500
- if ("via_to_layer" in a) {
2521
+ if (dominantLayer) {
2501
2522
  trace.route = trace.route.map((p) => {
2502
2523
  if (p.route_type === "wire") {
2503
- p.layer = a.via_to_layer;
2524
+ p.layer = dominantLayer;
2504
2525
  }
2505
2526
  return p;
2506
2527
  });
@@ -2558,6 +2579,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
2558
2579
  if (elm.type === "schematic_component") {
2559
2580
  obstacles.push({
2560
2581
  type: "rect",
2582
+ layers: ["top"],
2561
2583
  center: elm.center,
2562
2584
  width: elm.size.width,
2563
2585
  height: elm.size.height,
@@ -2566,13 +2588,14 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
2566
2588
  }
2567
2589
  }
2568
2590
  for (const { port } of ports) {
2569
- connection.pointsToConnect.push(
2570
- projectPointInDirection(
2591
+ connection.pointsToConnect.push({
2592
+ ...projectPointInDirection(
2571
2593
  port._getGlobalSchematicPositionBeforeLayout(),
2572
2594
  port.facingDirection,
2573
2595
  0.1501
2574
- )
2575
- );
2596
+ ),
2597
+ layer: "top"
2598
+ });
2576
2599
  }
2577
2600
  const bounds = computeObstacleBounds(obstacles);
2578
2601
  const simpleRouteJsonInput = {
@@ -442,6 +442,17 @@ export abstract class PrimitiveComponent<
442
442
  return descendants
443
443
  }
444
444
 
445
+ // TODO we shouldn't need to override this, errors can be rendered and handled
446
+ // by the Renderable class, however, the Renderable class currently doesn't
447
+ // have access to the database or cleanup
448
+ renderError(message: Parameters<typeof Renderable.prototype.renderError>[0]) {
449
+ if (typeof message === "string") {
450
+ return super.renderError(message)
451
+ }
452
+ // TODO this needs to be cleaned up at some point!
453
+ this.root?.db.pcb_error.insert(message)
454
+ }
455
+
445
456
  getString(): string {
446
457
  const { lowercaseComponentName: cname, _parsedProps: props, parent } = this
447
458
  if (parent?.props?.name && props?.name) {
@@ -110,11 +110,17 @@ export abstract class Renderable implements IRenderable {
110
110
  }
111
111
  }
112
112
 
113
- renderError(message: string | PCBTraceError | PCBPlacementError) {
113
+ renderError(
114
+ message:
115
+ | string
116
+ | Omit<PCBTraceError, "pcb_error_id">
117
+ | Omit<PCBPlacementError, "pcb_error_id">,
118
+ ) {
114
119
  // TODO add to render phase error list and try to add position or
115
120
  // relationships etc.
116
121
  if (typeof message === "string") {
117
122
  throw new Error(message)
118
123
  }
124
+ throw new Error(JSON.stringify(message, null, 2))
119
125
  }
120
126
  }
@@ -411,7 +411,10 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
411
411
 
412
412
  const routes: PCBTrace["route"][] = []
413
413
  for (const [a, b] of pairs(orderedRoutePoints)) {
414
+ const dominantLayer =
415
+ "via_to_layer" in a ? (a.via_to_layer as LayerRef) : null
414
416
  const BOUNDS_MARGIN = 2 //mm
417
+
415
418
  const ijump = new IJumpAutorouter({
416
419
  OBSTACLE_MARGIN: 0.3,
417
420
  input: {
@@ -419,7 +422,10 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
419
422
  connections: [
420
423
  {
421
424
  name: this.source_trace_id!,
422
- pointsToConnect: [a, b],
425
+ pointsToConnect: [
426
+ { ...a, layer: dominantLayer ?? "top" },
427
+ { ...b, layer: dominantLayer ?? "top" },
428
+ ],
423
429
  },
424
430
  ],
425
431
  layerCount: 2,
@@ -433,9 +439,16 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
433
439
  })
434
440
  const traces = ijump.solveAndMapToTraces()
435
441
  if (traces.length === 0) {
436
- this.renderError(
437
- `Could not find a route between ${JSON.stringify(a)} and ${JSON.stringify(b)} for ${this}`,
438
- )
442
+ this.renderError({
443
+ type: "pcb_error",
444
+ error_type: "pcb_trace_error",
445
+ message: `Could not find a route for ${this}`,
446
+ source_trace_id: this.source_trace_id!,
447
+ center: { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 },
448
+ pcb_port_ids: ports.map((p) => p.pcb_port_id!),
449
+ pcb_trace_id: this.pcb_trace_id!,
450
+ pcb_component_ids: ports.map((p) => p.pcb_component_id!),
451
+ })
439
452
  return
440
453
  }
441
454
  // TODO ijump returns multiple traces for some reason
@@ -444,10 +457,10 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
444
457
  // https://github.com/tscircuit/autorouting-dataset/issues/35
445
458
  // For now, we'll move the trace to whatever layer the first point
446
459
  // specifies we should have "via'd" to
447
- if ("via_to_layer" in a) {
460
+ if (dominantLayer) {
448
461
  trace.route = trace.route.map((p) => {
449
462
  if (p.route_type === "wire") {
450
- p.layer = a.via_to_layer as LayerRef
463
+ p.layer = dominantLayer
451
464
  }
452
465
  return p
453
466
  })
@@ -521,6 +534,7 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
521
534
  if (elm.type === "schematic_component") {
522
535
  obstacles.push({
523
536
  type: "rect",
537
+ layers: ["top"],
524
538
  center: elm.center,
525
539
  width: elm.size.width,
526
540
  height: elm.size.height,
@@ -530,13 +544,14 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
530
544
  }
531
545
 
532
546
  for (const { port } of ports) {
533
- connection.pointsToConnect.push(
534
- projectPointInDirection(
547
+ connection.pointsToConnect.push({
548
+ ...projectPointInDirection(
535
549
  port._getGlobalSchematicPositionBeforeLayout(),
536
550
  port.facingDirection!,
537
551
  0.1501,
538
552
  ),
539
- )
553
+ layer: "top",
554
+ })
540
555
  }
541
556
 
542
557
  const bounds = computeObstacleBounds(obstacles)
@@ -12,6 +12,7 @@ export type SimplifiedPcbTrace = {
12
12
  export type Obstacle = {
13
13
  // TODO include ovals
14
14
  type: "rect" // NOTE: most datasets do not contain ovals
15
+ layers: string[]
15
16
  center: { x: number; y: number }
16
17
  width: number
17
18
  height: number
@@ -20,7 +21,7 @@ export type Obstacle = {
20
21
 
21
22
  export interface SimpleRouteConnection {
22
23
  name: string
23
- pointsToConnect: Array<{ x: number; y: number }>
24
+ pointsToConnect: Array<{ x: number; y: number; layer: string }>
24
25
  }
25
26
 
26
27
  export interface SimpleRouteJson {
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@tscircuit/core",
3
3
  "module": "index.ts",
4
4
  "type": "module",
5
- "version": "0.0.49",
5
+ "version": "0.0.51",
6
6
  "types": "dist/index.d.ts",
7
7
  "main": "dist/index.js",
8
8
  "files": [
@@ -23,7 +23,7 @@
23
23
  "@types/react": "^18.3.3",
24
24
  "@types/react-reconciler": "^0.28.8",
25
25
  "bun-match-svg": "0.0.2",
26
- "circuit-to-svg": "^0.0.18",
26
+ "circuit-to-svg": "^0.0.22",
27
27
  "debug": "^4.3.6",
28
28
  "howfat": "^0.3.8",
29
29
  "looks-same": "^9.0.1",
@@ -34,7 +34,7 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "@lume/kiwi": "^0.4.3",
37
- "@tscircuit/infgrid-ijump-astar": "^0.0.9",
37
+ "@tscircuit/infgrid-ijump-astar": "^0.0.10",
38
38
  "@tscircuit/props": "^0.0.62",
39
39
  "@tscircuit/soup": "^0.0.67",
40
40
  "@tscircuit/soup-util": "^0.0.23",