@tscircuit/core 0.0.50 → 0.0.52
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 +2 -1
- package/dist/index.js +63 -9
- package/lib/components/base-components/PrimitiveComponent.ts +11 -0
- package/lib/components/base-components/Renderable.ts +7 -1
- package/lib/components/primitive-components/Trace.ts +46 -21
- package/lib/utils/try-now.ts +7 -0
- package/package.json +2 -2
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) {
|
|
@@ -2213,6 +2223,17 @@ function getClosest(point, candidates) {
|
|
|
2213
2223
|
|
|
2214
2224
|
// lib/components/primitive-components/Trace.ts
|
|
2215
2225
|
import "zod";
|
|
2226
|
+
|
|
2227
|
+
// lib/utils/try-now.ts
|
|
2228
|
+
function tryNow(fn) {
|
|
2229
|
+
try {
|
|
2230
|
+
return [fn(), null];
|
|
2231
|
+
} catch (e) {
|
|
2232
|
+
return [null, e];
|
|
2233
|
+
}
|
|
2234
|
+
}
|
|
2235
|
+
|
|
2236
|
+
// lib/components/primitive-components/Trace.ts
|
|
2216
2237
|
var portToObjective = (port) => {
|
|
2217
2238
|
const portPosition = port._getGlobalPcbPositionAfterLayout();
|
|
2218
2239
|
return {
|
|
@@ -2390,10 +2411,6 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
2390
2411
|
);
|
|
2391
2412
|
return;
|
|
2392
2413
|
}
|
|
2393
|
-
const pcbElements = db.toArray().filter(
|
|
2394
|
-
(elm) => elm.type === "pcb_smtpad" || elm.type === "pcb_trace" || elm.type === "pcb_plated_hole" || elm.type === "pcb_hole" || elm.type === "source_port" || elm.type === "pcb_port" || elm.type === "source_trace" || elm.type === "pcb_keepout"
|
|
2395
|
-
);
|
|
2396
|
-
const source_trace = db.source_trace.get(this.source_trace_id);
|
|
2397
2414
|
const hints = ports.flatMap(
|
|
2398
2415
|
(port) => port.matchedComponents.filter((c) => c.componentName === "TraceHint")
|
|
2399
2416
|
);
|
|
@@ -2441,7 +2458,22 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
2441
2458
|
);
|
|
2442
2459
|
return;
|
|
2443
2460
|
}
|
|
2444
|
-
const obstacles =
|
|
2461
|
+
const [obstacles, err] = tryNow(
|
|
2462
|
+
() => getObstaclesFromSoup(this.root.db.toArray())
|
|
2463
|
+
);
|
|
2464
|
+
if (err) {
|
|
2465
|
+
this.renderError({
|
|
2466
|
+
type: "pcb_error",
|
|
2467
|
+
error_type: "pcb_trace_error",
|
|
2468
|
+
message: `Error getting obstacles for autorouting: ${err.message}`,
|
|
2469
|
+
source_trace_id: this.source_trace_id,
|
|
2470
|
+
center: { x: 0, y: 0 },
|
|
2471
|
+
pcb_port_ids: ports.map((p) => p.pcb_port_id),
|
|
2472
|
+
pcb_trace_id: this.pcb_trace_id,
|
|
2473
|
+
pcb_component_ids: []
|
|
2474
|
+
});
|
|
2475
|
+
return;
|
|
2476
|
+
}
|
|
2445
2477
|
markObstaclesAsConnected(
|
|
2446
2478
|
obstacles,
|
|
2447
2479
|
orderedRouteObjectives,
|
|
@@ -2493,11 +2525,33 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
2493
2525
|
}
|
|
2494
2526
|
}
|
|
2495
2527
|
});
|
|
2496
|
-
|
|
2528
|
+
let traces = null;
|
|
2529
|
+
try {
|
|
2530
|
+
traces = ijump.solveAndMapToTraces();
|
|
2531
|
+
} catch (e) {
|
|
2532
|
+
this.renderError({
|
|
2533
|
+
type: "pcb_error",
|
|
2534
|
+
error_type: "pcb_trace_error",
|
|
2535
|
+
message: `error solving route: ${e.message}`,
|
|
2536
|
+
source_trace_id: this.source_trace_id,
|
|
2537
|
+
center: { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 },
|
|
2538
|
+
pcb_port_ids: ports.map((p) => p.pcb_port_id),
|
|
2539
|
+
pcb_trace_id: this.pcb_trace_id,
|
|
2540
|
+
pcb_component_ids: ports.map((p) => p.pcb_component_id)
|
|
2541
|
+
});
|
|
2542
|
+
}
|
|
2543
|
+
if (!traces) return;
|
|
2497
2544
|
if (traces.length === 0) {
|
|
2498
|
-
this.renderError(
|
|
2499
|
-
|
|
2500
|
-
|
|
2545
|
+
this.renderError({
|
|
2546
|
+
type: "pcb_error",
|
|
2547
|
+
error_type: "pcb_trace_error",
|
|
2548
|
+
message: `Could not find a route for ${this}`,
|
|
2549
|
+
source_trace_id: this.source_trace_id,
|
|
2550
|
+
center: { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 },
|
|
2551
|
+
pcb_port_ids: ports.map((p) => p.pcb_port_id),
|
|
2552
|
+
pcb_trace_id: this.pcb_trace_id,
|
|
2553
|
+
pcb_component_ids: ports.map((p) => p.pcb_component_id)
|
|
2554
|
+
});
|
|
2501
2555
|
return;
|
|
2502
2556
|
}
|
|
2503
2557
|
const [trace] = traces;
|
|
@@ -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(
|
|
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
|
}
|
|
@@ -19,6 +19,7 @@ import type {
|
|
|
19
19
|
Obstacle,
|
|
20
20
|
SimpleRouteConnection,
|
|
21
21
|
SimpleRouteJson,
|
|
22
|
+
SimplifiedPcbTrace,
|
|
22
23
|
} from "lib/utils/autorouting/SimpleRouteJson"
|
|
23
24
|
import { computeObstacleBounds } from "lib/utils/autorouting/computeObstacleBounds"
|
|
24
25
|
import { projectPointInDirection } from "lib/utils/projectPointInDirection"
|
|
@@ -37,6 +38,7 @@ import {
|
|
|
37
38
|
isMatchingPathSelector,
|
|
38
39
|
isMatchingSelector,
|
|
39
40
|
} from "lib/utils/selector-matching"
|
|
41
|
+
import { tryNow } from "lib/utils/try-now"
|
|
40
42
|
|
|
41
43
|
type PcbRouteObjective =
|
|
42
44
|
| RouteHintPoint
|
|
@@ -285,22 +287,6 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
285
287
|
return
|
|
286
288
|
}
|
|
287
289
|
|
|
288
|
-
const pcbElements: AnySoupElement[] = db
|
|
289
|
-
.toArray()
|
|
290
|
-
.filter(
|
|
291
|
-
(elm) =>
|
|
292
|
-
elm.type === "pcb_smtpad" ||
|
|
293
|
-
elm.type === "pcb_trace" ||
|
|
294
|
-
elm.type === "pcb_plated_hole" ||
|
|
295
|
-
elm.type === "pcb_hole" ||
|
|
296
|
-
elm.type === "source_port" ||
|
|
297
|
-
elm.type === "pcb_port" ||
|
|
298
|
-
elm.type === "source_trace" ||
|
|
299
|
-
elm.type === "pcb_keepout",
|
|
300
|
-
)
|
|
301
|
-
|
|
302
|
-
const source_trace = db.source_trace.get(this.source_trace_id!)!
|
|
303
|
-
|
|
304
290
|
const hints = ports.flatMap((port) =>
|
|
305
291
|
port.matchedComponents.filter((c) => c.componentName === "TraceHint"),
|
|
306
292
|
) as TraceHint[]
|
|
@@ -372,7 +358,24 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
372
358
|
|
|
373
359
|
// Cache the PCB obstacles, they'll be needed for each segment between
|
|
374
360
|
// ports/hints
|
|
375
|
-
const obstacles =
|
|
361
|
+
const [obstacles, err] = tryNow(() =>
|
|
362
|
+
getObstaclesFromSoup(this.root!.db.toArray()),
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
if (err) {
|
|
366
|
+
this.renderError({
|
|
367
|
+
type: "pcb_error",
|
|
368
|
+
error_type: "pcb_trace_error",
|
|
369
|
+
message: `Error getting obstacles for autorouting: ${err.message}`,
|
|
370
|
+
source_trace_id: this.source_trace_id!,
|
|
371
|
+
center: { x: 0, y: 0 },
|
|
372
|
+
pcb_port_ids: ports.map((p) => p.pcb_port_id!),
|
|
373
|
+
pcb_trace_id: this.pcb_trace_id!,
|
|
374
|
+
pcb_component_ids: [],
|
|
375
|
+
})
|
|
376
|
+
return
|
|
377
|
+
}
|
|
378
|
+
|
|
376
379
|
markObstaclesAsConnected(
|
|
377
380
|
obstacles,
|
|
378
381
|
orderedRouteObjectives,
|
|
@@ -437,11 +440,33 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
437
440
|
},
|
|
438
441
|
},
|
|
439
442
|
})
|
|
440
|
-
|
|
443
|
+
let traces: SimplifiedPcbTrace[] | null = null
|
|
444
|
+
try {
|
|
445
|
+
traces = ijump.solveAndMapToTraces()
|
|
446
|
+
} catch (e: any) {
|
|
447
|
+
this.renderError({
|
|
448
|
+
type: "pcb_error",
|
|
449
|
+
error_type: "pcb_trace_error",
|
|
450
|
+
message: `error solving route: ${e.message}`,
|
|
451
|
+
source_trace_id: this.source_trace_id!,
|
|
452
|
+
center: { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 },
|
|
453
|
+
pcb_port_ids: ports.map((p) => p.pcb_port_id!),
|
|
454
|
+
pcb_trace_id: this.pcb_trace_id!,
|
|
455
|
+
pcb_component_ids: ports.map((p) => p.pcb_component_id!),
|
|
456
|
+
})
|
|
457
|
+
}
|
|
458
|
+
if (!traces) return
|
|
441
459
|
if (traces.length === 0) {
|
|
442
|
-
this.renderError(
|
|
443
|
-
|
|
444
|
-
|
|
460
|
+
this.renderError({
|
|
461
|
+
type: "pcb_error",
|
|
462
|
+
error_type: "pcb_trace_error",
|
|
463
|
+
message: `Could not find a route for ${this}`,
|
|
464
|
+
source_trace_id: this.source_trace_id!,
|
|
465
|
+
center: { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 },
|
|
466
|
+
pcb_port_ids: ports.map((p) => p.pcb_port_id!),
|
|
467
|
+
pcb_trace_id: this.pcb_trace_id!,
|
|
468
|
+
pcb_component_ids: ports.map((p) => p.pcb_component_id!),
|
|
469
|
+
})
|
|
445
470
|
return
|
|
446
471
|
}
|
|
447
472
|
// TODO ijump returns multiple traces for some reason
|
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.
|
|
5
|
+
"version": "0.0.52",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"files": [
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@lume/kiwi": "^0.4.3",
|
|
37
|
-
"@tscircuit/infgrid-ijump-astar": "^0.0.
|
|
37
|
+
"@tscircuit/infgrid-ijump-astar": "^0.0.11",
|
|
38
38
|
"@tscircuit/props": "^0.0.62",
|
|
39
39
|
"@tscircuit/soup": "^0.0.67",
|
|
40
40
|
"@tscircuit/soup-util": "^0.0.23",
|