Skip to content

Conversation

@ianshade
Copy link
Contributor

@ianshade ianshade commented May 26, 2025

About the Contributor

This pull request is posted on behalf of TV 2 Norge.

Type of Contribution

This is a:

Bug fix

Current Behavior

Updating Studio (Blueprint) Config using the HTTP API (updateStudioConfig operation) resulted in other Studio settings, e.g. peripheral devices to be lost.

New Behavior

Settings of the existing studio are preserved

Testing

  • I have added one or more unit tests for this PR
  • I have updated the relevant unit tests
  • No unit test changes are needed for this PR

Affected areas

This PR affects the HTTP API, specifically operations that update a Studio

Time Frame

Not urgent for us

Other Information

Status

  • PR is ready to be reviewed.
  • The functionality has been tested by the author.
  • Relevant unit tests has been added / updated.
  • Relevant documentation (code comments, system documentation) has been added / updated.

Fix for Settings Loss During Studio Configuration Updates

Problem:
Updating studio configuration (Blueprint) through the HTTP API's updateStudioConfig operation inadvertently discarded existing studio settings such as peripheral device configuration, causing data loss.

Solution:
The fix ensures that when a studio configuration is updated via the HTTP API, all existing studio properties not explicitly provided in the API request are preserved from the existing studio record, rather than being overwritten with defaults.

Key Changes:

  1. New Helper Function (buildStudioFromResolved)

    • Introduced in meteor/server/api/rest/v1/typeConversion.ts
    • Consolidates the logic for constructing a DBStudio from API data
    • Takes an optional existingStudio parameter and merges it with the new apiStudio data
    • Uses a default scaffold that spreads the existing studio data, then selectively overrides only the fields provided by the API request
    • Handles blueprint configuration computation correctly whether blueprintConfigFromAPI is a function or value
  2. Enhanced Override Handling (objectWithOverrides.ts)

    • Refactored updateOverrides function with a two-phase approach:
      • Phase 1: Preserves existing overrides that remain valid (via new getOverridesToPreserve helper)
      • Phase 2: Computes new override operations for changed properties (via new recursivelyGenerateOverrides function)
    • Improved handling for nested structures, arrays, and deletion operations
    • Ensures nested property overrides are correctly preserved and new overrides are only generated for actually changed values
  3. Comprehensive Test Coverage

    • Added tests in meteor/server/api/rest/v1/__tests__/typeConversions.spec.ts for buildStudioFromResolved, verifying that API-provided fields override existing studio fields while preserving ID fields and correctly applying overrides
    • Extended tests in packages/corelib/src/settings/__tests__/objectWithOverrides.spec.ts with suite covering:
      • Adding to existing overrides
      • Nested structures and arrays
      • Deletion operations in nested structures
      • Override updates and preservation of baseline defaults

Testing Status:
Unit tests added and verified; patch coverage at 80.59701%, with noted coverage gaps in override handling logic.

Impact:
Affected areas: HTTP API operations for studio configuration updates. Existing studio properties are now safely preserved during configuration updates, preventing unintended data loss.

@codecov-commenter
Copy link

codecov-commenter commented Aug 25, 2025

Codecov Report

❌ Patch coverage is 80.59701% with 26 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...ckages/corelib/src/settings/objectWithOverrides.ts 82.55% 15 Missing ⚠️
meteor/server/api/rest/v1/typeConversion.ts 77.08% 11 Missing ⚠️

📢 Thoughts on this report? Let us know!

