Skip to content

Conversation

@ggfevans
Copy link
Collaborator

@ggfevans ggfevans commented Jan 1, 2026

Summary

  • Define Cable interface with A/B side terminations for network connectivity tracking
  • Add NetBox-compatible CableType, CableStatus, and LengthUnit enums
  • Create CableSchema with Zod validation for all cable properties
  • Add cables array to Layout type with YAML serialization support
  • Implement cable store with full CRUD operations and validation

Files Changed

  • src/lib/types/index.ts - Cable, CableType, CableStatus, LengthUnit types
  • src/lib/schemas/index.ts - CableSchema, CableTypeSchema, CableStatusSchema, LengthUnitSchema
  • src/lib/utils/yaml.ts - Cable serialization with field ordering
  • src/lib/stores/cables.svelte.ts - Cable store with CRUD and validation
  • src/tests/cables.test.ts - 42 tests covering schema and store

Test Plan

  • Schema validates all cable type enums
  • Schema validates hex color format for cable color
  • Schema validates positive length values
  • Validation rejects non-existent devices
  • Validation rejects non-existent interfaces (when device type defines interfaces)
  • Validation rejects duplicate cables (same endpoints)
  • Validation rejects duplicate cables (reversed A/B endpoints)
  • Validation rejects self-referential cables (same interface to itself)
  • CRUD operations (add, update, remove) work correctly
  • Lint, build, and tests pass

Closes #261

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added cable connection management: define and track physical cables between device interfaces with type, colour, label, length/unit, and status.
    • Layout import/export now preserves and orders cable data in YAML.
    • Store enhancements: full CRUD for cables, validation (endpoints, duplicates, self-connections), and raw actions to mutate cables without affecting undo/dirty tracking.
  • Tests

    • Added comprehensive tests for schemas, validation rules, and store operations.

✏️ Tip: You can customize this high-level summary in your review settings.

Add data model and schema for cable connections between device interfaces,
supporting network visualization and connectivity tracking.

New types and schemas:
- Cable interface with A/B side terminations
- CableType enum (cat5e-cat8, DAC, fiber OM3/OM4/OS2, AOC, power, serial)
- CableStatus enum (connected, planned, decommissioning)
- LengthUnit enum (m, cm, ft, in)
- CableSchema with Zod validation

Cable store (cables.svelte.ts):
- CRUD operations: addCable, updateCable, removeCable
- Query helpers: getCableById, getCablesByDevice, getCablesByInterface
- Validation: device existence, interface existence, duplicate detection
- Auto-cleanup: removeCablesByDevice for cascading deletes

Layout integration:
- cables array added to Layout type
- LayoutSchema updated with cables validation
- YAML serialization with proper field ordering

Test coverage (42 tests):
- Schema validation for all enums and Cable structure
- Validation rules for endpoints and duplicates
- Full CRUD operation testing
- Edge cases for self-referential and reverse connections

Closes #261

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Jan 1, 2026

📝 Walkthrough

Walkthrough

Adds a NetBox-compatible cable data model and Zod schemas, YAML serialization support for cables, a Svelte cable store with validation and CRUD (including raw undo/redo hooks), layout-store raw cable mutators, and comprehensive tests for schema, validation, and store behavior.

Changes

Cohort / File(s) Summary
Schemas
src/lib/schemas/index.ts
Adds CableTypeSchema, CableStatusSchema, LengthUnitSchema, and CableSchema (validations: hex color, positive length with unit dependency). Extends LayoutSchemaBase with optional cables array and exports inferred cable types.
Types
src/lib/types/index.ts
Introduces CableType, CableStatus, LengthUnit unions and Cable interface; adds cables?: Cable[] to Layout. (Note: file contains a duplicated Cable interface block.)
Cable store
src/lib/stores/cables.svelte.ts
New store exposing getCableStore() with CRUD, retrieval helpers, raw ops for undo/redo, and validateCable() enforcing device/interface existence, self-connection, and duplicate (including reversed) detection; mutations mark layout dirty; returns structured validation/results.
Layout raw mutators
src/lib/stores/layout.svelte.ts
Adds raw mutators addCableRaw, updateCableRaw, removeCableRaw, removeCablesRaw and exposes them from getLayoutStore(); operate without dirty/undo tracking.
YAML utilities
src/lib/utils/yaml.ts
Adds orderCableFields(cable) to canonicalize field order; serializeLayoutToYaml() now emits cables when present; toRuntimeLayout() preserves parsed cables.
Tests
src/tests/cables.test.ts
New tests covering schema enums, CableSchema, validation against mock layout (existence, duplicates, reversed duplicates, self-connect), and store CRUD/filtering/dirty-state behavior using fixture layouts.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant UI
    participant Store as Cable Store
    participant Schema as Zod Schema
    participant Validator as validateCable()
    participant Layout as Layout Store

    rect rgb(40,42,54)
    Note over User,UI: User submits cable input
    User->>UI: submit cable payload
    UI->>Store: addCable(input)
    end

    Store->>Schema: parse & basic validation
    Schema-->>Store: parsed cable or errors
    alt Schema OK
        Store->>Validator: validateCable(cable, layout)
        Validator->>Layout: read devices & device types
        Layout-->>Validator: device/interface data
        Validator-->>Store: validation result
        alt Validation passes
            Store->>Layout: addCableRaw(cable)
            Layout-->>Store: layout updated
            Store->>UI: success (marks layout dirty)
        else Validation fails
            Store->>UI: error details
        end
    else Schema errors
        Store->>UI: schema error details
    end
