Skip to content

Conversation

@ayush0-7
Copy link

@ayush0-7 ayush0-7 commented Oct 27, 2025

Fixes #661

Describe the changes you have made in this PR -

  • Converted backupCircuit.js file to TypeScript (backupCircuit.ts)

  • Added proper type definitions for Scope and related functions

  • Improved code readability and type safety

  • No functional logic has been changed — only migration from JS → TS

Summary by CodeRabbit

  • Refactor
    • Upgraded the circuit backup module to TypeScript, improving type safety and code reliability while maintaining existing backup functionality for circuit state serialization, scheduling, and history tracking.

@netlify
Copy link

netlify bot commented Oct 27, 2025

Deploy Preview for circuitverse ready!

Name Link
🔨 Latest commit 9c38656
🔍 Latest deploy log https://app.netlify.com/projects/circuitverse/deploys/68ff7301c04918000820ea12
😎 Deploy Preview https://deploy-preview-672--circuitverse.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 41 (🔴 down 4 from production)
Accessibility: 73 (no change from production)
Best Practices: 92 (no change from production)
SEO: 82 (no change from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 27, 2025

Walkthrough

Converts the backup circuit module from JavaScript to TypeScript by migrating backupCircuit.js to backupCircuit.ts. Adds type annotations for scope parameters, return types, and internal type definitions while preserving the existing backup serialization and scheduling logic.

Changes

Cohort / File(s) Summary
TypeScript Migration
src/simulator/src/data/backupCircuit.js (removed), src/simulator/src/data/backupCircuit.ts (added)
Replaces JavaScript backup module with TypeScript version. Adds type safety via Scope, NodeLike, and SubCircuitLike type definitions. Migrates checkIfBackup(), backUp(), and scheduleBackup() functions with proper type annotations. Preserves backup serialization logic including subcircuit connection handling and history management.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

  • Verify type definitions (Scope, NodeLike, SubCircuitLike) are correctly structured and match actual usage patterns
  • Confirm globalScope default parameter typing is consistent with function signatures
  • Validate that backup serialization logic remains functionally identical to the JavaScript version
  • Check that the internal extract() helper properly serializes node objects

Possibly related PRs

  • JS to TS : simulator/src/data/undo.ts #421: Consumes the backup data and functions produced by this module to restore circuit state during undo operations; changes interact directly with the same backup serialization pipeline.

Suggested reviewers

  • Arnabdaz

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "Convert backupCircuit.js to TypeScript" is concise, clear, and accurately describes the primary change in the changeset. It directly reflects the main objective of migrating a JavaScript file to TypeScript with proper type definitions. A reviewer scanning the commit history would immediately understand that this PR involves converting a backup circuit module to TypeScript without changing its core logic.
Linked Issues Check ✅ Passed The PR successfully addresses the requirements of linked issue #661. It converts a single JavaScript file (backupCircuit.js) to TypeScript (backupCircuit.ts) while maintaining the same three exported functions (checkIfBackup, backUp, scheduleBackup) and their underlying logic. The changes focus on adding type safety through TypeScript type definitions (Scope, NodeLike, SubCircuitLike) rather than modifying the functional behavior, which aligns with the issue's requirement to "not change existing logic; only change interfaces, data types, improve type safety."
Out of Scope Changes Check ✅ Passed The PR remains within scope as it is limited to converting a single file from JavaScript to TypeScript as required by issue #661. The changes are focused solely on the backupCircuit module, transitioning from backupCircuit.js to backupCircuit.ts with added type definitions. No modifications to other files or functionality beyond the TypeScript migration are evident in the changeset, confirming that all changes are directly related to the stated objectives.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0921d26 and 9c38656.

📒 Files selected for processing (2)
  • src/simulator/src/data/backupCircuit.js (0 hunks)
  • src/simulator/src/data/backupCircuit.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • src/simulator/src/data/backupCircuit.js
🧰 Additional context used
🧬 Code graph analysis (1)
src/simulator/src/data/backupCircuit.ts (4)
src/simulator/src/circuit.ts (1)
  • Scope (294-515)
src/simulator/src/restrictedElementDiv.js (1)
  • globalScope (4-4)
src/simulator/src/metadata.ts (2)
  • updateOrder (67-72)
  • moduleList (66-66)
src/simulator/src/data/project.ts (1)
  • projectSavedSet (85-87)
🔇 Additional comments (4)
src/simulator/src/data/backupCircuit.ts (4)

1-4: LGTM!

The imports are correct and the eslint directive is appropriate for this module.


42-44: LGTM!

The helper function is simple and correctly typed.


52-58: LGTM!

The function correctly uses optional chaining to safely check for the existence of backup data.


108-122: LGTM!

The function correctly prevents duplicate backups and updates the timestamp. The logic is sound.

Comment on lines +19 to +33
interface Scope {
SubCircuit: SubCircuitLike[];
allNodes: NodeLike[];
nodes: NodeLike[];
layout: Record<string, any>;
verilogMetadata: Record<string, any>;
testbenchData: Record<string, any>;
id: number;
name: string;
restrictedCircuitElementsUsed: Record<string, any>;
backups: string[];
history: string[];
timeStamp: number;
[key: string]: any; // For dynamic moduleList entries
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Fix type mismatches with the actual Scope class.

The Scope interface has several type inconsistencies with the actual Scope class defined in circuit.ts:

  1. Line 26: id should be number | string (not just number)
  2. Line 28: restrictedCircuitElementsUsed should be any[] (not Record<string, any>)
  3. Lines 20-22: SubCircuit, allNodes, and nodes should be optional properties marked with ?, as they are in the actual Scope class
  4. Line 25: testbenchData is not defined in the Scope class from circuit.ts

Apply this diff to align the interface with the actual Scope class:

 interface Scope {
-  SubCircuit: SubCircuitLike[];
-  allNodes: NodeLike[];
-  nodes: NodeLike[];
+  SubCircuit?: SubCircuitLike[];
+  allNodes?: NodeLike[];
+  nodes?: NodeLike[];
   layout: Record<string, any>;
   verilogMetadata: Record<string, any>;
-  testbenchData: Record<string, any>;
-  id: number;
+  testbenchData?: Record<string, any>;
+  id: number | string;
   name: string;
-  restrictedCircuitElementsUsed: Record<string, any>;
+  restrictedCircuitElementsUsed: any[];
   backups: string[];
   history: string[];
   timeStamp: number;
   [key: string]: any;
 }

Please verify whether testbenchData exists on the Scope class or is dynamically added. Run this script to check:


🏁 Script executed:

#!/bin/bash
# Search for testbenchData usage in the Scope class definition
rg -nP --type=ts -C5 'testbenchData' 'src/simulator/src/circuit.ts'

# Also check where testbenchData is assigned or accessed
rg -nP --type=ts -A3 -B3 '\.testbenchData\s*[=:]'

Length of output: 5108


🏁 Script executed:

#!/bin/bash
# Find the actual Scope class/type definition in circuit.ts
rg -nP --type=ts -A20 'class Scope|interface Scope|type Scope' 'src/simulator/src/circuit.ts' | head -60

# Search for restrictedCircuitElementsUsed to see its actual type
rg -nP --type=ts -B2 -A2 'restrictedCircuitElementsUsed\s*[:=]' 'src/simulator/src/circuit.ts'

# Check id property definition
rg -nP --type=ts -B2 -A2 'this\.id\s*[:=]|id\s*[:=]\s*[0-9]|id\s*[:=]\s*string' 'src/simulator/src/circuit.ts' | head -40

Length of output: 2101


🏁 Script executed:

#!/bin/bash
# Check if SubCircuit is used elsewhere or if it's CircuitElement
rg -nP --type=ts -B3 -A3 'SubCircuit' 'src/simulator/src/data/backupCircuit.ts'

# Check how the Scope interface is actually used in backupCircuit.ts
rg -nP --type=ts -B5 -A5 'interface Scope' 'src/simulator/src/data/backupCircuit.ts'

# See the full context of backupCircuit.ts
cat 'src/simulator/src/data/backupCircuit.ts' | head -100

Length of output: 3424


Fix critical type mismatches and incompatibility with the actual Scope class.

The Scope interface has several serious type inconsistencies with the actual Scope class in circuit.ts:

  1. Line 20: SubCircuit property doesn't exist in the Scope class—it has CircuitElement instead. The backUp() function (lines 67, 95) will fail at runtime trying to access scope.SubCircuit.
  2. Line 26: id should be number | string (not just number)
  3. Line 28: restrictedCircuitElementsUsed should be any[] (not Record<string, any>)
  4. Lines 21–22: allNodes and nodes should be optional (marked with ?)

The testbenchData property (line 25) is intentionally included and actively used in the backup logic (line 73, 85), so it should remain.

Apply this diff:

 interface Scope {
-  SubCircuit: SubCircuitLike[];
+  CircuitElement?: SubCircuitLike[];
   allNodes?: NodeLike[];
   nodes?: NodeLike[];
   layout: Record<string, any>;
   verilogMetadata: Record<string, any>;
   testbenchData: Record<string, any>;
-  id: number;
+  id: number | string;
   name: string;
-  restrictedCircuitElementsUsed: Record<string, any>;
+  restrictedCircuitElementsUsed: any[];
   backups: string[];
   history: string[];
   timeStamp: number;
   [key: string]: any;
 }

Then update the backUp() function loops (lines 67, 95) to iterate over scope.CircuitElement instead of scope.SubCircuit.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/simulator/src/data/backupCircuit.ts around lines 19 to 33, the Scope
interface does not match the real Scope class: change SubCircuit to
CircuitElement: SubCircuit: SubCircuitLike[] -> remove and add CircuitElement?:
CircuitElementLike[] (or CircuitElement: CircuitElementLike[] if required by
class), make allNodes? and nodes? optional (add ?), change id: number -> id:
number | string, change restrictedCircuitElementsUsed: Record<string, any> ->
restrictedCircuitElementsUsed: any[], keep testbenchData as-is. Then update the
backUp() function loops at lines ~67 and ~95 to iterate over
scope.CircuitElement instead of scope.SubCircuit so runtime access matches the
actual class.

Comment on lines +67 to +69
for (const sub of scope.SubCircuit) {
sub.removeConnections();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Add guard for optional SubCircuit property.

Since SubCircuit is an optional property on the Scope class, attempting to iterate over it without checking if it exists will cause a runtime error.

Apply this diff to add a safe guard:

   // Disconnect subcircuits before saving
-  for (const sub of scope.SubCircuit) {
-    sub.removeConnections();
+  if (scope.SubCircuit) {
+    for (const sub of scope.SubCircuit) {
+      sub.removeConnections();
+    }
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for (const sub of scope.SubCircuit) {
sub.removeConnections();
}
// Disconnect subcircuits before saving
if (scope.SubCircuit) {
for (const sub of scope.SubCircuit) {
sub.removeConnections();
}
}
🤖 Prompt for AI Agents
In src/simulator/src/data/backupCircuit.ts around lines 67 to 69, the code
iterates over scope.SubCircuit which is optional on Scope; add a guard to check
that scope.SubCircuit exists and is iterable before looping (e.g., if
(scope.SubCircuit && Array.isArray(scope.SubCircuit)) or if
(scope.SubCircuit?.length) ), and only then call sub.removeConnections() for
each element; keep the existing behavior otherwise.

Comment on lines +71 to +85
const data: Record<string, any> = {
layout: scope.layout,
verilogMetadata: scope.verilogMetadata,
allNodes: scope.allNodes.map(extract),
testbenchData: scope.testbenchData,
id: scope.id,
name: scope.name,
};

// Save all module objects dynamically
for (const moduleName of moduleList) {
if (scope[moduleName]?.length) {
data[moduleName] = scope[moduleName].map(extract);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Add guards for optional properties.

The code accesses optional properties without checking if they exist:

  1. Line 74: allNodes is optional and could be undefined
  2. Line 75: testbenchData might not exist on the Scope

Apply this diff to add safe guards:

   const data: Record<string, any> = {
     layout: scope.layout,
     verilogMetadata: scope.verilogMetadata,
-    allNodes: scope.allNodes.map(extract),
-    testbenchData: scope.testbenchData,
+    allNodes: scope.allNodes?.map(extract) || [],
+    testbenchData: scope.testbenchData || {},
     id: scope.id,
     name: scope.name,
   };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const data: Record<string, any> = {
layout: scope.layout,
verilogMetadata: scope.verilogMetadata,
allNodes: scope.allNodes.map(extract),
testbenchData: scope.testbenchData,
id: scope.id,
name: scope.name,
};
// Save all module objects dynamically
for (const moduleName of moduleList) {
if (scope[moduleName]?.length) {
data[moduleName] = scope[moduleName].map(extract);
}
}
const data: Record<string, any> = {
layout: scope.layout,
verilogMetadata: scope.verilogMetadata,
allNodes: scope.allNodes?.map(extract) || [],
testbenchData: scope.testbenchData || {},
id: scope.id,
name: scope.name,
};
// Save all module objects dynamically
for (const moduleName of moduleList) {
if (scope[moduleName]?.length) {
data[moduleName] = scope[moduleName].map(extract);
}
}
🤖 Prompt for AI Agents
In src/simulator/src/data/backupCircuit.ts around lines 71 to 85, the code maps
scope.allNodes and reads scope.testbenchData without guarding for undefined;
update the construction of data so optional properties are safely handled—use
default empty array when mapping (e.g., treat allNodes as an empty array if
undefined) and set testbenchData to a safe default (null/undefined or an empty
object) when absent; keep the existing dynamic module loop but ensure each
scope[moduleName] access is also guarded (only map when it exists and is an
array).

Comment on lines +90 to +92
data.nodes = scope.nodes.map(node =>
scope.allNodes.indexOf(node)
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Add guards for optional nodes property.

The nodes property is optional on the Scope class. Attempting to map over it without checking will cause a runtime error.

Apply this diff:

   // Save intermediate nodes (wire nodes)
-  data.nodes = scope.nodes.map(node =>
-    scope.allNodes.indexOf(node)
-  );
+  data.nodes = scope.nodes?.map(node =>
+    scope.allNodes?.indexOf(node) ?? -1
+  ) || [];
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
data.nodes = scope.nodes.map(node =>
scope.allNodes.indexOf(node)
);
data.nodes = scope.nodes?.map(node =>
scope.allNodes?.indexOf(node) ?? -1
) || [];
🤖 Prompt for AI Agents
In src/simulator/src/data/backupCircuit.ts around lines 90 to 92, the code maps
scope.nodes without guarding for scope.nodes being optional; update this to
first check whether scope.nodes is present before mapping (e.g., set data.nodes
to an empty array or undefined when scope.nodes is missing), and only call
scope.nodes.map when scope.nodes is defined to avoid runtime errors.

Comment on lines +95 to +97
for (const sub of scope.SubCircuit) {
sub.makeConnections();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Add guard for optional SubCircuit property.

Same issue as the disconnection code—need to check if SubCircuit exists before iterating.

Apply this diff:

   // Reconnect subcircuits after saving
-  for (const sub of scope.SubCircuit) {
-    sub.makeConnections();
+  if (scope.SubCircuit) {
+    for (const sub of scope.SubCircuit) {
+      sub.makeConnections();
+    }
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for (const sub of scope.SubCircuit) {
sub.makeConnections();
}
// Reconnect subcircuits after saving
if (scope.SubCircuit) {
for (const sub of scope.SubCircuit) {
sub.makeConnections();
}
}
🤖 Prompt for AI Agents
In src/simulator/src/data/backupCircuit.ts around lines 95 to 97, the loop
assumes scope.SubCircuit always exists; add a guard to check that SubCircuit is
defined (and is iterable) before iterating and calling sub.makeConnections(),
e.g. return early or wrap the for loop in an if (scope.SubCircuit) / if
(Array.isArray(scope.SubCircuit)) check so you don't iterate over undefined.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: Javascript to Typescript conversion in the src folder

2 participants