@ianshade ianshade marked this pull request as ready for review August 25, 2025 21:43
@ianshade ianshade requested a review from a team as a code owner August 25, 2025 21:43
@nytamin nytamin requested a review from Copilot August 26, 2025 04:02
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes an issue where updating Studio (Blueprint) Config via the HTTP API caused other Studio settings (like peripheral devices) to be lost. The fix preserves existing studio data when building updated studio objects.

  • Refactored the updateOverrides function to properly preserve existing overrides and handle complex object structures
  • Modified the studio building logic to preserve existing studio properties before applying API updates
  • Added comprehensive test coverage for the new override update behavior

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
packages/corelib/src/settings/objectWithOverrides.ts Completely rewrote updateOverrides function with improved logic for preserving overrides and handling nested objects
packages/corelib/src/settings/tests/objectWithOverrides.spec.ts Added extensive test cases covering various override update scenarios
meteor/server/api/rest/v1/typeConversion.ts Refactored studio creation to preserve existing studio fields using spread operator
meteor/server/api/rest/v1/tests/typeConversions.spec.ts Added new test file with tests for studio field preservation

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@jstarpl jstarpl changed the base branch from release52 to release53 October 8, 2025 12:49
Copy link
Contributor

@jstarpl jstarpl left a comment

Choose a reason for hiding this comment

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

Looks fine to me, other than the issue in recursivelyGenerateOverrides pointed out by Copilot.

@coderabbitai
Copy link

coderabbitai bot commented Jan 18, 2026

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

The changes introduce a new helper function to construct DBStudio objects from API data with blueprint manifest integration, refactor override handling in the object utilities to use a two-phase preservation-and-generation model, and add comprehensive test coverage for both the studio type conversion and override update logic.

Changes

Cohort / File(s) Summary
Studio Type Conversion
meteor/server/api/rest/v1/typeConversion.ts, meteor/server/api/rest/v1/__tests__/typeConversions.spec.ts
Introduces buildStudioFromResolved() helper to centralize DBStudio construction from API data, blueprint manifest, and optional existing studio. Delegates from studioFrom(). Tests verify field override behavior with and without blueprintConfigFromAPI function.
Object Override Utilities
packages/corelib/src/settings/objectWithOverrides.ts, packages/corelib/src/settings/__tests__/objectWithOverrides.spec.ts
Refactors updateOverrides() to use two-phase approach: preserve applicable overrides, then generate missing ones via new helpers getOverridesToPreserve() and recursivelyGenerateOverrides(). Enhanced handling for nested structures and deletions. Tests cover adding, updating, and deleting overrides in complex nested scenarios.

Sequence Diagram(s)

sequenceDiagram
    participant API as API Request
    participant studioFrom as studioFrom()
    participant buildStudio as buildStudioFromResolved()
    participant manifest as Blueprint Manifest
    participant result as DBStudio Result

    API->>studioFrom: apiStudio, studioId
    studioFrom->>studioFrom: Retrieve existingStudio from DB
    studioFrom->>buildStudio: Pass apiStudio, existingStudio, manifest, IDs
    buildStudio->>manifest: Access blueprintConfigFromAPI
    manifest-->>buildStudio: Config function or undefined
    buildStudio->>buildStudio: Compute blueprint config from API/existing
    buildStudio->>buildStudio: Scaffold defaults, merge existingStudio, override with apiStudio
    buildStudio-->>result: Consolidated DBStudio object
    result-->>studioFrom: Complete studio with overrides
    studioFrom-->>API: Final DBStudio
Loading
sequenceDiagram
    participant caller as Caller
    participant updateOverrides as updateOverrides()
    participant preserve as getOverridesToPreserve()
    participant generate as recursivelyGenerateOverrides()
    participant result as Final ObjectWithOverrides

    caller->>updateOverrides: curObj, rawObj, overrides
    updateOverrides->>preserve: Determine overrides to keep
    preserve->>preserve: Check if override still matches rawObj
    preserve-->>updateOverrides: Filtered preservedOverrides
    updateOverrides->>updateOverrides: Clone defaults, apply preserved overrides
    updateOverrides->>generate: Find missing overrides in flattened state
    generate->>generate: Traverse curObj vs rawObj recursively
    generate->>generate: Detect set/delete operations on scalars and arrays
    generate-->>updateOverrides: New override operations
    updateOverrides-->>result: Defaults + preserved + new overrides
    result-->>caller: Complete ObjectWithOverrides
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 A studio rises from API's call,
With blueprints and overrides standing tall,
Two phases of override, smooth and refined,
Nested structures and deletions aligned,
A refactored path, more clear for all! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically identifies the main change: fixing a bug where settings were lost during studio updates via the HTTP API.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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.

