@tscircuit/core 0.0.276 → 0.0.278

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
@@ -45,8 +45,9 @@ declare abstract class Renderable implements IRenderable {
45
45
  _renderId: string;
46
46
  _currentRenderPhase: RenderPhase | null;
47
47
  private _asyncEffects;
48
+ parent: Renderable | null;
48
49
  constructor(props: any);
49
- protected _markDirty(phase: RenderPhase): void;
50
+ _markDirty(phase: RenderPhase): void;
50
51
  protected _queueAsyncEffect(effectName: string, effect: () => Promise<void>): void;
51
52
  protected _emitRenderLifecycleEvent(phase: RenderPhase, startOrEnd: "start" | "end"): void;
52
53
  getString(): string;
@@ -928,6 +929,7 @@ interface SimpleRouteJson {
928
929
  declare class Group<Props extends z.ZodType<any, any, any> = typeof groupProps> extends NormalComponent<Props> implements ISubcircuit {
929
930
  pcb_group_id: string | null;
930
931
  subcircuit_id: string | null;
932
+ _hasStartedAsyncAutorouting: boolean;
931
933
  _asyncAutoroutingResult: {
932
934
  output_simple_route_json?: SimpleRouteJson;
933
935
  output_pcb_traces?: PcbTrace[];
@@ -937,10 +939,15 @@ declare class Group<Props extends z.ZodType<any, any, any> = typeof groupProps>
937
939
  componentName: string;
938
940
  };
939
941
  doInitialSourceRender(): void;
942
+ doInitialSourceParentAttachment(): void;
940
943
  doInitialPcbComponentRender(): void;
941
944
  doInitialCreateTraceHintsFromProps(): void;
942
945
  _getSimpleRouteJsonFromPcbTraces(): SimpleRouteJson;
943
946
  doInitialSourceAddConnectivityMapKey(): void;
947
+ _areChildSubcircuitsRouted(): boolean;
948
+ _shouldRouteAsync(): boolean;
949
+ _runEffectMakeHttpAutoroutingRequest(): Promise<void>;
950
+ _startAsyncAutorouting(): void;
944
951
  doInitialPcbTraceRender(): void;
945
952
  updatePcbTraceRender(): void;
946
953
  _updatePcbTraceRenderFromSimpleRouteJson(): void;
package/dist/index.js CHANGED
@@ -105,6 +105,7 @@ var Renderable = class {
105
105
  _renderId;
106
106
  _currentRenderPhase = null;
107
107
  _asyncEffects = [];
108
+ parent = null;
108
109
  constructor(props) {
109
110
  this._renderId = `${globalRenderCounter++}`;
110
111
  this.children = [];
@@ -122,6 +123,9 @@ var Renderable = class {
122
123
  for (let i = phaseIndex + 1; i < orderedRenderPhases.length; i++) {
123
124
  this.renderPhaseStates[orderedRenderPhases[i]].dirty = true;
124
125
  }
126
+ if (this.parent?._markDirty) {
127
+ this.parent._markDirty(phase);
128
+ }
125
129
  }
126
130
  _queueAsyncEffect(effectName, effect) {
127
131
  const asyncEffect = {
@@ -3133,6 +3137,7 @@ var NormalComponent = class extends PrimitiveComponent {
3133
3137
  if (this.root?.pcbDisabled) return;
3134
3138
  const { db } = this.root;
3135
3139
  const { _parsedProps: props } = this;
3140
+ const subcircuit = this.getSubcircuit();
3136
3141
  const pcb_component = db.pcb_component.insert({
3137
3142
  center: this._getGlobalPcbPositionBeforeLayout(),
3138
3143
  // width/height are computed in the PcbComponentSizeCalculation phase
@@ -3140,7 +3145,8 @@ var NormalComponent = class extends PrimitiveComponent {
3140
3145
  height: 0,
3141
3146
  layer: props.layer ?? "top",
3142
3147
  rotation: props.pcbRotation ?? 0,
3143
- source_component_id: this.source_component_id
3148
+ source_component_id: this.source_component_id,
3149
+ subcircuit_id: subcircuit.subcircuit_id ?? void 0
3144
3150
  });
3145
3151
  if (!props.footprint && !this.isGroup) {
3146
3152
  const footprint_error = db.pcb_missing_footprint_error.insert({
@@ -3620,6 +3626,7 @@ var TraceHint = class extends PrimitiveComponent {
3620
3626
  var Group = class extends NormalComponent {
3621
3627
  pcb_group_id = null;
3622
3628
  subcircuit_id = null;
3629
+ _hasStartedAsyncAutorouting = false;
3623
3630
  _asyncAutoroutingResult = null;
3624
3631
  get config() {
3625
3632
  return {
@@ -3639,6 +3646,15 @@ var Group = class extends NormalComponent {
3639
3646
  subcircuit_id: this.subcircuit_id
3640
3647
  });
3641
3648
  }
3649
+ doInitialSourceParentAttachment() {
3650
+ const { db } = this.root;
3651
+ if (!this.isSubcircuit) return;
3652
+ const parent_subcircuit_id = this.parent?.getSubcircuit?.()?.subcircuit_id;
3653
+ if (!parent_subcircuit_id) return;
3654
+ db.source_group.update(this.source_group_id, {
3655
+ parent_subcircuit_id
3656
+ });
3657
+ }
3642
3658
  doInitialPcbComponentRender() {
3643
3659
  if (this.root?.pcbDisabled) return;
3644
3660
  const { db } = this.root;
@@ -3709,63 +3725,98 @@ var Group = class extends NormalComponent {
3709
3725
  });
3710
3726
  }
3711
3727
  }
3712
- doInitialPcbTraceRender() {
3713
- if (this.root?.pcbDisabled) return;
3714
- if (this._shouldUseTraceByTraceRouting()) return;
3715
- const serverUrl = this.props.autorouter?.serverUrl ?? "https://registry-api.tscircuit.com";
3716
- const serverMode = this.props.autorouter?.serverMode ?? "job";
3717
- const debug4 = Debug5("tscircuit:core:autorouting");
3728
+ _areChildSubcircuitsRouted() {
3729
+ const subcircuitChildren = this.selectAll("group").filter(
3730
+ (g) => g.isSubcircuit
3731
+ );
3732
+ for (const subcircuitChild of subcircuitChildren) {
3733
+ if (subcircuitChild._shouldRouteAsync() && !subcircuitChild._asyncAutoroutingResult) {
3734
+ return false;
3735
+ }
3736
+ }
3737
+ return true;
3738
+ }
3739
+ _shouldRouteAsync() {
3740
+ const props = this._parsedProps;
3741
+ if (props.autorouter === "auto-local") return true;
3742
+ if (props.autorouter === "auto-cloud") return true;
3743
+ if (props.autorouter === "sequential-trace") return false;
3744
+ if (typeof props.autorouter === "object") return true;
3745
+ return false;
3746
+ }
3747
+ async _runEffectMakeHttpAutoroutingRequest() {
3748
+ const debug4 = Debug5("tscircuit:core:_runEffectMakeHttpAutoroutingRequest");
3749
+ const props = this._parsedProps;
3750
+ const serverUrl = props.autorouter?.serverUrl ?? "https://registry-api.tscircuit.com";
3751
+ const serverMode = props.autorouter?.serverMode ?? "job";
3718
3752
  const fetchWithDebug = (url, options) => {
3719
3753
  debug4("fetching", url);
3720
3754
  return fetch(url, options);
3721
3755
  };
3722
- this._queueAsyncEffect("make-http-autorouting-request", async () => {
3723
- if (serverMode === "solve-endpoint") {
3724
- if (this.props.autorouter?.inputFormat === "simplified") {
3725
- const { autorouting_result: autorouting_result2 } = await fetchWithDebug(
3726
- `${serverUrl}/autorouting/solve`,
3727
- {
3728
- method: "POST",
3729
- body: JSON.stringify({
3730
- input_simple_route_json: this._getSimpleRouteJsonFromPcbTraces()
3731
- }),
3732
- headers: { "Content-Type": "application/json" }
3733
- }
3734
- ).then((r) => r.json());
3735
- this._asyncAutoroutingResult = autorouting_result2;
3736
- this._markDirty("PcbTraceRender");
3737
- return;
3738
- }
3739
- const { autorouting_result } = await fetchWithDebug(
3756
+ const pcbAndSourceCircuitJson = this.root.db.toArray().filter(
3757
+ (element) => {
3758
+ return element.type.startsWith("source_") || element.type.startsWith("pcb_");
3759
+ }
3760
+ );
3761
+ if (serverMode === "solve-endpoint") {
3762
+ if (this.props.autorouter?.inputFormat === "simplified") {
3763
+ const { autorouting_result: autorouting_result2 } = await fetchWithDebug(
3740
3764
  `${serverUrl}/autorouting/solve`,
3741
3765
  {
3742
3766
  method: "POST",
3743
3767
  body: JSON.stringify({
3744
- input_circuit_json: this.root.db.toArray()
3768
+ input_simple_route_json: this._getSimpleRouteJsonFromPcbTraces()
3745
3769
  }),
3746
3770
  headers: { "Content-Type": "application/json" }
3747
3771
  }
3748
3772
  ).then((r) => r.json());
3749
- this._asyncAutoroutingResult = autorouting_result;
3773
+ this._asyncAutoroutingResult = autorouting_result2;
3750
3774
  this._markDirty("PcbTraceRender");
3751
3775
  return;
3752
3776
  }
3753
- const { autorouting_job } = await fetchWithDebug(
3754
- `${serverUrl}/autorouting/jobs/create`,
3777
+ const { autorouting_result } = await fetchWithDebug(
3778
+ `${serverUrl}/autorouting/solve`,
3779
+ {
3780
+ method: "POST",
3781
+ body: JSON.stringify({
3782
+ input_circuit_json: pcbAndSourceCircuitJson,
3783
+ subcircuit_id: this.subcircuit_id
3784
+ }),
3785
+ headers: { "Content-Type": "application/json" }
3786
+ }
3787
+ ).then((r) => r.json());
3788
+ this._asyncAutoroutingResult = autorouting_result;
3789
+ this._markDirty("PcbTraceRender");
3790
+ return;
3791
+ }
3792
+ const { autorouting_job } = await fetchWithDebug(
3793
+ `${serverUrl}/autorouting/jobs/create`,
3794
+ {
3795
+ method: "POST",
3796
+ body: JSON.stringify({
3797
+ input_circuit_json: pcbAndSourceCircuitJson,
3798
+ provider: "freerouting",
3799
+ autostart: true,
3800
+ display_name: this.root?.name,
3801
+ subcircuit_id: this.subcircuit_id
3802
+ }),
3803
+ headers: { "Content-Type": "application/json" }
3804
+ }
3805
+ ).then((r) => r.json());
3806
+ while (true) {
3807
+ const { autorouting_job: job } = await fetchWithDebug(
3808
+ `${serverUrl}/autorouting/jobs/get`,
3755
3809
  {
3756
3810
  method: "POST",
3757
3811
  body: JSON.stringify({
3758
- input_circuit_json: this.root.db.toArray(),
3759
- provider: "freerouting",
3760
- autostart: true,
3761
- display_name: this.root?.name
3812
+ autorouting_job_id: autorouting_job.autorouting_job_id
3762
3813
  }),
3763
3814
  headers: { "Content-Type": "application/json" }
3764
3815
  }
3765
3816
  ).then((r) => r.json());
3766
- while (true) {
3767
- const { autorouting_job: job } = await fetchWithDebug(
3768
- `${serverUrl}/autorouting/jobs/get`,
3817
+ if (job.is_finished) {
3818
+ const { autorouting_job_output } = await fetchWithDebug(
3819
+ `${serverUrl}/autorouting/jobs/get_output`,
3769
3820
  {
3770
3821
  method: "POST",
3771
3822
  body: JSON.stringify({
@@ -3774,33 +3825,51 @@ var Group = class extends NormalComponent {
3774
3825
  headers: { "Content-Type": "application/json" }
3775
3826
  }
3776
3827
  ).then((r) => r.json());
3777
- if (job.is_finished) {
3778
- const { autorouting_job_output } = await fetchWithDebug(
3779
- `${serverUrl}/autorouting/jobs/get_output`,
3780
- {
3781
- method: "POST",
3782
- body: JSON.stringify({
3783
- autorouting_job_id: autorouting_job.autorouting_job_id
3784
- }),
3785
- headers: { "Content-Type": "application/json" }
3786
- }
3787
- ).then((r) => r.json());
3788
- this._asyncAutoroutingResult = {
3789
- output_pcb_traces: autorouting_job_output.output_pcb_traces
3790
- };
3791
- this._markDirty("PcbTraceRender");
3792
- break;
3793
- }
3794
- if (job.has_error) {
3795
- throw new Error(
3796
- `Autorouting job failed: ${JSON.stringify(job.error)}`
3797
- );
3798
- }
3799
- await new Promise((resolve) => setTimeout(resolve, 100));
3828
+ this._asyncAutoroutingResult = {
3829
+ output_pcb_traces: autorouting_job_output.output_pcb_traces
3830
+ };
3831
+ this._markDirty("PcbTraceRender");
3832
+ break;
3800
3833
  }
3801
- });
3834
+ if (job.has_error) {
3835
+ throw new Error(`Autorouting job failed: ${JSON.stringify(job.error)}`);
3836
+ }
3837
+ await new Promise((resolve) => setTimeout(resolve, 100));
3838
+ }
3839
+ }
3840
+ _startAsyncAutorouting() {
3841
+ this._hasStartedAsyncAutorouting = true;
3842
+ this._queueAsyncEffect(
3843
+ "make-http-autorouting-request",
3844
+ async () => this._runEffectMakeHttpAutoroutingRequest()
3845
+ );
3846
+ }
3847
+ doInitialPcbTraceRender() {
3848
+ const debug4 = Debug5("tscircuit:core:doInitialPcbTraceRender");
3849
+ if (this.root?.pcbDisabled) return;
3850
+ if (this._shouldUseTraceByTraceRouting()) return;
3851
+ if (!this._areChildSubcircuitsRouted()) {
3852
+ debug4(
3853
+ `[${this.getString()}] child subcircuits are not routed, skipping async autorouting until subcircuits routed`
3854
+ );
3855
+ return;
3856
+ }
3857
+ debug4(
3858
+ `[${this.getString()}] no child subcircuits to wait for, initiating async routing`
3859
+ );
3860
+ this._startAsyncAutorouting();
3802
3861
  }
3803
3862
  updatePcbTraceRender() {
3863
+ const debug4 = Debug5("tscircuit:core:updatePcbTraceRender");
3864
+ if (this._shouldRouteAsync() && !this._hasStartedAsyncAutorouting) {
3865
+ if (this._areChildSubcircuitsRouted()) {
3866
+ debug4(
3867
+ `[${this.getString()}] child subcircuits are now routed, starting async autorouting`
3868
+ );
3869
+ this._startAsyncAutorouting();
3870
+ }
3871
+ return;
3872
+ }
3804
3873
  if (!this._asyncAutoroutingResult) return;
3805
3874
  if (this._shouldUseTraceByTraceRouting()) return;
3806
3875
  const { db } = this.root;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.276",
4
+ "version": "0.0.278",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
@@ -57,7 +57,7 @@
57
57
  "@tscircuit/props": "^0.0.130",
58
58
  "@tscircuit/schematic-autolayout": "^0.0.6",
59
59
  "@tscircuit/soup-util": "^0.0.41",
60
- "circuit-json": "^0.0.133",
60
+ "circuit-json": "^0.0.134",
61
61
  "circuit-json-to-connectivity-map": "^0.0.17",
62
62
  "format-si-unit": "^0.0.2",
63
63
  "nanoid": "^5.0.7",