Loading
sequenceDiagram
    participant CLI
    participant YAML as serializeLayoutToYaml()
    participant Order as orderCableFields()
    participant Disk

    CLI->>YAML: serializeLayoutToYaml(layout)
    YAML->>Order: orderCableFields() per cable
    Order-->>YAML: ordered objects
    YAML->>Disk: write YAML with `cables` section
    Disk-->>CLI: persisted file
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

In moonlit racks the new cords weave, with hex and length aligned,
Validators whisper, endpoints cleave — each cable well-defined,
Raw tricks slip past the watchers' sight, undo waits in the gloom,
Tests sing softly, passing bright — connectivity finds room 🦇

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 PR title clearly and concisely describes the main change: implementing cable data model and schema, which aligns perfectly with the changeset across types, schemas, stores, and utilities.
Linked Issues check ✅ Passed The PR fulfills all coding objectives from issue #261: Cable interface definition [#261], Zod schemas with enums [#261], Layout extension with cables array [#261], YAML serialization support [#261], cable store with CRUD and validation [#261], and comprehensive test coverage [#261].
Out of Scope Changes check ✅ Passed All changes remain focused on cable data model implementation: type definitions, schema validation, store operations, YAML serialization, and tests. No unrelated changes detected.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 07b03a9 and 1c375e4.

📒 Files selected for processing (2)
  • src/lib/stores/cables.svelte.ts
  • src/tests/cables.test.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,svelte}

📄 CodeRabbit inference engine (CLAUDE.md)

Use TypeScript strict mode

Files:

  • src/lib/stores/cables.svelte.ts
  • src/tests/cables.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

NetBox-compatible field naming: use snake_case for field names (e.g., u_height, device_type, form_factor) in data models

Files:

  • src/lib/stores/cables.svelte.ts
  • src/tests/cables.test.ts
🧬 Code graph analysis (1)
src/lib/stores/cables.svelte.ts (2)
src/lib/types/index.ts (4)
  • CableType (158-177)
  • LengthUnit (187-187)
  • CableStatus (182-182)
  • Cable (299-328)
src/lib/stores/layout.svelte.ts (1)
  • getLayoutStore (103-226)
🔇 Additional comments (10)
src/lib/stores/cables.svelte.ts (5)

6-25: Excellent type definitions and proper field naming, my friend!

Ze imports are clean, and ze CreateCableInput interface correctly follows ze NetBox-compatible snake_case naming convention for all fields (a_device_id, a_interface, b_device_id, b_interface, length_unit). Zis vill ensure compatibility vith ze rest of ze codebase.


35-153: Ze validation logic is thorough and all past concerns have been addressed!

Ze comprehensive JSDoc (lines 38-40) now clearly explains zat zis function is exported for testing purposes, and application code should use ze store's validateCable method. Very good documentation, my nocturnal friend!

Ze debug warnings (lines 89-91 and 111-113) vhen device types lack explicit interface definitions are a nice touch—users vill appreciate ze visibility during development vhen cables reference interfaces on device types vizout explicit templates.

Ze duplicate detection logic (lines 117-135) correctly handles both forward and reverse endpoints, and ze self-referential check (lines 141-147) prevents nonsensical configurations. Zis is solid validation logic!


204-272: Ze CRUD operations are vell-implemented vith proper validation and error handling!

Ze addCable function (lines 204-235) correctly validates before creation, uses generateId() to ensure unique identifiers, and properly marks ze layout dirty after mutation. Ze structured return type { cable: Cable; errors: null } | { cable: null; errors: string[] } provides excellent type safety for callers.

Ze updateCable function (lines 241-272) shows good defensive programming by only validating vhen endpoints are being changed (lines 254-265), avoiding unnecessary validation overhead for non-structural updates like label or color changes. Zis is smart optimization!

Ze non-null assertion at line 251 is safe because ve've already verified existingIndex !== -1 at line 247, so cables[existingIndex] is guaranteed to exist.


293-309: Ze batch removal optimization is excellent, my friend!

I see ze performance concern from ze previous review has been beautifully addressed! Ze removeCablesByDevice function now uses removeCablesRaw (line 304) vith a batch operation instead of calling removal in a loop. Zis avoids rebuilding ze layout multiple times and vill perform much better for devices vith many cables.

Ze eslint-disable comment (lines 301-302) is exemplary defensive coding—it clearly explains vy a plain Set is intentional here (immediate filtering, not reactive state). Zis prevents future confusion and shows careful consideration of ze Svelte reactivity model.


339-367: Ze store API design is clean and vell-organized!