properties not present in apiStudio needed to be taken from the existing studio

refactor(EAV-588): extract `studioFrom` logic

... and add test coverage

refactor(EAV-588): small changes for clarity

fix(EAV-598): make `updateOverrides` respect deep property overrides, not generate invalid overrides, and correctly preserve existing overrides

fix(EAV-588): add null checks
@jstarpl
Copy link
Contributor

jstarpl commented Jan 20, 2026

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Jan 20, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

🤖 Fix all issues with AI agents
In `@meteor/server/api/rest/v1/typeConversion.ts`:
- Around line 353-386: The code always resets supportedShowStyleBase to [] when
apiStudio omits it, overwriting existingStudio; change the assignment for
supportedShowStyleBase to preserve existing values when
apiStudio.supportedShowStyleBase is undefined: set supportedShowStyleBase to
apiStudio.supportedShowStyleBase !== undefined ?
apiStudio.supportedShowStyleBase.map(id => protectString<ShowStyleBaseId>(id)) :
(existingStudio?.supportedShowStyleBase ?? []), mirroring the pattern used for
settingsWithOverrides (and keep wrapDefaultObject/updateOverrides usage
unchanged).
♻️ Duplicate comments (2)
packages/corelib/src/settings/objectWithOverrides.ts (2)

2-5: Avoid deep import from type-fest’s internal path.

type-fest/source/readonly-deep isn’t part of the public API and can break on upgrades. If ReadonlyObjectDeep is exported from the package root in v4.33.0, prefer importing it from type-fest alongside ReadonlyDeep. Otherwise consider ReadonlyDeep or a local alias.

♻️ Proposed refactor
-import { ReadonlyDeep } from 'type-fest'
-import { ReadonlyObjectDeep } from 'type-fest/source/readonly-deep'
+import { ReadonlyDeep, ReadonlyObjectDeep } from 'type-fest'
Does type-fest v4.33.0 export ReadonlyObjectDeep from the package root?

153-162: Arrays are treated as atomic values, but recursion still dives into them.

Line 153 handles arrays as single values, yet Line 160 recurses into arrays (they’re objects), which can emit per-index overrides and contradict the “arrays are treated as a single value” rule. Add an early guard for arrays (both curValue and rawValue) and continue.

🐛 Suggested fix
-		if (Array.isArray(rawValue) && !_.isEqual(curValue, rawValue)) {
-			outOverrides.push({
-				op: 'set',
-				path: fullKeyPathString,
-				value: rawValue,
-			})
-		}
-		if (typeof curValue === 'object' && curValue !== null && typeof rawValue === 'object' && rawValue !== null) {
+		if (Array.isArray(rawValue) || Array.isArray(curValue)) {
+			if (!_.isEqual(curValue, rawValue)) {
+				outOverrides.push({
+					op: 'set',
+					path: fullKeyPathString,
+					value: rawValue,
+				})
+			}
+			continue
+		}
+		if (typeof curValue === 'object' && curValue !== null && typeof rawValue === 'object' && rawValue !== null) {
 			recursivelyGenerateOverrides(curValue, rawValue, fullKeyPath, outOverrides)
 			continue
 		}

Copy link

@chandrashekar-nallamilli chandrashekar-nallamilli left a comment

Choose a reason for hiding this comment

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

LGTM

@ianshade ianshade merged commit 794fc9e into Sofie-Automation:release53 Jan 22, 2026
35 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Contribution from TV 2 Norge Contributions sponsored by TV 2 Norge (tv2.no)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants