Skip to content

AFTE RELEASE feat(customization): typed customization registry via AppTypes.Customizations#6133

Open
sedghi wants to merge 1 commit into
masterfrom
ohifTypeOHIFCustomization
Open

AFTE RELEASE feat(customization): typed customization registry via AppTypes.Customizations#6133
sedghi wants to merge 1 commit into
masterfrom
ohifTypeOHIFCustomization

Conversation

@sedghi

@sedghi sedghi commented Jul 10, 2026

Copy link
Copy Markdown
Member

Context

The CustomizationService exposes ~90 customization ids, but getCustomization(id) returns the loose Customization union for all of them. There is no discoverability of which ids exist or what shape each expects, and consumers compensate with ~20 as unknown as X / as any casts across the repo. setCustomizations payloads (including $set / $push command specs used by modes and app config) are not checked at all.

Changes

This PR adds the typing infrastructure (no per-key population yet, and no runtime changes):

  • AppTypes.Customizations registry — an empty, declaration-merged global interface in platform/core/src/types/AppTypes.ts, following the exact pattern already used by AppTypes.Services and PresentationIds. Each extension (in-tree or third-party) declares the ids it owns:

    declare global {
      namespace AppTypes {
        interface Customizations {
          'viewportOverlay.topLeft': OverlayItem[];
          'panelSegmentation.disableEditing': boolean;
        }
      }
    }
  • Typed overloads on getCustomization, getValue, and hasCustomization: registered ids get autocomplete and their declared return type; any other string (dynamic keys, undeclared third-party keys) falls back to the existing Customization | undefined signature, so nothing breaks.

  • Checked setCustomizations payloads via the new CustomizationEntries type: registered ids accept their declared value directly or as an immutability-helper spec ({ $set: ... }, { $push: [...] }, the custom $filter, ...). CustomizationPhaseInput reuses it, so phase-tagged appConfig.customizationService blocks written in TypeScript are checked the same way.

  • Two small call-site fixes: usAnnotation and basic-test-mode passed the raw string 'mode' where the CustomizationScope enum is expected (Mode is already the default scope, so the argument is dropped; runtime behavior identical).

  • CUSTOMIZATION_TYPING_PLAN.md documents the design, the conventions for declaring keys, and the follow-up phases (populating the registry per extension, then optionally generating the docs table and a JSON Schema for JSONC customization files from the registry).

Testing

  • All 68 CustomizationService unit tests pass.
  • Full-repo tsc diffed against a pre-change baseline: three pre-existing false positives fixed (valid customization objects rejected by the old Record<string, Customization> input type), zero new errors.
  • A standalone compile-time smoke test exercised the mechanism end to end (registry augmentation from an extension, typed reads, wrong-type reads rejected, $push of wrong element type rejected, $filter accepted, unknown keys and string module refs still compiling) under both the repo compiler settings and --strict.

Summary by CodeRabbit

  • New Features

    • Added typed and discoverable customization IDs with improved autocomplete and value validation.
    • Added support for safely typing customization updates, including supported update commands.
    • Unknown or dynamically generated customization IDs continue to work through a flexible fallback.
  • Documentation

    • Added a rollout plan describing customization typing conventions, validation, and future adoption steps.

@sedghi
sedghi temporarily deployed to fork-pr-approval July 10, 2026 16:22 — with GitHub Actions Inactive

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.

Tip: disable this comment in your organization's Code Review settings.

@netlify

netlify Bot commented Jul 10, 2026

Copy link
Copy Markdown

Deploy Preview for ohif-dev ready!

Name Link
🔨 Latest commit 68773e2
🔍 Latest deploy log https://app.netlify.com/projects/ohif-dev/deploys/6a5e500a6d6c470008b08ba1
😎 Deploy Preview https://deploy-preview-6133--ohif-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

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

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The customization service now supports declaration-merged customization registries, typed lookup and update payloads, and string fallbacks for unknown keys. URL phase inputs use the typed entry map, and the annotation mode adopts the updated setter call form.

Changes

Typed customizations

Layer / File(s) Summary
Customization registry and entry types
platform/core/src/types/AppTypes.ts, platform/core/src/services/CustomizationService/types.ts, platform/core/src/services/CustomizationService/customizationUrlTypes.ts
Adds the AppTypes.Customizations registry, typed $filter update commands, CustomizationEntries, and typed customization phase inputs.
CustomizationService typed overloads
platform/core/src/services/CustomizationService/CustomizationService.ts
Adds registry-keyed overloads for lookup, fallback retrieval, and existence checks, and applies typed customization entry maps.
Mode integration and rollout specification
modes/usAnnotation/src/index.ts, CUSTOMIZATION_TYPING_PLAN.md
Updates the annotation mode to pass one customization object and documents the typing rollout and verification plan.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • OHIF/Viewers#5992: Updates URL-driven customization application through the same customization service APIs.
  • OHIF/Viewers#6041: Adds and consumes a customization accessed through CustomizationService.

Suggested reviewers: wayfarer3130

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The main sections are present, but the required Checklist section and tested-environment details are missing from the template. Add the Checklist section with all checkboxes marked and fill in OS, Node version, and browser details to match the template.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change—typed customization registry via AppTypes.Customizations—though the stray 'AFTE RELEASE' text is noisy.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ohifTypeOHIFCustomization

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.

@cypress

cypress Bot commented Jul 10, 2026

Copy link
Copy Markdown

Viewers    Run #6584

Run Properties:  status check passed Passed #6584  •  git commit 68773e2122: feat(customization): add typed customization registry via AppTypes.Customization...
Project Viewers
Branch Review ohifTypeOHIFCustomization
Run status status check passed Passed #6584
Run duration 01m 55s
Commit git commit 68773e2122: feat(customization): add typed customization registry via AppTypes.Customization...
Committer Alireza
View all properties for this run ↗︎

Test results
Tests that failed  Failures 0
Tests that were flaky  Flaky 0
Tests that did not run due to a developer annotating a test with .skip  Pending 0
Tests that did not run due to a failure in a mocha hook  Skipped 0
Tests that passed  Passing 28
View all changes introduced in this branch ↗︎

@sedghi sedghi changed the title feat(customization): typed customization registry via AppTypes.Customizations AFTE RELEASE feat(customization): typed customization registry via AppTypes.Customizations Jul 11, 2026
…stomizations

Seeds a declaration-merged AppTypes.Customizations registry so extensions
can declare the value type of each customization id they own, and adds
typed overloads to getCustomization, getValue, hasCustomization and
setCustomizations. Registered ids get autocomplete and precise types;
unregistered and dynamic ids keep the existing loose Customization
fallback, so nothing breaks. setCustomizations payloads (including
immutability-helper command specs and the custom $filter) are checked
against the registry through the new CustomizationEntries type, which
CustomizationPhaseInput now reuses for phased app-config blocks.

Also drops a redundant string 'mode' scope argument in two modes that
was mistyped against the CustomizationScope enum (Mode is the default).

CUSTOMIZATION_TYPING_PLAN.md documents the design and the follow-up
phases for populating the registry across extensions.
@sedghi
sedghi force-pushed the ohifTypeOHIFCustomization branch from 21ed32e to 68773e2 Compare July 20, 2026 16:42
@sedghi
sedghi temporarily deployed to fork-pr-approval July 20, 2026 16:42 — with GitHub Actions Inactive

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@platform/core/src/services/CustomizationService/customizationUrlTypes.ts`:
- Around line 12-15: Update the CustomizationPhaseInput type alias to accept
arrays containing either string extension references or CustomizationEntries,
while continuing to accept a standalone CustomizationEntries value. Use the
supported shape Array<string | CustomizationEntries> | CustomizationEntries and
leave setCustomizations behavior unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ca0adf0e-4124-49d7-9d2d-3e9de70271d2

📥 Commits

Reviewing files that changed from the base of the PR and between 21ed32e and 68773e2.

📒 Files selected for processing (6)
  • CUSTOMIZATION_TYPING_PLAN.md
  • modes/usAnnotation/src/index.ts
  • platform/core/src/services/CustomizationService/CustomizationService.ts
  • platform/core/src/services/CustomizationService/customizationUrlTypes.ts
  • platform/core/src/services/CustomizationService/types.ts
  • platform/core/src/types/AppTypes.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • platform/core/src/types/AppTypes.ts
  • platform/core/src/services/CustomizationService/types.ts
  • modes/usAnnotation/src/index.ts
  • platform/core/src/services/CustomizationService/CustomizationService.ts

Comment on lines 12 to +15
* - an array that mixes string references (extension module ids resolved via
* the ExtensionManager) and inline object maps.
*/
export type CustomizationPhaseInput = string[] | Record<string, any>;
export type CustomizationPhaseInput = string[] | CustomizationEntries;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the target file and nearby declarations
ast-grep outline platform/core/src/services/CustomizationService/customizationUrlTypes.ts --view expanded || true

echo
echo "---- file ----"
cat -n platform/core/src/services/CustomizationService/customizationUrlTypes.ts | sed -n '1,120p'

echo
echo "---- usages ----"
rg -n "CustomizationPhaseInput|CustomizationEntries|setCustomizations|customizationUrlTypes" platform/core/src/services -S

Repository: OHIF/Viewers

Length of output: 12915


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect consumer code paths that build or consume customization phase inputs
rg -n "setCustomizations\(|CustomizationPhaseInput|CustomizationEntries|customization.*phase|mixed arrays|ExtensionManager" platform/core/src -S

Repository: OHIF/Viewers

Length of output: 14270


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the related service implementation if present
fd -a "CustomizationService" platform/core/src/services

Repository: OHIF/Viewers

Length of output: 820


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the current commit context for the file if available
git status --short
git rev-parse --short HEAD

Repository: OHIF/Viewers

Length of output: 160


🏁 Script executed:

#!/bin/bash
set -euo pipefail
cat -n platform/core/src/services/CustomizationService/customizationUrlTypes.ts | sed -n '1,120p'

Repository: OHIF/Viewers

Length of output: 3094


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the implementation and nearby tests for array handling
sed -n '600,740p' platform/core/src/services/CustomizationService/CustomizationService.ts

echo
echo "---- array-related tests ----"
rg -n "string\\[\\]|Array|mixed|reference|customizationModule|setCustomizations\\(" platform/core/src/services/CustomizationService/CustomizationService.*test* platform/core/src/services/CustomizationService/CustomizationService.ts -S

Repository: OHIF/Viewers

Length of output: 25504


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect how URL customization payloads are normalized before reaching setCustomizations
sed -n '900,1010p' platform/core/src/services/CustomizationService/CustomizationService.ts

echo
echo "---- related payload helpers ----"
sed -n '1,220p' platform/core/src/services/CustomizationService/getUrlCustomizationModulePayload.ts

echo
echo "---- phase input definitions ----"
sed -n '1,220p' platform/core/src/services/CustomizationService/types.ts

Repository: OHIF/Viewers

Length of output: 8762


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
text = Path('platform/core/src/services/CustomizationService/CustomizationService.ts').read_text()

for needle in [
    'public setCustomizations(',
    'Array.isArray(customizations)',
    'typeof customizations',
    'this._extensionManager',
    'resolveCustomization',
]:
    idx = text.find(needle)
    print(f"\n### {needle} @ {idx}")
    if idx != -1:
        start = max(0, idx - 500)
        end = min(len(text), idx + 1500)
        print(text[start:end])
PY

Repository: OHIF/Viewers

Length of output: 6332


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Quick structural scan for where phase inputs are consumed
ast-grep run --pattern 'setCustomizations($$$)' --lang typescript platform/core/src/services/CustomizationService/CustomizationService.ts

Repository: OHIF/Viewers

Length of output: 150


Widen the phase-input type to match the supported array shape. setCustomizations already processes array items one by one, so phase blocks can include both string references and inline customization maps. CustomizationPhaseInput currently narrows that to string[], which rejects a documented valid form; change it to Array<string | CustomizationEntries> | CustomizationEntries.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@platform/core/src/services/CustomizationService/customizationUrlTypes.ts`
around lines 12 - 15, Update the CustomizationPhaseInput type alias to accept
arrays containing either string extension references or CustomizationEntries,
while continuing to accept a standalone CustomizationEntries value. Use the
supported shape Array<string | CustomizationEntries> | CustomizationEntries and
leave setCustomizations behavior unchanged.

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.

1 participant