Ze returned object provides a beautifully structured API vith logical grouping:

  • Getters for retrieval operations
  • Full CRUD operations vith validation
  • Raw operations explicitly marked for undo/redo usage
  • A convenient validateCable wrapper (lines 360-365) zat automatically provides ze current cables array

Ze wrapper method at lines 360-365 is particularly nice—it simplifies ze caller's interface by automatically passing getCables(), vhile ze standalone exported function (line 47) accepts cables as a parameter for flexible testing. Zis dual approach gives ze best of both vorlds!

src/tests/cables.test.ts (5)

18-72: Excellent test fixtures vith proper field naming, my friend!

Ze helper functions create vell-structured test data zat follows ze NetBox-compatible snake_case convention throughout: u_height, device_type, desc_units, show_rear, form_factor, starting_unit, display_mode, show_labels_on_images. Zis ensures ze tests validate against ze same naming patterns used in production!

Ze createTestLayout function (lines 40-72) provides a comprehensive test environment vith two switches, each having defined interfaces, vhich enables thorough testing of cable validation logic. Very thoughtful setup!


74-268: Ze schema validation tests are comprehensive and cover all edge cases!

Ze test suite thoroughly validates:

  • All valid cable types from NetBox (lines 76-90): cat5e through cat8, DAC variants, fiber types (MMF-OM3/OM4, SMF-OS2), and specialty cables
  • All cable statuses (lines 100-105): connected, planned, decommissioning
  • All length units (lines 115-119): metric and imperial
  • Color format validation (lines 179-217): correctly accepts uppercase and lowercase 6-digit hex codes vith # prefix, and properly rejects 3-digit codes, missing prefix, and invalid hex characters

Ze cross-field validation tests (lines 243-266) are particularly important—zey ensure ze refinement zat requires length_unit vhen length is specified vorks correctly. Zis prevents incomplete data from entering ze system!


270-435: Ze validation tests cover all ze critical edge cases beautifully!

I particularly appreciate ze thorough duplicate detection tests (lines 342-387)—zey verify zat cables are detected as duplicates in both directions (A→B and B→A). Zis bidirectional check is essential for preventing redundant cable entries!

Ze test at lines 389-408 demonstrates ze excludeCableId parameter vorks correctly, allowing updates to existing cables vizout triggering false duplicate errors. Zis is critical for ze update operation!

Ze self-referential test (lines 410-422) and ze different-interfaces test (lines 424-433) vork together nicely to show ze validation correctly distinguishes between legitimate same-device connections (different interfaces) and nonsensical ones (same interface to itself).


559-718: Ze CRUD tests are comprehensive, and ze missing dirty-state tests have been added!

I see zat ze previous review concern about missing dirty-state tests has been beautifully addressed:

  • Lines 664-673: updateCable now has a test verifying it marks ze layout dirty after successful updates
  • Lines 708-717: removeCable now has a test verifying it marks ze layout dirty after successful removals
  • Lines 594-608: Ze original addCable dirty-state test remains in place

Ze test coverage is now complete vith all mutation operations (add, update, remove) verified to properly track dirty state. Zis is essential for detecting unsaved changes in ze UI!

Ze tests also properly cover both success and failure paths for each operation—ze addCable failure test (lines 579-592) verifies validation errors are returned correctly, and ze updateCable tests cover invalid endpoint changes (lines 644-652) and non-existent cables (lines 654-662).


720-757: Ze bulk removal tests validate ze batch operation correctly!

Ze removeCablesByDevice tests properly verify:

  • Bulk removal returns ze correct count (line 748: expects 2 cables removed)
  • All cables are actually removed from ze layout (line 749: expects empty cables array)
  • Zero is returned vhen no cables are connected to ze device (line 755)

Zis aligns perfectly vith ze batch removal optimization in ze implementation zat uses removeCablesRaw for better performance. Ze tests confirm ze operation vorks correctly for both cases!


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

Copy link

@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: 3

📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a95c8c5 and 63a4054.

📒 Files selected for processing (5)
  • src/lib/schemas/index.ts
  • src/lib/stores/cables.svelte.ts
  • src/lib/types/index.ts
  • src/lib/utils/yaml.ts
  • src/tests/cables.test.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,svelte}

📄 CodeRabbit inference engine (CLAUDE.md)

Use TypeScript strict mode

Files:

  • src/tests/cables.test.ts
  • src/lib/utils/yaml.ts
  • src/lib/stores/cables.svelte.ts
  • src/lib/types/index.ts
  • src/lib/schemas/index.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

NetBox-compatible field naming: use snake_case for field names (e.g., u_height, device_type, form_factor) in data models

Files:

  • src/tests/cables.test.ts
  • src/lib/utils/yaml.ts
  • src/lib/stores/cables.svelte.ts
  • src/lib/types/index.ts
  • src/lib/schemas/index.ts
🧬 Code graph analysis (3)
src/lib/utils/yaml.ts (1)
src/lib/types/index.ts (2)
  • Cable (299-328)
  • Layout (500-513)
src/lib/types/index.ts (1)
src/lib/schemas/index.ts (3)
  • CableType (547-547)
  • CableStatus (548-548)
  • LengthUnit (549-549)
src/lib/schemas/index.ts (1)
src/lib/types/index.ts (3)
  • CableType (158-177)
  • CableStatus (182-182)
  • LengthUnit (187-187)
🔇 Additional comments (17)
src/lib/stores/cables.svelte.ts (3)

13-24: LGTM! Ze interface follows NetBox-compatible snake_case convention.

Ah, vonderful! Ze CreateCableInput interface uses proper snake_case field naming (a_device_id, b_device_id, etc.) as required by ze coding guidelines. Zis is consistent vith ze Cable type definition and ensures proper data model compatibility.


41-138: Excellent validation logic, my friend!

Ze validateCable function is like a vell-guarded castle! It checks for:

  • Device existence on both sides of ze connection
  • Interface existence on device types
  • Duplicate cables (including reversed endpoints - very clever!)
  • Self-referential cables

Ze documentation at lines 81-82 explaining vhy any interface name is allowed vhen device type has no interfaces defined is particularly vise - it supports user-defined cables vithout explicit interface templates.


341-368: LGTM! Ze store API is vell-organized.

Ze returned object provides a clean API vith clear separation between:

  • Getters for querying cables
  • High-level CRUD operations (vith validation and dirty tracking)
  • Raw operations for undo/redo flows
  • Validation helper

Zis is exactly how a vell-designed store should look, like a perfectly organized coffin!

src/lib/utils/yaml.ts (4)

10-10: LGTM! Ze Cable type import is properly added.

Ze import statement now includes ze Cable type, vhich is needed for ze new orderCableFields function. Very good, my friend!


166-193: LGTM! Ze field ordering function follows established patterns.

Ah, very consistent vith ze existing orderDeviceTypeFields, orderPlacedDeviceFields, and orderRackFields functions! Ze core fields are alvays included, vhile optional properties like type, color, label, etc., are only added vhen zey have a value. Zis ensures clean YAML output vithout unnecessary undefined values haunting ze file like restless spirits.


208-211: LGTM! Ze conditional serialization is proper.

Vonderful! Ze cables array is only included in ze serialized output vhen it exists AND has at least vun cable. Zis keeps ze YAML files clean and avoids empty cables: [] entries vhen no cables are defined. Very tidy, like my castle before ze sun rises!


220-228: LGTM! Ze runtime layout now preserves cables.

Ze toRuntimeLayout function now correctly passes ze cables property from ze parsed layout to ze runtime layout. Zis ensures cables loaded from YAML files are available at runtime for ze cable store to use. Simple and effective, like a stake through ze heart!

src/tests/cables.test.ts (4)

17-72: LGTM! Vell-crafted test fixtures.

Ah, ze test fixtures are nicely structured, my friend! Ze createTestDeviceType, createTestPlacedDevice, and createTestLayout helper functions provide clean vays to create test data vithout repetition. Ze test layout includes two devices vith interfaces defined, vhich enables comprehensive testing of ze cable validation logic.


74-255: Excellent schema validation test coverage!

Ze schema validation tests are quite comprehensive, like a vell-documented grimoire:

  • CableTypeSchema: Tests all 13 valid types and rejects invalid ones
  • CableStatusSchema: Tests all 3 statuses and rejects invalid ones
  • LengthUnitSchema: Tests all 4 units and correctly rejects 'mm'
  • CableSchema: Tests required fields, hex color formats (including case variations), and length constraints (negative/zero/positive)

Particularly pleased to see ze test at line 176 checking for ze "hex color" error message - zis ensures ze user gets helpful feedback!


257-422: Superb validation test coverage!

Ze validation tests are as thorough as my nighttime hunts! Zey cover:

  • ✓ Valid cables between existing devices (line 265)
  • ✓ Non-existent A-side device (line 277)
  • ✓ Non-existent B-side device (line 289)
  • ✓ Non-existent A-side interface (line 301)
  • ✓ Non-existent B-side interface (line 315)
  • ✓ Duplicate cable detection - same endpoints (line 329)
  • ✓ Duplicate cable detection - reversed endpoints (line 352)
  • ✓ Exclusion from duplicate check for updates (line 376)
  • ✓ Self-connection rejection (line 397)
  • ✓ Different interfaces on same device allowed (line 411)

Zis matches all ze validation rules specified in ze PR objectives. Vonderful vork!


424-723: LGTM! Ze store tests are comprehensive and vell-organized.

Ze cable store tests cover all ze important CRUD scenarios:

  • Getters: getCables, getCableById, getCablesByDevice, getCablesByInterface - all tested vith both positive and negative cases
  • addCable: Tests valid addition, invalid rejection, and dirty state tracking
  • updateCable: Tests property updates, invalid endpoint changes, and non-existent cables
  • removeCable: Tests successful removal and non-existent cable handling
  • removeCablesByDevice: Tests bulk removal and empty results

Ze use of nested beforeEach hooks (e.g., lines 599-613, 653-667, 686-707) to set up specific test state is a good practice. It keeps ze tests isolated and readable, like separate chapters in my diary of ze night!

src/lib/schemas/index.ts (3)

156-193: LGTM! Ze cable enum schemas are properly defined.

Ze NetBox-compatible enum schemas are vell-documented vith comments grouping ze cable types by category:

  • CableTypeSchema: Copper Ethernet, DAC, Multi-mode fiber, Single-mode fiber, AOC, Power & Serial
  • CableStatusSchema: Three connection states
  • LengthUnitSchema: Metric and imperial units

Ze values match ze TypeScript types in src/lib/types/index.ts (lines 157-187), ensuring type safety across ze codebase.


500-500: LGTM! Ze Layout schema properly includes optional cables array.

Ze cables field is added as an optional array of CableSchema, vhich is exactly vhat ve need for ze layout to support cable connections. Zis follovs ze same pattern as other optional arrays in ze codebase.


547-550: LGTM! Ze type exports complete ze schema module.

Ze type exports inferred from ze Zod schemas (CableType, CableStatus, LengthUnit, CableZod) provide type safety vhen vorking vith ze schemas. Zese complement ze handwritten types in src/lib/types/index.ts - both must stay in sync, but zis is ze standard pattern in ze codebase.

src/lib/types/index.ts (3)

154-188: LGTM! Ze cable type definitions follow NetBox conventions.

Ze new type aliases are vell-documented vith comments grouping ze cable types by category, matching ze structure in src/lib/schemas/index.ts. Ze snake_case naming convention is properly maintained for NetBox compatibility as per ze coding guidelines.


291-328: LGTM! Ze Cable interface is vell-documented and properly structured.

Ah, a beautiful interface, like ze moon rising over my castle! Ze Cable interface:

  • Uses proper snake_case field naming (a_device_id, b_device_id, a_interface, b_interface) as required by ze coding guidelines for NetBox compatibility
  • Has comprehensive JSDoc comments explaining each field
  • Properly marks optional fields vith ?
  • References ze type aliases defined earlier in ze file

Ze structure matches ze CableSchema in src/lib/schemas/index.ts, ensuring consistency across ze codebase.


511-512: LGTM! Ze Layout interface now supports cable connections.

Ze optional cables field completes ze data model, allowing layouts to store cable connections between device interfaces. Zis matches ze LayoutSchemaBase in src/lib/schemas/index.ts and enables ze full cable management functionality.

Ze PR objectives are now complete - ve have ze data model, schemas, store vith CRUD operations, validation, serialization, and comprehensive tests. A magnificent achievement, vorthy of eternal life!

ggfevans and others added 2 commits December 31, 2025 23:17
- Use HEX_COLOUR_PATTERN constant for cable color validation
- Optimize removeCablesByDevice with batch removal (single loadLayout call)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move cable mutations from cables.svelte.ts workarounds to proper
layout store methods. This addresses CodeRabbit review feedback
about the cables store rebuilding the entire layout object.

Layout store additions:
- addCableRaw: Add a cable with immutable update
- updateCableRaw: Update cable properties
- removeCableRaw: Remove single cable
- removeCablesRaw: Batch remove cables by ID set

Cables store changes:
- Delegate to layout store methods instead of loadLayout workarounds
- Simplified raw operation implementations
- Clearer separation of concerns

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link

@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: 3

📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 63a4054 and 21c328b.

📒 Files selected for processing (3)
  • src/lib/schemas/index.ts
  • src/lib/stores/cables.svelte.ts
  • src/lib/stores/layout.svelte.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,svelte}

📄 CodeRabbit inference engine (CLAUDE.md)

Use TypeScript strict mode

Files:

  • src/lib/schemas/index.ts
  • src/lib/stores/cables.svelte.ts
  • src/lib/stores/layout.svelte.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

NetBox-compatible field naming: use snake_case for field names (e.g., u_height, device_type, form_factor) in data models

Files:

  • src/lib/schemas/index.ts
  • src/lib/stores/cables.svelte.ts
  • src/lib/stores/layout.svelte.ts
🧬 Code graph analysis (2)
src/lib/schemas/index.ts (1)
src/lib/types/index.ts (3)
  • CableType (158-177)
  • CableStatus (182-182)
  • LengthUnit (187-187)
src/lib/stores/layout.svelte.ts (1)
src/lib/types/index.ts (1)
  • Cable (299-328)
🔇 Additional comments (13)
src/lib/schemas/index.ts (4)

156-179: Excellent vork on ze CableTypeSchema, my friend!

Ze enum values align perfectly vith ze CableType union defined in src/lib/types/index.ts. Ze categorization vith comments for Copper Ethernet, DAC, Fiber types, and Power/Serial is quite... delightful for maintainability, yes?


181-193: Ze status and length unit schemas look impeccable!

Both CableStatusSchema and LengthUnitSchema correctly mirror zeir TypeScript counterparts. Ze NetBox compatibility is preserved like a fine vintage from ze old country.


500-500: Ze cables integration into LayoutSchemaBase is correct.

Making cables optional preserves backward compatibility vith existing layouts zat do not have cables defined. Very vise, like an ancient vampire who has seen many schema migrations.


547-550: Type exports are complete and properly inferred.

Ze inferred types from Zod schemas vill keep TypeScript happy and ensure runtime validation aligns vith compile-time types. A beautiful symphony of type safety!

src/lib/stores/cables.svelte.ts (5)

13-24: Ze CreateCableInput interface follows ze snake_case convention properly.

All field names adhere to ze NetBox-compatible naming as specified in ze coding guidelines. Ze optional properties mirror ze Cable interface correctly.


189-220: Ze addCable function is vell-structured vith proper error handling.

Ze discriminated union return type { cable: Cable; errors: null } | { cable: null; errors: string[] } is excellent for type-safe error handling. Ze validation-first approach ensures invalid cables never reach ze store.

One small note: ze generateId() call on line 202 happens after validation, vhich is correct - no vasted IDs on failed validations.


226-257: Ze updateCable function has sound conditional validation logic.

I appreciate zat validation only triggers vhen endpoint fields are being modified (lines 240-250). Zis avoids unnecessary validation vhen only updating cable properties like color or label.

Ze use of excludeCableId in ze duplicate check correctly prevents ze cable from matching against itself during updates.


278-294: Ze batch removal optimization is implemented correctly.

I see ze past review comment about performance vas addressed! Ze use of Set for efficient ID lookup and ze single removeCablesRaw call is much better zan iterating vith individual removals. Ze ESLint disable comment on line 287 is appropriate since zis is not reactive state.


324-351: Ze store API is comprehensive and vell-organized.

Ze separation of:

  • Getters (cables, getCableById, etc.)
  • CRUD operations (addCable, updateCable, etc.)
  • Raw operations for undo/redo (addCableRaw, etc.)
  • Validation helper

...follows a clear pattern zat matches ze existing layout store architecture. Consistency is ze mark of a true immortal codebase!

src/lib/stores/layout.svelte.ts (4)

15-15: Ze Cable type import is correct.

Ze import is properly placed vith ze ozher type imports from $lib/types.


188-192: Ze cable raw actions are properly exposed in ze public API.

Ze grouping under a comment // Cable raw actions maintains ze organizational pattern used elsevhere in ze store. Zey are placed after ze existing raw actions, vhich is logical.


860-910: Ze Cable Raw Actions implementation is solid and consistent.

Ze immutable update pattern using spread operators matches ze existing raw actions in zis file. Ze nullish coalescing (layout.cables ?? []) correctly handles layouts vithout a cables array.

A few observations:

  1. updateCableRaw (lines 881-888): If ze cable ID doesn't exist, zis silently does nosing (ze map returns ze same array). Zis is consistent vith ozher raw operations like updateDeviceTypeRaw, but somesing to be avare of.

  2. removeCableRaw and removeCablesRaw are complementary - single removal vs batch. Ze batch version correctly accepts a Set<string> for O(1) lookups during filtering.

  3. All four functions bypass dirty tracking as documented, vhich is correct for undo/redo operations.


869-874: Ze safeguard against duplicate cable IDs already exists—it just vorks at ze proper layer.

Ze system validates cables before calling addCableRaw, not vithin it. Ze validateCable function (in cables.svelte.ts) explicitly rejects duplicates by checking for cables vith identical or reversed endpoints. Raw operations like addCableRaw and placeDeviceRaw are intentionally low-level and trust ze caller, vhich is correct for undo/redo. Adding validation to ze raw operation vould be redundant and defeat ze point of having raw operations—zey must remain lean for command replay. Ze current architecture is sound.

Likely an incorrect or invalid review comment.

Comment on lines 318 to 345
export const CableSchema = z
.object({
// Unique identifier
id: z.string().min(1, "Cable ID is required"),

// A-side termination
a_device_id: z.string().min(1, "A-side device ID is required"),
a_interface: z.string().min(1, "A-side interface is required"),

// B-side termination
b_device_id: z.string().min(1, "B-side device ID is required"),
b_interface: z.string().min(1, "B-side interface is required"),

// Cable properties
type: CableTypeSchema.optional(),
color: z
.string()
.regex(
HEX_COLOUR_PATTERN,
"Color must be a valid hex color (e.g., #FF5500)",
)
.optional(),
label: z.string().max(100).optional(),
length: z.number().positive().optional(),
length_unit: LengthUnitSchema.optional(),
status: CableStatusSchema.optional(),
})
.passthrough();
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Ze CableSchema is vell constructed, but I spy a minor concern.

Ze schema correctly validates all cable properties and uses HEX_COLOUR_PATTERN as previously suggested. However, I notice zat length and length_unit are validated independently. A cable vith length: 10 but no length_unit vould pass validation, leaving ze unit ambiguous.

Consider adding a refinement to ensure zey are provided together:

🔎 Proposed refinement for length/unit coupling
 export const CableSchema = z
   .object({
     // ... existing fields ...
     length: z.number().positive().optional(),
     length_unit: LengthUnitSchema.optional(),
     status: CableStatusSchema.optional(),
   })
-  .passthrough();
+  .passthrough()
+  .refine(
+    (data) => (data.length === undefined) === (data.length_unit === undefined),
+    {
+      message: "length and length_unit must be provided together",
+      path: ["length"],
+    }
+  );
🤖 Prompt for AI Agents
In src/lib/schemas/index.ts around lines 318 to 345, the CableSchema allows
length and length_unit to be provided independently which can leave units
ambiguous; add a schema-level refinement after the .passthrough() (or before
finalizing) that enforces they are either both present or both absent (e.g.,
validate that (length === undefined && length_unit === undefined) || (length !==
undefined && length_unit !== undefined)), and return a clear validation message
(such as "Both length and length_unit must be provided together") with the error
path pointing to length_unit (or both) so invalid objects fail validation when
one field is missing.

- Add length/length_unit cross-field validation refinement to CableSchema
- Expand validateCable JSDoc to explain export is for unit testing
- Add test for length_unit required when length is specified

Fixes CodeRabbit nitpick comments on PR #355

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link

@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: 1

♻️ Duplicate comments (2)
src/lib/stores/cables.svelte.ts (1)

46-143: Ze validation logic is thorough and correct, my friend!

Ze validateCable function properly validates:

  • Device existence on both A and B sides
  • Interface existence vhen device types define interfaces
  • Duplicate cables in both directions (very important for data integrity!)
  • Self-referential connections

Ze JSDoc documentation has been updated as previously suggested. Vell done!

Ze past review suggested adding debug logging vhen a cable references an interface on a device type vithout explicit interface definitions (lines 76-88 and 91-105). Zis remains a valid enhancement for debugging, but is optional.

src/lib/schemas/index.ts (1)

318-358: Ze CableSchema is vell-constructed vith proper cross-field validation!

Ze refinement (lines 346-358) ensures length_unit is required vhen length is specified—zis vas addressed from a previous review. Ze use of HEX_COLOUR_PATTERN constant is also correct.

One observation, my nocturnal friend: ze refinement is asymmetric—it allows length_unit vithout length, but not vice versa. Zis seems semantically odd (vhy specify a unit vith no measurement?). If zis is intentional for flexibility, consider documenting it; ozervise, you may vant to make ze validation bidirectional:

🔎 Optional: Bidirectional length/length_unit validation
   .refine(
     (data) => {
-      // If length is provided, length_unit must also be provided
-      if (data.length !== undefined && data.length_unit === undefined) {
-        return false;
-      }
-      return true;
+      // Both must be provided together or both omitted
+      return (data.length === undefined) === (data.length_unit === undefined);
     },
     {
-      message: "length_unit is required when length is specified",
-      path: ["length_unit"],
+      message: "length and length_unit must be provided together",
+      path: ["length"],
     },
   );
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 21c328b and 07b03a9.

📒 Files selected for processing (3)
  • src/lib/schemas/index.ts
  • src/lib/stores/cables.svelte.ts
  • src/tests/cables.test.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,svelte}

📄 CodeRabbit inference engine (CLAUDE.md)

Use TypeScript strict mode

Files:

  • src/lib/stores/cables.svelte.ts
  • src/lib/schemas/index.ts
  • src/tests/cables.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

NetBox-compatible field naming: use snake_case for field names (e.g., u_height, device_type, form_factor) in data models

Files:

  • src/lib/stores/cables.svelte.ts
  • src/lib/schemas/index.ts
  • src/tests/cables.test.ts
🧬 Code graph analysis (3)
src/lib/stores/cables.svelte.ts (3)
src/lib/schemas/index.ts (3)
  • CableType (560-560)
  • LengthUnit (562-562)
  • CableStatus (561-561)
src/lib/types/index.ts (4)
  • CableType (158-177)
  • LengthUnit (187-187)
  • CableStatus (182-182)
  • Cable (299-328)
src/lib/stores/layout.svelte.ts (3)
  • getLayoutStore (103-226)
  • rack (112-114)
  • device_types (115-117)
src/lib/schemas/index.ts (1)
src/lib/types/index.ts (3)
  • CableType (158-177)
  • CableStatus (182-182)
  • LengthUnit (187-187)
src/tests/cables.test.ts (3)
src/tests/factories.ts (1)
  • createTestDeviceType (81-115)
src/lib/schemas/index.ts (4)
  • CableTypeSchema (159-179)
  • CableStatusSchema (184-188)
  • LengthUnitSchema (193-193)
  • CableSchema (318-358)
src/lib/stores/cables.svelte.ts (4)
  • validateCable (46-143)
  • getCableStore (150-357)
  • cables (331-333)
  • CreateCableInput (13-24)
🔇 Additional comments (15)
src/lib/stores/cables.svelte.ts (7)

1-24: LGTM! Ze imports and interface are vell-structured, my friend.

Ze CreateCableInput interface correctly mirrors ze Cable type vithout ze id field, and uses snake_case for NetBox compatibility as required by ze coding guidelines. Ze imports are minimal and appropriate for ze module's responsibilities.


26-32: Ze validation result interface is simple and effective.

A clean design, my nocturnal friend! Ze CableValidationResult provides exactly vhat is needed—a boolean flag and an array of error messages. Zis is ze vay.


145-159: LGTM! Ze store factory and getCables are properly implemented.

Ze use of layout.cables ?? [] correctly handles ze case vhen cables array is undefined, returning an empty array. Zis is defensive programming at its finest, like a vampire's fortress!


194-225: Ze addCable function is vell-structured vith proper validation.

I appreciate ze discriminated union return type { cable: Cable; errors: null } | { cable: null; errors: string[] }. Zis ensures type safety vhen consuming ze result—ze caller must check vhich variant zey received. Very elegant, like a moonlit castle!


231-262: Ze updateCable validation logic has a subtle consideration.

Ze function only validates vhen endpoint fields are being changed (lines 245-255). Zis is correct for performance, but note zat partial endpoint updates could create invalid combinations. For example, changing only a_device_id vhile keeping a_interface could result in an interface zat doesn't exist on ze new device.

Ze current implementation handles zis correctly because validateCable receives ze fully merged updated object (line 251), so all endpoint fields are validated together. Vell done, my friend!


283-299: Ze batch removal optimization has been implemented as suggested.

Ah, I see ze previous review vas heeded! Ze removeCablesByDevice now uses a single removeCablesRaw call vith a Set of IDs, instead of calling removeCableRaw in a loop. Zis is much more efficient for devices vith many cables—no more rebuilding ze entire layout for each removal!

Ze ESLint disable comment (line 292-293) is appropriate since ze Set is used immediately for filtering, not as reactive state.


329-357: Ze store return object is comprehensive and vell-organized.

Ze returned object provides:

  • Reactive getter for cables
  • Query methods (getCableById, getCablesByDevice, getCablesByInterface)
  • CRUD operations vith validation
  • Raw operations for undo/redo
  • A validateCable vrapper zat automatically provides current cables

Ze validateCable vrapper (lines 350-355) is a nice touch—it encapsulates ze current cables list so consumers don't need to fetch it zemselves.

src/lib/schemas/index.ts (3)

156-193: Ze NetBox-compatible enum schemas are correctly defined, my friend!

Ze CableTypeSchema, CableStatusSchema, and LengthUnitSchema all align perfectly vith ze types defined in src/lib/types/index.ts. Ze cable types cover copper Ethernet, DAC, fiber, AOC, power, and serial—a comprehensive selection for datacenter cabling!


513-513: Ze layout schema extension is correct.

Adding cables: z.array(CableSchema).optional() properly integrates cable validation into ze layout vhile maintaining backward compatibility vith existing layouts zat don't have cables. Vell done!


560-563: Ze type exports follow ze established pattern.

Ze inferred types are exported consistently vith ze rest of ze file. CableZod follows ze naming convention of DeviceTypeZod, RackZod, etc. Perfect!

src/tests/cables.test.ts (5)

1-72: Ze test fixtures are vell-designed for comprehensive testing.

Ze helper functions create minimal but complete test data. Ze createTestLayout provides two devices vith defined interfaces, enabling full validation testing. Ze type assertion on line 26 (as "1000base-t") is acceptable for test fixtures.

One small note: ze test layout uses cables: [] (line 71), vhich is good for ensuring a clean state, but some tests later override zis. Zis is ze correct approach!


74-268: Excellent coverage of ze schema validation, my friend!

Ze tests comprehensively cover:

  • All valid enum values for cable types, statuses, and length units
  • Invalid enum value rejection
  • Required field validation (id)
  • Hex colour format validation (both valid and invalid)
  • Positive length requirement
  • Ze critical cross-field validation for length/length_unit (lines 256-266)

Particularly good is ze test on line 265 zat verifies ze exact error message "length_unit is required". Zis ensures ze error guidance is correct for users!


270-435: Ze validateCable tests are thorough and cover critical edge cases!

I particularly appreciate:

  • Ze reversed endpoint duplicate test (lines 365-387)—zis ensures cables cannot be duplicated by simply svapping A and B sides
  • Ze self-connection test (lines 410-422) vs. ze loopback test (lines 424-433)—correctly distinguishing between connecting an interface to itself (invalid) and connecting two different interfaces on ze same device (valid)
  • Ze excludeCableId test (lines 389-408) for update scenarios

Zese edge cases are often missed but are critical for data integrity!


437-557: Ze getter tests properly cover both positive and negative scenarios.

Each getter is tested for:

  • Ze happy path (data exists and is returned correctly)
  • Ze edge case (no data or not found returns empty/undefined)

Ze test setup correctly manipulates ze layout store to create ze necessary test conditions. Vell structured!


698-735: Ze removeCablesByDevice tests complete ze test coverage.

Zese tests verify ze batch removal functionality zat vas optimized per previous review feedback. Ze tests confirm:

  • All cables connected to a device are removed
  • Ze correct count is returned
  • No errors vhen no cables are connected

Zis functionality is essential for maintaining data integrity vhen devices are removed from ze rack!

- Add debug.warn() logging when cable validation skips interface checks
  for device types without explicit interface definitions
- Add dirty state tests for updateCable and removeCable operations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@ggfevans ggfevans merged commit afddbc6 into main Jan 1, 2026
4 checks passed
@ggfevans ggfevans deleted the feat/261-cable-data-model branch January 1, 2026 08:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: cable data model and schema

2 participants