feat: Add combined build (#5895)
* Add combined build * Link script location update * Security and validation fixes * Allow specifying target path in PR description * fix: Version match * Fix build detection issue * fix: Playwright deploy * Separate out the branch merge guard * Update docs and link info * test: Update the layout change to wait for network idle * Move audit late so the rest of the build can be worked on * Add text with network check to ensure we see this change is updated * Attempt to fix the mpr loading on ohif-downstream * PR review comments * Update docs * Update to CS3D 4.20.0 * PR comments * Add log on ohif-integration builds * Update build test * Removed unused space to kickoff build
This commit is contained in:
parent
15ef4c2e0f
commit
1df671e9ab
@ -112,61 +112,6 @@ jobs:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: ~/repo
|
||||
# SECURITY AUDIT - only when bun.lock has changed
|
||||
- run:
|
||||
name: 'Security Audit - High Risk Vulnerabilities'
|
||||
command: |
|
||||
git fetch origin master 2>/dev/null || true
|
||||
BASE_REF=$(git merge-base HEAD origin/master 2>/dev/null)
|
||||
if [[ -z "$BASE_REF" ]]; then
|
||||
echo "Could not determine base ref (e.g. shallow clone or no origin/master), skipping security audit."
|
||||
exit 0
|
||||
fi
|
||||
CHANGED_FILES=$(git diff --name-only origin/master...HEAD 2>/dev/null || echo "")
|
||||
if ! echo "$CHANGED_FILES" | grep -qx 'bun.lock'; then
|
||||
echo "⏭️ bun.lock unchanged - skipping security audit."
|
||||
exit 0
|
||||
fi
|
||||
echo "🔍 bun.lock changed - running bun audit for security vulnerabilities..."
|
||||
echo "Checking for HIGH-RISK vulnerabilities..."
|
||||
|
||||
# Define ignored vulnerabilities with comments
|
||||
IGNORED_VULNS=(
|
||||
"GHSA-3ppc-4f35-3m26" # CVE-2026-26996 - minimatch via itk-wasm and glob is safe because it does NOT use the CLI
|
||||
# CVE-2026-26996 - minimatch via other packages are strictly for building and CI/CD purposes; no user supplied expressions are passed to minimatch
|
||||
"GHSA-7r86-cg39-jmmj" # CVE-2026-27903 - minimatch same as above
|
||||
"GHSA-23c5-xmqv-rm74" # CVE-2026-27904 - minimatch same as above
|
||||
)
|
||||
|
||||
# Build ignore flags
|
||||
IGNORE_FLAGS=""
|
||||
for vuln in "${IGNORED_VULNS[@]}"; do
|
||||
IGNORE_FLAGS="$IGNORE_FLAGS --ignore=$vuln"
|
||||
done
|
||||
|
||||
if bun audit $IGNORE_FLAGS --audit-level high; then
|
||||
echo "✅ No high-risk vulnerabilities found"
|
||||
echo "🎉 Security audit passed!"
|
||||
else
|
||||
echo ""
|
||||
echo "❌ HIGH-RISK VULNERABILITIES DETECTED!"
|
||||
echo "======================================"
|
||||
echo ""
|
||||
echo "🔧 To fix these issues:"
|
||||
echo " 1. Run: bun audit"
|
||||
echo " 2. Review the vulnerability details"
|
||||
echo " 3. Update affected packages to secure versions"
|
||||
echo " 4. Test your changes"
|
||||
echo " 5. Re-run: bun audit --audit-level high"
|
||||
echo ""
|
||||
echo "📋 Full audit report:"
|
||||
|
||||
bun audit $IGNORE_FLAGS --audit-level low || true
|
||||
|
||||
echo ""
|
||||
echo "❌ This build cannot proceed until high-risk vulnerabilities are resolved."
|
||||
exit 1
|
||||
fi
|
||||
- run:
|
||||
name: Install Dependencies
|
||||
command: bun install --frozen-lockfile
|
||||
@ -405,6 +350,68 @@ jobs:
|
||||
npx wait-on@latest http://localhost:3000 && cd platform/app && npx cypress run --record --parallel
|
||||
start-command: yarn run test:data && yarn run test:e2e:serve
|
||||
|
||||
SECURITY_AUDIT:
|
||||
<<: *defaults
|
||||
resource_class: large
|
||||
steps:
|
||||
- install_bun
|
||||
- checkout
|
||||
- run:
|
||||
name: 'Security Audit - High Risk Vulnerabilities'
|
||||
command: |
|
||||
git fetch origin master 2>/dev/null || true
|
||||
BASE_REF=$(git merge-base HEAD origin/master 2>/dev/null)
|
||||
if [[ -z "$BASE_REF" ]]; then
|
||||
echo "Could not determine base ref (e.g. shallow clone or no origin/master), skipping security audit."
|
||||
exit 0
|
||||
fi
|
||||
CHANGED_FILES=$(git diff --name-only origin/master...HEAD 2>/dev/null || echo "")
|
||||
if ! echo "$CHANGED_FILES" | grep -qx 'bun.lock'; then
|
||||
echo "⏭️ bun.lock unchanged - skipping security audit."
|
||||
exit 0
|
||||
fi
|
||||
echo "🔍 bun.lock changed - running bun audit for security vulnerabilities..."
|
||||
echo "Checking for HIGH-RISK vulnerabilities..."
|
||||
|
||||
# Define ignored vulnerabilities with comments
|
||||
IGNORED_VULNS=(
|
||||
"GHSA-3ppc-4f35-3m26" # CVE-2026-26996 - minimatch via itk-wasm and glob is safe because it does NOT use the CLI
|
||||
# CVE-2026-26996 - minimatch via other packages are strictly for building and CI/CD purposes; no user supplied expressions are passed to minimatch
|
||||
"GHSA-7r86-cg39-jmmj" # CVE-2026-27903 - minimatch same as above
|
||||
"GHSA-23c5-xmqv-rm74" # CVE-2026-27904 - minimatch same as above
|
||||
)
|
||||
|
||||
# Build ignore flags
|
||||
IGNORE_FLAGS=""
|
||||
for vuln in "${IGNORED_VULNS[@]}"; do
|
||||
IGNORE_FLAGS="$IGNORE_FLAGS --ignore=$vuln"
|
||||
done
|
||||
|
||||
if bun audit $IGNORE_FLAGS --audit-level high; then
|
||||
echo "✅ No high-risk vulnerabilities found"
|
||||
echo "🎉 Security audit passed!"
|
||||
exit 0
|
||||
else
|
||||
echo ""
|
||||
echo "❌ HIGH-RISK VULNERABILITIES DETECTED!"
|
||||
echo "======================================"
|
||||
echo ""
|
||||
echo "🔧 To fix these issues:"
|
||||
echo " 1. Run: bun audit"
|
||||
echo " 2. Review the vulnerability details"
|
||||
echo " 3. Update affected packages to secure versions"
|
||||
echo " 4. Test your changes"
|
||||
echo " 5. Re-run: bun audit --audit-level high"
|
||||
echo ""
|
||||
echo "📋 Full audit report:"
|
||||
|
||||
bun audit $IGNORE_FLAGS --audit-level low || true
|
||||
|
||||
echo ""
|
||||
echo "❌ This build cannot proceed until high-risk vulnerabilities are resolved."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DOCKER_MULTIARCH_MANIFEST:
|
||||
<<: *defaults
|
||||
resource_class: large
|
||||
@ -494,6 +501,10 @@ workflows:
|
||||
- CYPRESS:
|
||||
name: 'Cypress Tests'
|
||||
context: cypress
|
||||
- SECURITY_AUDIT:
|
||||
filters:
|
||||
branches:
|
||||
ignore: master
|
||||
|
||||
# viewer-dev.ohif.org
|
||||
DEPLOY_MASTER:
|
||||
|
||||
153
.github/workflows/playwright.yml
vendored
153
.github/workflows/playwright.yml
vendored
@ -2,6 +2,19 @@ name: Playwright Tests
|
||||
on:
|
||||
pull_request:
|
||||
branches: [master, release/*]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
cs3d_ref:
|
||||
description: >-
|
||||
CS3D branch (e.g. main, origin:feat/foo) or version (e.g. 4.18.2, 4.19+, 4.x). Only used
|
||||
when ohif-integration label is present or via workflow_dispatch.
|
||||
required: false
|
||||
default: '4.19+'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
issues: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@ -9,7 +22,7 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
playwright-tests:
|
||||
timeout-minutes: 60
|
||||
timeout-minutes: 120
|
||||
runs-on: self-hosted
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@ -25,14 +38,85 @@ jobs:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Install Yarn
|
||||
run: npm install -g yarn@1.22.22
|
||||
|
||||
# ── CS3D integration: detect label and ref type ──────────────────────
|
||||
- name: Check for CS3D integration label
|
||||
id: cs3d-check
|
||||
run: bash .scripts/ci/cs3d-check-integration.sh
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
CS3D_REF_INPUT: ${{ github.event.inputs.cs3d_ref || '4.19+' }}
|
||||
REPO: ${{ github.repository }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
|
||||
- name: Detect CS3D ref type
|
||||
id: cs3d-ref
|
||||
if: steps.cs3d-check.outputs.enabled == 'true'
|
||||
run: |
|
||||
REF="${CS3D_REF}"
|
||||
if [[ "$REF" =~ ^[0-9]+\.[0-9x]+\+?(\.[0-9x]+)?(-[a-zA-Z0-9._]+)?$ ]]; then
|
||||
echo "type=version" >> "$GITHUB_OUTPUT"
|
||||
RESOLVED=$(node .scripts/cs3d-resolve-version.mjs "$REF")
|
||||
echo "version=$RESOLVED" >> "$GITHUB_OUTPUT"
|
||||
echo "::notice::CS3D version: $REF -> $RESOLVED"
|
||||
else
|
||||
echo "type=branch" >> "$GITHUB_OUTPUT"
|
||||
echo "::notice::CS3D branch: $REF"
|
||||
fi
|
||||
env:
|
||||
CS3D_REF: ${{ steps.cs3d-check.outputs.cs3d_ref }}
|
||||
|
||||
# ── CS3D branch path: clone and build before OHIF install ───────────
|
||||
- name: Clone CS3D
|
||||
if: steps.cs3d-check.outputs.enabled == 'true' && steps.cs3d-ref.outputs.type == 'branch'
|
||||
run: |
|
||||
REF="${CS3D_REF}"
|
||||
if [[ "$REF" == *:* ]]; then
|
||||
REPO="https://github.com/${REF%%:*}/cornerstone3D.git"
|
||||
BRANCH="${REF#*:}"
|
||||
else
|
||||
REPO="https://github.com/cornerstonejs/cornerstone3D.git"
|
||||
BRANCH="$REF"
|
||||
fi
|
||||
echo "::notice::Cloning CS3D from $REPO branch $BRANCH"
|
||||
git clone --depth 1 --branch "$BRANCH" "$REPO" libs/@cornerstonejs
|
||||
env:
|
||||
CS3D_REF: ${{ steps.cs3d-check.outputs.cs3d_ref }}
|
||||
|
||||
- name: Install & Build CS3D
|
||||
if: steps.cs3d-check.outputs.enabled == 'true' && steps.cs3d-ref.outputs.type == 'branch'
|
||||
working-directory: libs/@cornerstonejs
|
||||
run: bun install --frozen-lockfile && bun run build:esm
|
||||
|
||||
# ── Common: install OHIF dependencies ───────────────────────────────
|
||||
- name: Install dependencies
|
||||
run: bun install --frozen-lockfile
|
||||
|
||||
# ── CS3D branch path: link packages after OHIF install ──────────────
|
||||
- name: Link CS3D packages
|
||||
if: steps.cs3d-check.outputs.enabled == 'true' && steps.cs3d-ref.outputs.type == 'branch'
|
||||
working-directory: libs/@cornerstonejs
|
||||
run: node scripts/link-ohif-cornerstone-node-modules.mjs "$GITHUB_WORKSPACE"
|
||||
|
||||
# ── CS3D version path: update versions after OHIF install ───────────
|
||||
- name: Set CS3D version
|
||||
if: steps.cs3d-check.outputs.enabled == 'true' && steps.cs3d-ref.outputs.type == 'version'
|
||||
run: |
|
||||
node .scripts/cs3d-set-version.mjs "${CS3D_VERSION}"
|
||||
bun install
|
||||
env:
|
||||
CS3D_VERSION: ${{ steps.cs3d-ref.outputs.version }}
|
||||
|
||||
# ── Common: run tests ───────────────────────────────────────────────
|
||||
- name: Install Playwright browsers
|
||||
run: npx playwright install
|
||||
- name: Run Playwright tests
|
||||
run: |
|
||||
export NODE_OPTIONS="--max_old_space_size=10192"
|
||||
bun run test:e2e:coverage
|
||||
|
||||
# ── Common: collect test results and coverage ───────────────────────
|
||||
- name: Create directory of test results
|
||||
if: ${{ !cancelled() }}
|
||||
run: |
|
||||
@ -56,3 +140,70 @@ jobs:
|
||||
name: coverage-report-pr
|
||||
path: coverage
|
||||
retention-days: 3
|
||||
|
||||
# ── CS3D: build and deploy preview to Netlify ───────────────────────
|
||||
- name: Log build context (OHIF/CS3D branch and version for build diagnosis)
|
||||
if: steps.cs3d-check.outputs.enabled == 'true'
|
||||
run: |
|
||||
if [[ "$CS3D_REF_TYPE" == "branch" ]]; then
|
||||
echo "::notice::Build type: ohif-downstream | OHIF: ${{ github.repository }}@${{ github.ref }} (${{ github.sha }}) | CS3D: branch ${{ steps.cs3d-check.outputs.cs3d_ref }}"
|
||||
else
|
||||
echo "::notice::Build type: ohif-upstream | OHIF: ${{ github.repository }}@${{ github.ref }} (${{ github.sha }}) | CS3D: version ${{ steps.cs3d-ref.outputs.version }}"
|
||||
fi
|
||||
node .scripts/log-build-context.mjs
|
||||
env:
|
||||
BUILD_TYPE: ${{ steps.cs3d-ref.outputs.type == 'branch' && 'ohif-downstream' || 'ohif-upstream' }}
|
||||
CS3D_REF_TYPE: ${{ steps.cs3d-ref.outputs.type }}
|
||||
|
||||
- name: Build OHIF viewer (CS3D preview)
|
||||
if: steps.cs3d-check.outputs.enabled == 'true'
|
||||
run: bun run build:ci
|
||||
|
||||
- name: Deploy CS3D preview to Netlify
|
||||
if: steps.cs3d-check.outputs.enabled == 'true'
|
||||
run: |
|
||||
RESULT=$(npx netlify-cli deploy --dir=platform/app/dist --alias="cs3d-pr-${PR_NUM}" --json --filter=@ohif/app) || {
|
||||
echo "::error::Netlify deploy command failed"
|
||||
exit 1
|
||||
}
|
||||
URL=$(echo "$RESULT" | jq -r '.deploy_url')
|
||||
if [[ -z "$URL" || "$URL" == "null" ]]; then
|
||||
echo "::error::Netlify deploy did not return a valid URL"
|
||||
echo "$RESULT"
|
||||
exit 1
|
||||
fi
|
||||
echo "::notice::CS3D preview deployed: $URL"
|
||||
env:
|
||||
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
||||
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
|
||||
PR_NUM: ${{ github.event.pull_request.number || 'manual' }}
|
||||
|
||||
# ── CS3D: log results ───────────────────────────────────────────────
|
||||
- name: Log CS3D build used
|
||||
if: steps.cs3d-check.outputs.enabled == 'true'
|
||||
run: |
|
||||
if [[ "$CS3D_REF_TYPE" == "branch" ]]; then
|
||||
echo "::notice::CS3D integration PASSED with branch ${CS3D_REF} (linked from libs/@cornerstonejs)"
|
||||
else
|
||||
echo "::notice::CS3D integration PASSED with @cornerstonejs/*@${CS3D_VERSION}"
|
||||
fi
|
||||
env:
|
||||
CS3D_REF_TYPE: ${{ steps.cs3d-ref.outputs.type }}
|
||||
CS3D_REF: ${{ steps.cs3d-check.outputs.cs3d_ref }}
|
||||
CS3D_VERSION: ${{ steps.cs3d-ref.outputs.version }}
|
||||
|
||||
# ── Separate job: block merge when using a CS3D branch ─────────────
|
||||
cs3d-branch-merge-guard:
|
||||
name: "CS3D Branch Merge Guard"
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Check for CS3D branch usage
|
||||
run: bash .scripts/ci/cs3d-branch-merge-guard.sh
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
CS3D_REF_INPUT: ${{ github.event.inputs.cs3d_ref || '4.19+' }}
|
||||
REPO: ${{ github.repository }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@ -61,5 +61,8 @@ tests/playwright-report/
|
||||
|
||||
**/.claude/settings.local.json
|
||||
|
||||
# cornerstone3D local linking
|
||||
libs/
|
||||
|
||||
# Backup files
|
||||
*~
|
||||
|
||||
42
.scripts/ci/cs3d-branch-merge-guard.sh
Normal file
42
.scripts/ci/cs3d-branch-merge-guard.sh
Normal file
@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env bash
|
||||
# CS3D branch merge guard: blocks merge when tests ran against a CS3D branch (not a version).
|
||||
# Exits 0 when merge is allowed or guard is skipped; exits 1 when merge must be blocked.
|
||||
#
|
||||
# Required env: GH_TOKEN, EVENT_NAME, REPO, PR_NUMBER
|
||||
# Optional env: CS3D_REF_INPUT (for workflow_dispatch, default 4.19+)
|
||||
|
||||
set -e
|
||||
|
||||
if [[ "$EVENT_NAME" == "workflow_dispatch" ]]; then
|
||||
echo "::notice::workflow_dispatch — no merge to block, skipping guard."
|
||||
exit 0
|
||||
elif [[ "$EVENT_NAME" == "pull_request" ]]; then
|
||||
LABELS=$(gh api "repos/${REPO}/issues/${PR_NUMBER}/labels" --jq '.[].name')
|
||||
if echo "$LABELS" | grep -q "ohif-integration"; then
|
||||
ENABLED=true
|
||||
CS3D_REF=$(gh api "repos/${REPO}/pulls/${PR_NUMBER}" --jq '.body' \
|
||||
| sed -n 's/^[[:space:]]*CS3D_REF:[[:space:]]*\([^[:space:]]*\).*/\1/p' | head -1)
|
||||
if [[ -z "$CS3D_REF" ]]; then
|
||||
CS3D_REF="4.19+"
|
||||
fi
|
||||
else
|
||||
ENABLED=false
|
||||
fi
|
||||
else
|
||||
ENABLED=false
|
||||
fi
|
||||
|
||||
if [[ "$ENABLED" != "true" ]]; then
|
||||
echo "::notice::No ohif-integration label — skipping merge guard."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check if the ref is a branch (not a version)
|
||||
if [[ "$CS3D_REF" =~ ^[0-9]+\.[0-9x]+\+?(\.[0-9x]+)?(-[a-zA-Z0-9._]+)?$ ]]; then
|
||||
echo "::notice::CS3D ref '$CS3D_REF' is a version — merge allowed."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "::error::Tests ran against CS3D branch '${CS3D_REF}' — this build cannot be merged."
|
||||
echo "::error::Re-run with a published CS3D version (e.g. 4.19+) before merging."
|
||||
exit 1
|
||||
29
.scripts/ci/cs3d-check-integration.sh
Normal file
29
.scripts/ci/cs3d-check-integration.sh
Normal file
@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env bash
|
||||
# CS3D integration check: detects ohif-integration label and parses CS3D_REF.
|
||||
# Writes to GITHUB_OUTPUT: enabled (true|false), cs3d_ref (when enabled).
|
||||
#
|
||||
# Required env: GH_TOKEN, EVENT_NAME, REPO, PR_NUMBER, GITHUB_OUTPUT
|
||||
# Optional env: CS3D_REF_INPUT (for workflow_dispatch, default 4.19+)
|
||||
|
||||
set -e
|
||||
|
||||
if [[ "$EVENT_NAME" == "workflow_dispatch" ]]; then
|
||||
echo "enabled=true" >> "$GITHUB_OUTPUT"
|
||||
echo "cs3d_ref=${CS3D_REF_INPUT:-4.19+}" >> "$GITHUB_OUTPUT"
|
||||
elif [[ "$EVENT_NAME" == "pull_request" ]]; then
|
||||
LABELS=$(gh api "repos/${REPO}/issues/${PR_NUMBER}/labels" --jq '.[].name')
|
||||
if echo "$LABELS" | grep -q "ohif-integration"; then
|
||||
echo "enabled=true" >> "$GITHUB_OUTPUT"
|
||||
REF=$(gh api "repos/${REPO}/pulls/${PR_NUMBER}" --jq '.body' \
|
||||
| sed -n 's/^[[:space:]]*CS3D_REF:[[:space:]]*\([^[:space:]]*\).*/\1/p' | head -1)
|
||||
if [[ -z "$REF" ]]; then
|
||||
REF="4.19+"
|
||||
fi
|
||||
echo "cs3d_ref=${REF}" >> "$GITHUB_OUTPUT"
|
||||
echo "::notice::CS3D ref from PR body: ${REF}"
|
||||
else
|
||||
echo "enabled=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
else
|
||||
echo "enabled=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
63
.scripts/cs3d-resolve-version.mjs
Normal file
63
.scripts/cs3d-resolve-version.mjs
Normal file
@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Resolves a version pattern to a concrete npm version of @cornerstonejs/core.
|
||||
*
|
||||
* Patterns:
|
||||
* 4.18.2 -> 4.18.2 (exact, returned as-is)
|
||||
* 4.18.2-beta.3 -> 4.18.2-beta.3 (exact prerelease)
|
||||
* 4.x -> latest 4.* from npm
|
||||
* 4.17.x -> latest 4.17.* from npm
|
||||
* 4.19+ -> latest >=4.19.0 <5.0.0-0 from npm (4.19 and later, same major)
|
||||
*
|
||||
* Prints the resolved version to stdout.
|
||||
*/
|
||||
|
||||
import { execSync } from 'child_process';
|
||||
|
||||
const pattern = process.argv[2];
|
||||
if (!pattern) {
|
||||
console.error('Usage: cs3d-resolve-version.mjs <pattern>');
|
||||
console.error(' e.g. 4.x, 4.17.x, 4.19+, 4.18.2, 4.18.2-beta.3');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Exact version (no wildcard or range) — pass through unchanged
|
||||
if (!pattern.includes('x') && !pattern.endsWith('+')) {
|
||||
console.log(pattern);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Convert "M.m+" to npm semver range ">=M.m.0 <(M+1).0.0-0"
|
||||
let npmRange = pattern;
|
||||
const plusMatch = pattern.match(/^(\d+)\.(\d+)\+$/);
|
||||
if (plusMatch) {
|
||||
const major = Number(plusMatch[1]);
|
||||
const minor = Number(plusMatch[2]);
|
||||
npmRange = `>=${major}.${minor}.0 <${major + 1}.0.0-0`;
|
||||
}
|
||||
|
||||
try {
|
||||
// Let npm resolve the range: @package@<range> → concrete version
|
||||
const raw = execSync(`npm view @cornerstonejs/core@"${npmRange}" version --json`, {
|
||||
encoding: 'utf8',
|
||||
timeout: 30_000,
|
||||
});
|
||||
|
||||
const resolved = JSON.parse(raw);
|
||||
if (!resolved) {
|
||||
console.error(`npm returned no version when resolving @cornerstonejs/core@${npmRange}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// npm may return an array of versions for ranges; pick the latest (last) one
|
||||
const version = Array.isArray(resolved) ? resolved[resolved.length - 1] : resolved;
|
||||
console.log(version);
|
||||
} catch (err) {
|
||||
const message =
|
||||
(err && (err.stderr?.toString() || err.message || String(err))) ||
|
||||
`Unknown error resolving @cornerstonejs/core@${pattern}`;
|
||||
console.error(`Failed to resolve @cornerstonejs/core version for pattern "${pattern}":`);
|
||||
console.error(message);
|
||||
process.exit(1);
|
||||
}
|
||||
124
.scripts/cs3d-set-version.mjs
Normal file
124
.scripts/cs3d-set-version.mjs
Normal file
@ -0,0 +1,124 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Updates all @cornerstonejs/* package versions across the OHIF workspace.
|
||||
*
|
||||
* Usage: node .scripts/cs3d-set-version.mjs <version>
|
||||
*
|
||||
* Only updates the 8 main CS3D packages (not codec packages):
|
||||
* adapters, ai, core, dicom-image-loader, labelmap-interpolation,
|
||||
* nifti-volume-loader, polymorphic-segmentation, tools
|
||||
*/
|
||||
|
||||
import { readFileSync, writeFileSync, existsSync, readdirSync } from 'fs';
|
||||
import { resolve, dirname, join } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const rootDir = resolve(__dirname, '..');
|
||||
|
||||
const version = process.argv[2];
|
||||
if (!version) {
|
||||
console.error('Usage: cs3d-set-version.mjs <version>');
|
||||
console.error(' e.g. 4.18.2, 4.19.0-beta.1');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// The 8 CS3D packages that are built from source (not codecs)
|
||||
const CS3D_PACKAGES = [
|
||||
'@cornerstonejs/adapters',
|
||||
'@cornerstonejs/ai',
|
||||
'@cornerstonejs/core',
|
||||
'@cornerstonejs/dicom-image-loader',
|
||||
'@cornerstonejs/labelmap-interpolation',
|
||||
'@cornerstonejs/nifti-volume-loader',
|
||||
'@cornerstonejs/polymorphic-segmentation',
|
||||
'@cornerstonejs/tools',
|
||||
];
|
||||
|
||||
// Read root package.json to get workspace globs
|
||||
const rootPkgPath = resolve(rootDir, 'package.json');
|
||||
const rootPkg = JSON.parse(readFileSync(rootPkgPath, 'utf8'));
|
||||
const workspaceGlobs = rootPkg.workspaces?.packages || rootPkg.workspaces || [];
|
||||
|
||||
// Collect all package.json paths from workspace globs
|
||||
function findWorkspacePackageJsons() {
|
||||
const paths = [rootPkgPath]; // include root
|
||||
|
||||
for (const pattern of workspaceGlobs) {
|
||||
const parts = pattern.split('/');
|
||||
let searchDir = rootDir;
|
||||
let hasWildcard = false;
|
||||
|
||||
for (const part of parts) {
|
||||
if (part === '*') {
|
||||
hasWildcard = true;
|
||||
break;
|
||||
}
|
||||
searchDir = join(searchDir, part);
|
||||
}
|
||||
|
||||
if (hasWildcard) {
|
||||
try {
|
||||
const entries = readdirSync(searchDir, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
if (entry.isDirectory()) {
|
||||
const pkgJson = join(searchDir, entry.name, 'package.json');
|
||||
if (existsSync(pkgJson)) {
|
||||
paths.push(pkgJson);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// directory doesn't exist, skip
|
||||
}
|
||||
} else {
|
||||
const pkgJson = join(rootDir, pattern, 'package.json');
|
||||
if (existsSync(pkgJson)) {
|
||||
paths.push(pkgJson);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
// Update a dependencies object, returning count of changes
|
||||
function updateDeps(deps, targetVersion) {
|
||||
let count = 0;
|
||||
if (!deps) return count;
|
||||
for (const pkg of CS3D_PACKAGES) {
|
||||
if (pkg in deps && deps[pkg] !== targetVersion) {
|
||||
deps[pkg] = targetVersion;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
const pkgPaths = findWorkspacePackageJsons();
|
||||
let totalChanges = 0;
|
||||
|
||||
for (const pkgPath of pkgPaths) {
|
||||
const content = readFileSync(pkgPath, 'utf8');
|
||||
const pkg = JSON.parse(content);
|
||||
let changes = 0;
|
||||
|
||||
changes += updateDeps(pkg.dependencies, version);
|
||||
changes += updateDeps(pkg.devDependencies, version);
|
||||
changes += updateDeps(pkg.peerDependencies, version);
|
||||
changes += updateDeps(pkg.resolutions, version);
|
||||
|
||||
if (changes > 0) {
|
||||
// Preserve original formatting (detect indent)
|
||||
const indent = content.match(/^(\s+)/m)?.[1] || ' ';
|
||||
writeFileSync(pkgPath, JSON.stringify(pkg, null, indent) + '\n');
|
||||
const rel = pkgPath.replace(rootDir + '/', '').replace(rootDir + '\\', '');
|
||||
console.log(` Updated ${rel} (${changes} packages)`);
|
||||
totalChanges += changes;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(
|
||||
`\nDone: ${totalChanges} version(s) updated to ${version} across ${pkgPaths.length} package files.`
|
||||
);
|
||||
108
.scripts/log-build-context.mjs
Normal file
108
.scripts/log-build-context.mjs
Normal file
@ -0,0 +1,108 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Logs build context (OHIF branch/version, CS3D source) for diagnosing build issues on GitHub.
|
||||
* Run from repo root. Used by version.mjs and can be invoked from CI workflows.
|
||||
*/
|
||||
import { execa } from 'execa';
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const REPO_ROOT = path.resolve(__dirname, '..');
|
||||
|
||||
function log(msg) {
|
||||
console.log(`[build-context] ${msg}`);
|
||||
}
|
||||
|
||||
async function detectCs3dSource() {
|
||||
const libsCs3d = path.join(REPO_ROOT, 'libs/@cornerstonejs');
|
||||
const coreInNodeModules = path.join(REPO_ROOT, 'node_modules/@cornerstonejs/core');
|
||||
|
||||
try {
|
||||
const libsExists = await fs.access(libsCs3d).then(() => true).catch(() => false);
|
||||
if (!libsExists) {
|
||||
return { source: 'npm', detail: 'published @cornerstonejs packages (no libs/@cornerstonejs)' };
|
||||
}
|
||||
|
||||
const coreStat = await fs.lstat(coreInNodeModules).catch(() => null);
|
||||
const isSymlink = coreStat?.isSymbolicLink();
|
||||
if (isSymlink) {
|
||||
const target = await fs.readlink(coreInNodeModules);
|
||||
return { source: 'integrated', detail: `linked from libs/@cornerstonejs (→ ${target})` };
|
||||
}
|
||||
|
||||
return { source: 'npm', detail: 'published @cornerstonejs packages (libs exists but not linked)' };
|
||||
} catch {
|
||||
return { source: 'unknown', detail: 'could not detect' };
|
||||
}
|
||||
}
|
||||
|
||||
async function getCs3dVersion() {
|
||||
try {
|
||||
const corePkg = path.join(REPO_ROOT, 'node_modules/@cornerstonejs/core/package.json');
|
||||
const pkg = JSON.parse(await fs.readFile(corePkg, 'utf-8'));
|
||||
return pkg.version || 'unknown';
|
||||
} catch {
|
||||
return 'unknown';
|
||||
}
|
||||
}
|
||||
|
||||
async function getCs3dBranchFromLibs() {
|
||||
try {
|
||||
const libsCs3d = path.join(REPO_ROOT, 'libs/@cornerstonejs');
|
||||
const { stdout } = await execa('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {
|
||||
cwd: libsCs3d,
|
||||
});
|
||||
return stdout;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function run() {
|
||||
const inCI = process.env.GITHUB_ACTIONS === 'true';
|
||||
const buildType = inCI ? (process.env.BUILD_TYPE || 'ohif-upstream') : 'local';
|
||||
|
||||
log('═══════════════════════════════════════════════════════════════');
|
||||
log('Build context (for diagnosing GitHub build issues)');
|
||||
log('═══════════════════════════════════════════════════════════════');
|
||||
|
||||
if (inCI) {
|
||||
log(`Build type: ${process.env.BUILD_TYPE || 'ohif-upstream'}`);
|
||||
log(`GitHub repo: ${process.env.GITHUB_REPOSITORY || 'unknown'}`);
|
||||
log(`GitHub ref: ${process.env.GITHUB_REF || 'unknown'}`);
|
||||
log(`GitHub SHA: ${process.env.GITHUB_SHA || 'unknown'}`);
|
||||
log(`Workflow: ${process.env.GITHUB_WORKFLOW || 'unknown'}`);
|
||||
}
|
||||
|
||||
try {
|
||||
const { stdout: branch } = await execa('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {
|
||||
cwd: REPO_ROOT,
|
||||
});
|
||||
const { stdout: sha } = await execa('git', ['rev-parse', '--short', 'HEAD'], {
|
||||
cwd: REPO_ROOT,
|
||||
});
|
||||
log(`OHIF branch: ${branch} (${sha})`);
|
||||
} catch {
|
||||
log('OHIF branch: (not a git repo or error)');
|
||||
}
|
||||
|
||||
const cs3d = await detectCs3dSource();
|
||||
log(`CS3D source: ${cs3d.source} — ${cs3d.detail}`);
|
||||
|
||||
if (cs3d.source === 'integrated') {
|
||||
const branch = await getCs3dBranchFromLibs();
|
||||
if (branch) log(`CS3D branch (libs/@cornerstonejs): ${branch}`);
|
||||
} else {
|
||||
const ver = await getCs3dVersion();
|
||||
log(`CS3D version (@cornerstonejs/core): ${ver}`);
|
||||
}
|
||||
|
||||
log('═══════════════════════════════════════════════════════════════');
|
||||
}
|
||||
|
||||
run().catch((err) => {
|
||||
console.error('[build-context] Error:', err.message);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
59
README.md
59
README.md
@ -105,7 +105,6 @@ For commercial support, academic collaborations, and answers to common
|
||||
questions; please use [Get Support](https://ohif.org/get-support/) to contact
|
||||
us.
|
||||
|
||||
|
||||
## Developing
|
||||
|
||||
### Branches
|
||||
@ -169,6 +168,64 @@ yarn config set workspaces-experimental true
|
||||
yarn install --frozen-lockfile
|
||||
```
|
||||
|
||||
### Cornerstone3D Integration Testing
|
||||
|
||||
OHIF's Playwright end-to-end tests can run against a **CS3D branch** or a
|
||||
**published CS3D version**, allowing changes that span both repositories to be
|
||||
validated together before merging.
|
||||
|
||||
#### Setting up an integration build
|
||||
|
||||
1. Add the **`ohif-integration`** label to your OHIF pull request.
|
||||
2. In the PR body, add a line specifying the CS3D ref:
|
||||
```
|
||||
CS3D_REF: feat/my-feature
|
||||
```
|
||||
- **Version ref** (e.g. `4.19+`, `4.18.2`) — the workflow resolves it to an
|
||||
exact published version and swaps the CS3D dependency via npm.
|
||||
- **Branch ref** (e.g. `main`, `cornerstonejs:feat/foo`) — the workflow
|
||||
clones the branch, builds CS3D from source with `bun run build:esm`, and
|
||||
symlinks the built packages into OHIF's `node_modules`.
|
||||
- For forks, use the `<owner>:<branch>` format
|
||||
(e.g. `myGithubUser:feat/foo`).
|
||||
- If no `CS3D_REF` is specified, the default is `4.19+`.
|
||||
3. The workflow can also be triggered manually via **workflow_dispatch** with a
|
||||
`cs3d_ref` input.
|
||||
|
||||
#### What happens in CI
|
||||
|
||||
The [Playwright workflow](.github/workflows/playwright.yml) runs two jobs:
|
||||
|
||||
| Job | Purpose |
|
||||
|-----|---------|
|
||||
| **Playwright Tests** | Builds OHIF (with CS3D linked or version-swapped), runs the full Playwright suite, uploads test results and coverage, and deploys a Netlify preview when `ohif-integration` is active. |
|
||||
| **CS3D Branch Merge Guard** | A lightweight check that **fails** when the `ohif-integration` label is present and `CS3D_REF` points to a branch (not a version). This prevents merging while still letting the Playwright tests show green so you can see whether the code actually works. |
|
||||
|
||||
#### Testing changes that span both repos
|
||||
|
||||
If a feature requires changes in both Cornerstone3D and OHIF:
|
||||
|
||||
1. Create your feature branch in CS3D and push it.
|
||||
2. Create a matching branch in OHIF.
|
||||
3. Add the `ohif-integration` label to the OHIF pull request.
|
||||
4. In the PR body, add: `CS3D_REF: <your-cs3d-branch>`.
|
||||
5. Playwright tests will build CS3D from source, link it, and run the full
|
||||
suite. The merge guard will block merge until you switch to a published
|
||||
version — but you can see the test results and the preview deploy while
|
||||
iterating.
|
||||
6. Once the CS3D side is merged and published, update the PR body to reference
|
||||
the published version (e.g. `CS3D_REF: 4.19+`). The tests will run against
|
||||
the registry version and the merge guard will pass.
|
||||
|
||||
#### Preview deploys
|
||||
|
||||
When `ohif-integration` is active, the Playwright workflow also builds the OHIF
|
||||
viewer and deploys it to Netlify as a preview. This gives you a live URL to
|
||||
manually test the combined CS3D + OHIF changes without running anything locally.
|
||||
|
||||
For details on linking CS3D locally for development, see the
|
||||
[Cornerstone3D README](libs/@cornerstonejs/README.md#local-development-linking--unlinking).
|
||||
|
||||
## Commands
|
||||
|
||||
These commands are available from the root directory. Each project directory
|
||||
|
||||
331
bun.lock
331
bun.lock
@ -1,5 +1,6 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 0,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "ohif-monorepo-root",
|
||||
@ -50,7 +51,7 @@
|
||||
},
|
||||
"addOns/externals/devDependencies": {
|
||||
"name": "@externals/devDependencies",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@kitware/vtk.js": "34.15.1",
|
||||
@ -131,22 +132,22 @@
|
||||
},
|
||||
"addOns/externals/dicom-microscopy-viewer": {
|
||||
"name": "@externals/dicom-microscopy-viewer",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"dicom-microscopy-viewer": "0.48.17",
|
||||
},
|
||||
},
|
||||
"extensions/cornerstone": {
|
||||
"name": "@ohif/extension-cornerstone",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/adapters": "4.19.0",
|
||||
"@cornerstonejs/ai": "4.19.0",
|
||||
"@cornerstonejs/core": "4.19.0",
|
||||
"@cornerstonejs/labelmap-interpolation": "4.19.0",
|
||||
"@cornerstonejs/polymorphic-segmentation": "4.19.0",
|
||||
"@cornerstonejs/tools": "4.19.0",
|
||||
"@cornerstonejs/adapters": "4.20.0",
|
||||
"@cornerstonejs/ai": "4.20.0",
|
||||
"@cornerstonejs/core": "4.20.0",
|
||||
"@cornerstonejs/labelmap-interpolation": "4.20.0",
|
||||
"@cornerstonejs/polymorphic-segmentation": "4.20.0",
|
||||
"@cornerstonejs/tools": "4.20.0",
|
||||
"@icr/polyseg-wasm": "0.4.0",
|
||||
"@itk-wasm/morphological-contour-interpolation": "1.1.0",
|
||||
"@kitware/vtk.js": "34.15.1",
|
||||
@ -164,9 +165,9 @@
|
||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "1.2.2",
|
||||
"@cornerstonejs/codec-openjpeg": "1.3.0",
|
||||
"@cornerstonejs/codec-openjph": "2.4.7",
|
||||
"@cornerstonejs/dicom-image-loader": "4.19.0",
|
||||
"@ohif/core": "3.13.0-beta.39",
|
||||
"@ohif/ui": "3.13.0-beta.39",
|
||||
"@cornerstonejs/dicom-image-loader": "4.20.0",
|
||||
"@ohif/core": "3.13.0-beta.41",
|
||||
"@ohif/ui": "3.13.0-beta.41",
|
||||
"dcmjs": "0.49.4",
|
||||
"dicom-parser": "1.8.21",
|
||||
"hammerjs": "2.0.8",
|
||||
@ -178,18 +179,18 @@
|
||||
},
|
||||
"extensions/cornerstone-dicom-pmap": {
|
||||
"name": "@ohif/extension-cornerstone-dicom-pmap",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/adapters": "4.19.0",
|
||||
"@cornerstonejs/core": "4.19.0",
|
||||
"@cornerstonejs/adapters": "4.20.0",
|
||||
"@cornerstonejs/core": "4.20.0",
|
||||
"@kitware/vtk.js": "34.15.1",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.13.0-beta.39",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.39",
|
||||
"@ohif/extension-default": "3.13.0-beta.39",
|
||||
"@ohif/i18n": "3.13.0-beta.39",
|
||||
"@ohif/core": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.41",
|
||||
"@ohif/extension-default": "3.13.0-beta.41",
|
||||
"@ohif/i18n": "3.13.0-beta.41",
|
||||
"prop-types": "15.8.1",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
@ -200,15 +201,15 @@
|
||||
},
|
||||
"extensions/cornerstone-dicom-rt": {
|
||||
"name": "@ohif/extension-cornerstone-dicom-rt",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.13.0-beta.39",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.39",
|
||||
"@ohif/extension-default": "3.13.0-beta.39",
|
||||
"@ohif/i18n": "3.13.0-beta.39",
|
||||
"@ohif/core": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.41",
|
||||
"@ohif/extension-default": "3.13.0-beta.41",
|
||||
"@ohif/i18n": "3.13.0-beta.41",
|
||||
"prop-types": "15.8.1",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
@ -219,18 +220,18 @@
|
||||
},
|
||||
"extensions/cornerstone-dicom-seg": {
|
||||
"name": "@ohif/extension-cornerstone-dicom-seg",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/adapters": "4.19.0",
|
||||
"@cornerstonejs/core": "4.19.0",
|
||||
"@cornerstonejs/adapters": "4.20.0",
|
||||
"@cornerstonejs/core": "4.20.0",
|
||||
"@kitware/vtk.js": "34.15.1",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.13.0-beta.39",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.39",
|
||||
"@ohif/extension-default": "3.13.0-beta.39",
|
||||
"@ohif/i18n": "3.13.0-beta.39",
|
||||
"@ohif/core": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.41",
|
||||
"@ohif/extension-default": "3.13.0-beta.41",
|
||||
"@ohif/i18n": "3.13.0-beta.41",
|
||||
"prop-types": "15.8.1",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
@ -241,19 +242,19 @@
|
||||
},
|
||||
"extensions/cornerstone-dicom-sr": {
|
||||
"name": "@ohif/extension-cornerstone-dicom-sr",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/adapters": "4.19.0",
|
||||
"@cornerstonejs/core": "4.19.0",
|
||||
"@cornerstonejs/tools": "4.19.0",
|
||||
"@cornerstonejs/adapters": "4.20.0",
|
||||
"@cornerstonejs/core": "4.20.0",
|
||||
"@cornerstonejs/tools": "4.20.0",
|
||||
"classnames": "2.5.1",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.13.0-beta.39",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.39",
|
||||
"@ohif/extension-measurement-tracking": "3.13.0-beta.39",
|
||||
"@ohif/ui": "3.13.0-beta.39",
|
||||
"@ohif/core": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.41",
|
||||
"@ohif/extension-measurement-tracking": "3.13.0-beta.41",
|
||||
"@ohif/ui": "3.13.0-beta.41",
|
||||
"dcmjs": "0.49.4",
|
||||
"dicom-parser": "1.8.21",
|
||||
"hammerjs": "2.0.8",
|
||||
@ -263,19 +264,19 @@
|
||||
},
|
||||
"extensions/cornerstone-dynamic-volume": {
|
||||
"name": "@ohif/extension-cornerstone-dynamic-volume",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/core": "4.19.0",
|
||||
"@cornerstonejs/tools": "4.19.0",
|
||||
"@cornerstonejs/core": "4.20.0",
|
||||
"@cornerstonejs/tools": "4.20.0",
|
||||
"classnames": "2.5.1",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.13.0-beta.39",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.39",
|
||||
"@ohif/extension-default": "3.13.0-beta.39",
|
||||
"@ohif/i18n": "3.13.0-beta.39",
|
||||
"@ohif/ui": "3.13.0-beta.39",
|
||||
"@ohif/core": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.41",
|
||||
"@ohif/extension-default": "3.13.0-beta.41",
|
||||
"@ohif/i18n": "3.13.0-beta.41",
|
||||
"@ohif/ui": "3.13.0-beta.41",
|
||||
"dcmjs": "0.49.4",
|
||||
"dicom-parser": "1.8.21",
|
||||
"hammerjs": "2.0.8",
|
||||
@ -285,7 +286,7 @@
|
||||
},
|
||||
"extensions/default": {
|
||||
"name": "@ohif/extension-default",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/calculate-suv": "1.1.0",
|
||||
@ -294,8 +295,8 @@
|
||||
"react-color": "2.19.3",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.13.0-beta.39",
|
||||
"@ohif/i18n": "3.13.0-beta.39",
|
||||
"@ohif/core": "3.13.0-beta.41",
|
||||
"@ohif/i18n": "3.13.0-beta.41",
|
||||
"dcmjs": "0.49.4",
|
||||
"dicomweb-client": "0.10.4",
|
||||
"prop-types": "15.8.1",
|
||||
@ -309,7 +310,7 @@
|
||||
},
|
||||
"extensions/dicom-microscopy": {
|
||||
"name": "@ohif/extension-dicom-microscopy",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/codec-charls": "1.2.3",
|
||||
@ -320,10 +321,10 @@
|
||||
"mathjs": "12.4.3",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.13.0-beta.39",
|
||||
"@ohif/extension-default": "3.13.0-beta.39",
|
||||
"@ohif/i18n": "3.13.0-beta.39",
|
||||
"@ohif/ui": "3.13.0-beta.39",
|
||||
"@ohif/core": "3.13.0-beta.41",
|
||||
"@ohif/extension-default": "3.13.0-beta.41",
|
||||
"@ohif/i18n": "3.13.0-beta.41",
|
||||
"@ohif/ui": "3.13.0-beta.41",
|
||||
"prop-types": "15.8.1",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
@ -334,14 +335,14 @@
|
||||
},
|
||||
"extensions/dicom-pdf": {
|
||||
"name": "@ohif/extension-dicom-pdf",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"classnames": "2.5.1",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.13.0-beta.39",
|
||||
"@ohif/ui": "3.13.0-beta.39",
|
||||
"@ohif/core": "3.13.0-beta.41",
|
||||
"@ohif/ui": "3.13.0-beta.41",
|
||||
"dcmjs": "0.49.4",
|
||||
"dicom-parser": "1.8.21",
|
||||
"hammerjs": "2.0.8",
|
||||
@ -351,14 +352,14 @@
|
||||
},
|
||||
"extensions/dicom-video": {
|
||||
"name": "@ohif/extension-dicom-video",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"classnames": "2.5.1",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.13.0-beta.39",
|
||||
"@ohif/ui": "3.13.0-beta.39",
|
||||
"@ohif/core": "3.13.0-beta.41",
|
||||
"@ohif/ui": "3.13.0-beta.41",
|
||||
"dcmjs": "0.49.4",
|
||||
"dicom-parser": "1.8.21",
|
||||
"hammerjs": "2.0.8",
|
||||
@ -368,20 +369,20 @@
|
||||
},
|
||||
"extensions/measurement-tracking": {
|
||||
"name": "@ohif/extension-measurement-tracking",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@ohif/ui": "3.13.0-beta.39",
|
||||
"@ohif/ui": "3.13.0-beta.41",
|
||||
"@xstate/react": "3.2.2",
|
||||
"xstate": "4.38.3",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@cornerstonejs/core": "4.19.0",
|
||||
"@cornerstonejs/tools": "4.19.0",
|
||||
"@ohif/core": "3.13.0-beta.39",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.39",
|
||||
"@ohif/extension-default": "3.13.0-beta.39",
|
||||
"@ohif/ui": "3.13.0-beta.39",
|
||||
"@cornerstonejs/core": "4.20.0",
|
||||
"@cornerstonejs/tools": "4.20.0",
|
||||
"@ohif/core": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.41",
|
||||
"@ohif/extension-default": "3.13.0-beta.41",
|
||||
"@ohif/ui": "3.13.0-beta.41",
|
||||
"classnames": "2.5.1",
|
||||
"dcmjs": "0.49.4",
|
||||
"lodash.debounce": "4.0.8",
|
||||
@ -394,14 +395,14 @@
|
||||
},
|
||||
"extensions/test-extension": {
|
||||
"name": "@ohif/extension-test",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"classnames": "2.5.1",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.13.0-beta.39",
|
||||
"@ohif/ui": "3.13.0-beta.39",
|
||||
"@ohif/core": "3.13.0-beta.41",
|
||||
"@ohif/ui": "3.13.0-beta.41",
|
||||
"dcmjs": "0.49.4",
|
||||
"dicom-parser": "1.8.21",
|
||||
"hammerjs": "2.0.8",
|
||||
@ -411,7 +412,7 @@
|
||||
},
|
||||
"extensions/tmtv": {
|
||||
"name": "@ohif/extension-tmtv",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"classnames": "2.5.1",
|
||||
@ -428,16 +429,16 @@
|
||||
},
|
||||
"extensions/usAnnotation": {
|
||||
"name": "@ohif/extension-ultrasound-pleura-bline",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/core": "4.19.0",
|
||||
"@cornerstonejs/tools": "4.19.0",
|
||||
"@ohif/core": "3.13.0-beta.39",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.39",
|
||||
"@ohif/extension-default": "3.13.0-beta.39",
|
||||
"@ohif/i18n": "3.13.0-beta.39",
|
||||
"@ohif/ui-next": "3.13.0-beta.39",
|
||||
"@cornerstonejs/core": "4.20.0",
|
||||
"@cornerstonejs/tools": "4.20.0",
|
||||
"@ohif/core": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.41",
|
||||
"@ohif/extension-default": "3.13.0-beta.41",
|
||||
"@ohif/i18n": "3.13.0-beta.41",
|
||||
"@ohif/ui-next": "3.13.0-beta.41",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.28.0",
|
||||
@ -476,7 +477,7 @@
|
||||
},
|
||||
"modes/basic": {
|
||||
"name": "@ohif/mode-basic",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
},
|
||||
@ -485,19 +486,19 @@
|
||||
"webpack-merge": "5.10.0",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.13.0-beta.39",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.39",
|
||||
"@ohif/extension-cornerstone-dicom-rt": "3.13.0-beta.39",
|
||||
"@ohif/extension-cornerstone-dicom-seg": "3.13.0-beta.39",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.39",
|
||||
"@ohif/extension-default": "3.13.0-beta.39",
|
||||
"@ohif/extension-dicom-pdf": "3.13.0-beta.39",
|
||||
"@ohif/extension-dicom-video": "3.13.0-beta.39",
|
||||
"@ohif/core": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone-dicom-rt": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone-dicom-seg": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.41",
|
||||
"@ohif/extension-default": "3.13.0-beta.41",
|
||||
"@ohif/extension-dicom-pdf": "3.13.0-beta.41",
|
||||
"@ohif/extension-dicom-video": "3.13.0-beta.41",
|
||||
},
|
||||
},
|
||||
"modes/basic-dev-mode": {
|
||||
"name": "@ohif/mode-basic-dev-mode",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"i18next": "17.3.1",
|
||||
@ -507,17 +508,17 @@
|
||||
"webpack-merge": "5.10.0",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.13.0-beta.39",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.39",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.39",
|
||||
"@ohif/extension-default": "3.13.0-beta.39",
|
||||
"@ohif/extension-dicom-pdf": "3.13.0-beta.39",
|
||||
"@ohif/extension-dicom-video": "3.13.0-beta.39",
|
||||
"@ohif/core": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.41",
|
||||
"@ohif/extension-default": "3.13.0-beta.41",
|
||||
"@ohif/extension-dicom-pdf": "3.13.0-beta.41",
|
||||
"@ohif/extension-dicom-video": "3.13.0-beta.41",
|
||||
},
|
||||
},
|
||||
"modes/basic-test-mode": {
|
||||
"name": "@ohif/mode-test",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"i18next": "17.3.1",
|
||||
@ -527,19 +528,19 @@
|
||||
"webpack-merge": "5.10.0",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.13.0-beta.39",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.39",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.39",
|
||||
"@ohif/extension-default": "3.13.0-beta.39",
|
||||
"@ohif/extension-dicom-pdf": "3.13.0-beta.39",
|
||||
"@ohif/extension-dicom-video": "3.13.0-beta.39",
|
||||
"@ohif/extension-measurement-tracking": "3.13.0-beta.39",
|
||||
"@ohif/extension-test": "3.13.0-beta.39",
|
||||
"@ohif/core": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.41",
|
||||
"@ohif/extension-default": "3.13.0-beta.41",
|
||||
"@ohif/extension-dicom-pdf": "3.13.0-beta.41",
|
||||
"@ohif/extension-dicom-video": "3.13.0-beta.41",
|
||||
"@ohif/extension-measurement-tracking": "3.13.0-beta.41",
|
||||
"@ohif/extension-test": "3.13.0-beta.41",
|
||||
},
|
||||
},
|
||||
"modes/longitudinal": {
|
||||
"name": "@ohif/mode-longitudinal",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"i18next": "17.3.1",
|
||||
@ -549,33 +550,33 @@
|
||||
"webpack-merge": "5.10.0",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.13.0-beta.39",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.39",
|
||||
"@ohif/extension-cornerstone-dicom-rt": "3.13.0-beta.39",
|
||||
"@ohif/extension-cornerstone-dicom-seg": "3.13.0-beta.39",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.39",
|
||||
"@ohif/extension-default": "3.13.0-beta.39",
|
||||
"@ohif/extension-dicom-pdf": "3.13.0-beta.39",
|
||||
"@ohif/extension-dicom-video": "3.13.0-beta.39",
|
||||
"@ohif/extension-measurement-tracking": "3.13.0-beta.39",
|
||||
"@ohif/mode-basic": "3.13.0-beta.39",
|
||||
"@ohif/core": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone-dicom-rt": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone-dicom-seg": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.41",
|
||||
"@ohif/extension-default": "3.13.0-beta.41",
|
||||
"@ohif/extension-dicom-pdf": "3.13.0-beta.41",
|
||||
"@ohif/extension-dicom-video": "3.13.0-beta.41",
|
||||
"@ohif/extension-measurement-tracking": "3.13.0-beta.41",
|
||||
"@ohif/mode-basic": "3.13.0-beta.41",
|
||||
},
|
||||
},
|
||||
"modes/microscopy": {
|
||||
"name": "@ohif/mode-microscopy",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"i18next": "17.3.1",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.13.0-beta.39",
|
||||
"@ohif/extension-dicom-microscopy": "3.13.0-beta.39",
|
||||
"@ohif/core": "3.13.0-beta.41",
|
||||
"@ohif/extension-dicom-microscopy": "3.13.0-beta.41",
|
||||
},
|
||||
},
|
||||
"modes/preclinical-4d": {
|
||||
"name": "@ohif/mode-preclinical-4d",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
},
|
||||
@ -594,7 +595,7 @@
|
||||
},
|
||||
"modes/segmentation": {
|
||||
"name": "@ohif/mode-segmentation",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"i18next": "17.3.1",
|
||||
@ -636,7 +637,7 @@
|
||||
},
|
||||
"modes/tmtv": {
|
||||
"name": "@ohif/mode-tmtv",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"i18next": "17.3.1",
|
||||
@ -657,14 +658,14 @@
|
||||
},
|
||||
"modes/usAnnotation": {
|
||||
"name": "@ohif/mode-ultrasound-pleura-bline",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/core": "4.19.0",
|
||||
"@cornerstonejs/tools": "4.19.0",
|
||||
"@ohif/core": "3.13.0-beta.39",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.39",
|
||||
"@ohif/extension-ultrasound-pleura-bline": "3.13.0-beta.39",
|
||||
"@cornerstonejs/core": "4.20.0",
|
||||
"@cornerstonejs/tools": "4.20.0",
|
||||
"@ohif/core": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.41",
|
||||
"@ohif/extension-ultrasound-pleura-bline": "3.13.0-beta.41",
|
||||
"i18next": "17.3.1",
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -693,34 +694,34 @@
|
||||
},
|
||||
"platform/app": {
|
||||
"name": "@ohif/app",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/codec-charls": "1.2.3",
|
||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "1.2.2",
|
||||
"@cornerstonejs/codec-openjpeg": "1.3.0",
|
||||
"@cornerstonejs/codec-openjph": "2.4.7",
|
||||
"@cornerstonejs/dicom-image-loader": "4.19.0",
|
||||
"@cornerstonejs/dicom-image-loader": "4.20.0",
|
||||
"@emotion/serialize": "1.3.3",
|
||||
"@ohif/core": "3.13.0-beta.39",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.39",
|
||||
"@ohif/extension-cornerstone-dicom-rt": "3.13.0-beta.39",
|
||||
"@ohif/extension-cornerstone-dicom-seg": "3.13.0-beta.39",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.39",
|
||||
"@ohif/extension-default": "3.13.0-beta.39",
|
||||
"@ohif/extension-dicom-microscopy": "3.13.0-beta.39",
|
||||
"@ohif/extension-dicom-pdf": "3.13.0-beta.39",
|
||||
"@ohif/extension-dicom-video": "3.13.0-beta.39",
|
||||
"@ohif/extension-test": "3.13.0-beta.39",
|
||||
"@ohif/extension-ultrasound-pleura-bline": "3.13.0-beta.39",
|
||||
"@ohif/i18n": "3.13.0-beta.39",
|
||||
"@ohif/mode-basic-dev-mode": "3.13.0-beta.39",
|
||||
"@ohif/mode-longitudinal": "3.13.0-beta.39",
|
||||
"@ohif/mode-microscopy": "3.13.0-beta.39",
|
||||
"@ohif/mode-test": "3.13.0-beta.39",
|
||||
"@ohif/mode-ultrasound-pleura-bline": "3.13.0-beta.39",
|
||||
"@ohif/ui": "3.13.0-beta.39",
|
||||
"@ohif/ui-next": "3.13.0-beta.39",
|
||||
"@ohif/core": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone-dicom-rt": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone-dicom-seg": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.41",
|
||||
"@ohif/extension-default": "3.13.0-beta.41",
|
||||
"@ohif/extension-dicom-microscopy": "3.13.0-beta.41",
|
||||
"@ohif/extension-dicom-pdf": "3.13.0-beta.41",
|
||||
"@ohif/extension-dicom-video": "3.13.0-beta.41",
|
||||
"@ohif/extension-test": "3.13.0-beta.41",
|
||||
"@ohif/extension-ultrasound-pleura-bline": "3.13.0-beta.41",
|
||||
"@ohif/i18n": "3.13.0-beta.41",
|
||||
"@ohif/mode-basic-dev-mode": "3.13.0-beta.41",
|
||||
"@ohif/mode-longitudinal": "3.13.0-beta.41",
|
||||
"@ohif/mode-microscopy": "3.13.0-beta.41",
|
||||
"@ohif/mode-test": "3.13.0-beta.41",
|
||||
"@ohif/mode-ultrasound-pleura-bline": "3.13.0-beta.41",
|
||||
"@ohif/ui": "3.13.0-beta.41",
|
||||
"@ohif/ui-next": "3.13.0-beta.41",
|
||||
"@svgr/webpack": "8.1.0",
|
||||
"@types/react": "18.3.23",
|
||||
"classnames": "2.5.1",
|
||||
@ -772,7 +773,7 @@
|
||||
},
|
||||
"platform/cli": {
|
||||
"name": "@ohif/cli",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"bin": {
|
||||
"ohif-cli": "src/index.js",
|
||||
},
|
||||
@ -796,7 +797,7 @@
|
||||
},
|
||||
"platform/core": {
|
||||
"name": "@ohif/core",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"dcmjs": "0.49.4",
|
||||
@ -821,16 +822,16 @@
|
||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "1.2.2",
|
||||
"@cornerstonejs/codec-openjpeg": "1.3.0",
|
||||
"@cornerstonejs/codec-openjph": "2.4.7",
|
||||
"@cornerstonejs/core": "4.19.0",
|
||||
"@cornerstonejs/dicom-image-loader": "4.19.0",
|
||||
"@ohif/ui": "3.13.0-beta.39",
|
||||
"@cornerstonejs/core": "4.20.0",
|
||||
"@cornerstonejs/dicom-image-loader": "4.20.0",
|
||||
"@ohif/ui": "3.13.0-beta.41",
|
||||
"cornerstone-math": "0.1.9",
|
||||
"dicom-parser": "1.8.21",
|
||||
},
|
||||
},
|
||||
"platform/i18n": {
|
||||
"name": "@ohif/i18n",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"i18next-locize-backend": "2.2.2",
|
||||
@ -855,7 +856,7 @@
|
||||
},
|
||||
"platform/ui": {
|
||||
"name": "@ohif/ui",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@testing-library/react": "13.4.0",
|
||||
"browser-detect": "0.2.28",
|
||||
@ -905,7 +906,7 @@
|
||||
},
|
||||
"platform/ui-next": {
|
||||
"name": "@ohif/ui-next",
|
||||
"version": "3.13.0-beta.39",
|
||||
"version": "3.13.0-beta.41",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-accordion": "1.2.11",
|
||||
"@radix-ui/react-checkbox": "1.3.2",
|
||||
@ -1240,9 +1241,9 @@
|
||||
|
||||
"@bcoe/v8-coverage": ["@bcoe/v8-coverage@0.2.3", "", {}, "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw=="],
|
||||
|
||||
"@cornerstonejs/adapters": ["@cornerstonejs/adapters@4.19.0", "", { "dependencies": { "@babel/runtime-corejs2": "7.26.10", "buffer": "6.0.3", "dcmjs": "0.49.4", "gl-matrix": "3.4.3", "ndarray": "1.0.19" }, "peerDependencies": { "@cornerstonejs/core": "4.19.0", "@cornerstonejs/tools": "4.19.0" } }, "sha512-321AA/3CNwe4bE7NHtKz1agTr6ckvxga1iM8ohIDPHL5GLc0Ooj4kRJMjEatTe+WmeDa4lug3VhV2FxmqCPjTg=="],
|
||||
"@cornerstonejs/adapters": ["@cornerstonejs/adapters@4.20.0", "", { "dependencies": { "@babel/runtime-corejs2": "7.26.10", "buffer": "6.0.3", "dcmjs": "0.49.4", "gl-matrix": "3.4.3", "ndarray": "1.0.19" }, "peerDependencies": { "@cornerstonejs/core": "4.20.0", "@cornerstonejs/tools": "4.20.0" } }, "sha512-OxplEaHadms6mZ5fX8o9zkMVw7rSjxP6+KRovBAqLXlXsM9hj7MgencWG2JX6SR2bUXvHVusiV9cdECcDMNvsg=="],
|
||||
|
||||
"@cornerstonejs/ai": ["@cornerstonejs/ai@4.19.0", "", { "dependencies": { "@babel/runtime-corejs2": "7.26.10", "buffer": "6.0.3", "dcmjs": "0.49.4", "gl-matrix": "3.4.3", "lodash.clonedeep": "4.5.0", "ndarray": "1.0.19", "onnxruntime-common": "1.17.1", "onnxruntime-web": "1.17.1" }, "peerDependencies": { "@cornerstonejs/core": "4.19.0", "@cornerstonejs/tools": "4.19.0" } }, "sha512-BWIbvUDLzmB0SEZhvFmhrhGEXdXplZkY5qEUfXCsbVcrUs9KsOrFrxLzTCRnTTnIX+Ybad9KoZWrwISmmMI3PQ=="],
|
||||
"@cornerstonejs/ai": ["@cornerstonejs/ai@4.20.0", "", { "dependencies": { "@babel/runtime-corejs2": "7.26.10", "buffer": "6.0.3", "dcmjs": "0.49.4", "gl-matrix": "3.4.3", "lodash.clonedeep": "4.5.0", "ndarray": "1.0.19", "onnxruntime-common": "1.17.1", "onnxruntime-web": "1.17.1" }, "peerDependencies": { "@cornerstonejs/core": "4.20.0", "@cornerstonejs/tools": "4.20.0" } }, "sha512-65wl8mXy/N6DUjLlNZvKLgWTGWVu4kWDupxNU5p7Pd3ZxU6RnbG6d3pcM30D/bcQEuUWLEQBDodtBeJEsxJxoA=="],
|
||||
|
||||
"@cornerstonejs/calculate-suv": ["@cornerstonejs/calculate-suv@1.1.0", "", {}, "sha512-Q9XraiDJif9aMFArD2iEuDO/HXbcRVCqB7KfaHgDrdTTjgDFovS91Psbdim7crypRSvE6dh/+HKeFNHdvNkA6w=="],
|
||||
|
||||
@ -1254,15 +1255,15 @@
|
||||
|
||||
"@cornerstonejs/codec-openjph": ["@cornerstonejs/codec-openjph@2.4.7", "", {}, "sha512-qvP4q4JDib7mi9r7LqKOwqz7YZ8gjtDX4ZCezeYf8+eb7MBXCz5uXAMeVF3yz9Axw4XiIMdB/pqXkm8tqCl13w=="],
|
||||
|
||||
"@cornerstonejs/core": ["@cornerstonejs/core@4.19.0", "", { "dependencies": { "@kitware/vtk.js": "34.15.1", "comlink": "4.4.2", "gl-matrix": "3.4.3", "loglevel": "1.9.2" } }, "sha512-t8v1JStDS+TJc50UA82BOCD0D9U4SD0VHuofRCXfPVd/LfDcLyUmcmoDuEeHTMCHGFm16j+nc3a/tqBiC0ZOxA=="],
|
||||
"@cornerstonejs/core": ["@cornerstonejs/core@4.20.0", "", { "dependencies": { "@kitware/vtk.js": "34.15.1", "comlink": "4.4.2", "gl-matrix": "3.4.3", "loglevel": "1.9.2" } }, "sha512-rcrctEIcyyAwQ6zcVt1wbYoTPyH6YNLNBOBB/aLeJZfLqGAfca+Cgf5K+KSGFJX1gZOdQZmYGmAF9P58B9PNVw=="],
|
||||
|
||||
"@cornerstonejs/dicom-image-loader": ["@cornerstonejs/dicom-image-loader@4.19.0", "", { "dependencies": { "@cornerstonejs/codec-charls": "1.2.3", "@cornerstonejs/codec-libjpeg-turbo-8bit": "1.2.2", "@cornerstonejs/codec-openjpeg": "1.3.0", "@cornerstonejs/codec-openjph": "2.4.7", "comlink": "4.4.2", "dicom-parser": "1.8.21", "jpeg-lossless-decoder-js": "2.1.2", "pako": "2.1.0", "uuid": "9.0.1" }, "peerDependencies": { "@cornerstonejs/core": "4.19.0" } }, "sha512-aW7tNpYAnLZcrx6x9pPs2lDm/K00/1vzlca7CBZ8ihTZcHb2qPpzEsIPZ3F48udzy/Onl/pcw8IDEWTGWDnRzg=="],
|
||||
"@cornerstonejs/dicom-image-loader": ["@cornerstonejs/dicom-image-loader@4.20.0", "", { "dependencies": { "@cornerstonejs/codec-charls": "1.2.3", "@cornerstonejs/codec-libjpeg-turbo-8bit": "1.2.2", "@cornerstonejs/codec-openjpeg": "1.3.0", "@cornerstonejs/codec-openjph": "2.4.7", "comlink": "4.4.2", "dicom-parser": "1.8.21", "jpeg-lossless-decoder-js": "2.1.2", "pako": "2.1.0", "uuid": "9.0.1" }, "peerDependencies": { "@cornerstonejs/core": "4.20.0" } }, "sha512-A7N2ekKEMEEKbw0QecbmgtL89LMpLZDkyzt2a97cZM9qyUdhdETyzL8m6guVtP10Ga5l9Aq9mFt2ifGtwTw0wA=="],
|
||||
|
||||
"@cornerstonejs/labelmap-interpolation": ["@cornerstonejs/labelmap-interpolation@4.19.0", "", { "dependencies": { "@itk-wasm/morphological-contour-interpolation": "1.1.0", "itk-wasm": "1.0.0-b.165" }, "peerDependencies": { "@cornerstonejs/core": "4.19.0", "@cornerstonejs/tools": "4.19.0", "@kitware/vtk.js": "34.15.1" } }, "sha512-nQgZhNACFsi1frS7kpFf8+wywweHZFQjYRZ27OuaILUhcd4c5Rcz+4t3mfnzdqTuxtg3+ewPG+7oKyCFIUMrgw=="],
|
||||
"@cornerstonejs/labelmap-interpolation": ["@cornerstonejs/labelmap-interpolation@4.20.0", "", { "dependencies": { "@itk-wasm/morphological-contour-interpolation": "1.1.0", "itk-wasm": "1.0.0-b.165" }, "peerDependencies": { "@cornerstonejs/core": "4.20.0", "@cornerstonejs/tools": "4.20.0", "@kitware/vtk.js": "34.15.1" } }, "sha512-VDUkvRZPCk98NkBFH0qFNEfjQoyYp2Th2+0KAJtDPeA0aqSPhugh14uJQ5uKEkDzZFUG/TUpeaHi1kldx6C5Gw=="],
|
||||
|
||||
"@cornerstonejs/polymorphic-segmentation": ["@cornerstonejs/polymorphic-segmentation@4.19.0", "", { "dependencies": { "@icr/polyseg-wasm": "0.4.0" }, "peerDependencies": { "@cornerstonejs/core": "4.19.0", "@cornerstonejs/tools": "4.19.0", "@kitware/vtk.js": "34.15.1" } }, "sha512-WmB938EDefT21YBYDC2rZReJyyI0fS9QsIoc9FkJOEky6GdDWbpFRulqz1X0XGbsr2jbAQUh9p1KJaraEtXkIw=="],
|
||||
"@cornerstonejs/polymorphic-segmentation": ["@cornerstonejs/polymorphic-segmentation@4.20.0", "", { "dependencies": { "@icr/polyseg-wasm": "0.4.0" }, "peerDependencies": { "@cornerstonejs/core": "4.20.0", "@cornerstonejs/tools": "4.20.0", "@kitware/vtk.js": "34.15.1" } }, "sha512-tsMqAd/GrBeEFB2WU2K+YsGXeaP/1yD635yO1udpG2dloRaJrvFiK1dFMFCBLK3Xd768ZS1nq/MZEel00+vYxA=="],
|
||||
|
||||
"@cornerstonejs/tools": ["@cornerstonejs/tools@4.19.0", "", { "dependencies": { "@types/offscreencanvas": "2019.7.3", "comlink": "4.4.2", "lodash.get": "4.4.2" }, "peerDependencies": { "@cornerstonejs/core": "4.19.0", "@kitware/vtk.js": "34.15.1", "@types/d3-array": "3.2.1", "@types/d3-interpolate": "3.0.4", "d3-array": "3.2.4", "d3-interpolate": "3.0.1", "gl-matrix": "3.4.3" } }, "sha512-yDK3I3U4tYDUWhZh3/NNBWWwqBd5X5qAfkn6tba5KMwKMLtjSm11s+Wg5O4BWOooW/XRflwj28VtE+Kgivlsag=="],
|
||||
"@cornerstonejs/tools": ["@cornerstonejs/tools@4.20.0", "", { "dependencies": { "@types/offscreencanvas": "2019.7.3", "comlink": "4.4.2", "lodash.get": "4.4.2" }, "peerDependencies": { "@cornerstonejs/core": "4.20.0", "@kitware/vtk.js": "34.15.1", "@types/d3-array": "3.2.1", "@types/d3-interpolate": "3.0.4", "d3-array": "3.2.4", "d3-interpolate": "3.0.1", "gl-matrix": "3.4.3" } }, "sha512-kphlW17eohBRk8MXEgdufM2t8MC5JqdlWUCfXu5rfg0KS1ut6iSWGAxFS+12noPR5qDzfVEYnD+4NkL37jg8pw=="],
|
||||
|
||||
"@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="],
|
||||
|
||||
|
||||
@ -46,8 +46,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/adapters": "4.19.0",
|
||||
"@cornerstonejs/core": "4.19.0",
|
||||
"@cornerstonejs/adapters": "4.20.0",
|
||||
"@cornerstonejs/core": "4.20.0",
|
||||
"@kitware/vtk.js": "34.15.1"
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,8 +46,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/adapters": "4.19.0",
|
||||
"@cornerstonejs/core": "4.19.0",
|
||||
"@cornerstonejs/adapters": "4.20.0",
|
||||
"@cornerstonejs/core": "4.20.0",
|
||||
"@kitware/vtk.js": "34.15.1"
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,9 +46,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/adapters": "4.19.0",
|
||||
"@cornerstonejs/core": "4.19.0",
|
||||
"@cornerstonejs/tools": "4.19.0",
|
||||
"@cornerstonejs/adapters": "4.20.0",
|
||||
"@cornerstonejs/core": "4.20.0",
|
||||
"@cornerstonejs/tools": "4.20.0",
|
||||
"classnames": "2.5.1"
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,8 +42,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/core": "4.19.0",
|
||||
"@cornerstonejs/tools": "4.19.0",
|
||||
"@cornerstonejs/core": "4.20.0",
|
||||
"@cornerstonejs/tools": "4.20.0",
|
||||
"classnames": "2.5.1"
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@
|
||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "1.2.2",
|
||||
"@cornerstonejs/codec-openjpeg": "1.3.0",
|
||||
"@cornerstonejs/codec-openjph": "2.4.7",
|
||||
"@cornerstonejs/dicom-image-loader": "4.19.0",
|
||||
"@cornerstonejs/dicom-image-loader": "4.20.0",
|
||||
"@ohif/core": "3.13.0-beta.41",
|
||||
"@ohif/ui": "3.13.0-beta.41",
|
||||
"dcmjs": "0.49.4",
|
||||
@ -53,12 +53,12 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/adapters": "4.19.0",
|
||||
"@cornerstonejs/ai": "4.19.0",
|
||||
"@cornerstonejs/core": "4.19.0",
|
||||
"@cornerstonejs/labelmap-interpolation": "4.19.0",
|
||||
"@cornerstonejs/polymorphic-segmentation": "4.19.0",
|
||||
"@cornerstonejs/tools": "4.19.0",
|
||||
"@cornerstonejs/adapters": "4.20.0",
|
||||
"@cornerstonejs/ai": "4.20.0",
|
||||
"@cornerstonejs/core": "4.20.0",
|
||||
"@cornerstonejs/labelmap-interpolation": "4.20.0",
|
||||
"@cornerstonejs/polymorphic-segmentation": "4.20.0",
|
||||
"@cornerstonejs/tools": "4.20.0",
|
||||
"@icr/polyseg-wasm": "0.4.0",
|
||||
"@itk-wasm/morphological-contour-interpolation": "1.1.0",
|
||||
"@kitware/vtk.js": "34.15.1",
|
||||
|
||||
@ -32,8 +32,8 @@
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@cornerstonejs/core": "4.19.0",
|
||||
"@cornerstonejs/tools": "4.19.0",
|
||||
"@cornerstonejs/core": "4.20.0",
|
||||
"@cornerstonejs/tools": "4.20.0",
|
||||
"@ohif/core": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.41",
|
||||
"@ohif/extension-default": "3.13.0-beta.41",
|
||||
|
||||
@ -42,8 +42,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/core": "4.19.0",
|
||||
"@cornerstonejs/tools": "4.19.0",
|
||||
"@cornerstonejs/core": "4.20.0",
|
||||
"@cornerstonejs/tools": "4.20.0",
|
||||
"@ohif/core": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.41",
|
||||
"@ohif/extension-default": "3.13.0-beta.41",
|
||||
|
||||
@ -34,8 +34,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.28.2",
|
||||
"@cornerstonejs/core": "4.19.0",
|
||||
"@cornerstonejs/tools": "4.19.0",
|
||||
"@cornerstonejs/core": "4.20.0",
|
||||
"@cornerstonejs/tools": "4.20.0",
|
||||
"@ohif/core": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.41",
|
||||
"@ohif/extension-ultrasound-pleura-bline": "3.13.0-beta.41",
|
||||
|
||||
@ -76,7 +76,11 @@
|
||||
"lerna:cache": "./netlify-lerna-cache.sh",
|
||||
"lerna:restore": "./netlify-lerna-restore.sh",
|
||||
"lerna:customVersion": "node version.mjs",
|
||||
"link-list": "npm ls --depth=0 --link=true"
|
||||
"link-list": "npm ls --depth=0 --link=true",
|
||||
"cs3d:checkout": "cd libs/@cornerstonejs && git fetch && git checkout",
|
||||
"cs3d:build": "cd libs/@cornerstonejs && yarn install && yarn run build:esm",
|
||||
"cs3d:link": "node libs/@cornerstonejs/scripts/link-ohif-cornerstone-node-modules.mjs .",
|
||||
"cs3d:unlink": "node libs/@cornerstonejs/scripts/unlink-ohif-cornerstone-node-modules.mjs ."
|
||||
},
|
||||
"dependencies": {
|
||||
"execa": "8.0.1"
|
||||
|
||||
@ -54,7 +54,7 @@
|
||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "1.2.2",
|
||||
"@cornerstonejs/codec-openjpeg": "1.3.0",
|
||||
"@cornerstonejs/codec-openjph": "2.4.7",
|
||||
"@cornerstonejs/dicom-image-loader": "4.19.0",
|
||||
"@cornerstonejs/dicom-image-loader": "4.20.0",
|
||||
"@emotion/serialize": "1.3.3",
|
||||
"@ohif/core": "3.13.0-beta.41",
|
||||
"@ohif/extension-cornerstone": "3.13.0-beta.41",
|
||||
|
||||
@ -37,8 +37,8 @@
|
||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "1.2.2",
|
||||
"@cornerstonejs/codec-openjpeg": "1.3.0",
|
||||
"@cornerstonejs/codec-openjph": "2.4.7",
|
||||
"@cornerstonejs/core": "4.19.0",
|
||||
"@cornerstonejs/dicom-image-loader": "4.19.0",
|
||||
"@cornerstonejs/core": "4.20.0",
|
||||
"@cornerstonejs/dicom-image-loader": "4.20.0",
|
||||
"@ohif/ui": "3.13.0-beta.41",
|
||||
"cornerstone-math": "0.1.9",
|
||||
"dicom-parser": "1.8.21"
|
||||
|
||||
141
platform/docs/docs/development/cs3d-integration.md
Normal file
141
platform/docs/docs/development/cs3d-integration.md
Normal file
@ -0,0 +1,141 @@
|
||||
---
|
||||
sidebar_position: 10
|
||||
sidebar_label: CS3D Integration Testing
|
||||
title: Cornerstone3D Integration Testing
|
||||
summary: How to test OHIF against specific Cornerstone3D branches or versions, both locally and in CI.
|
||||
---
|
||||
|
||||
# Cornerstone3D Integration Testing
|
||||
|
||||
OHIF can be tested against a specific Cornerstone3D (CS3D) branch or published version.
|
||||
This is useful for:
|
||||
|
||||
- Validating OHIF changes against unreleased CS3D features
|
||||
- Upgrading CS3D versions with automated testing
|
||||
- Debugging issues that span both repositories
|
||||
|
||||
## CI Workflow
|
||||
|
||||
The **Playwright Tests** workflow in GitHub Actions has built-in CS3D integration support.
|
||||
|
||||
### Triggering via Label
|
||||
|
||||
1. Open a PR targeting `master` or `release/*`
|
||||
2. Add the **`ohif-integration`** label
|
||||
3. The workflow will automatically test against the latest `4.x` CS3D release from npm
|
||||
|
||||
To target a specific CS3D branch or version, add a `CS3D_REF` line anywhere in the PR
|
||||
description body:
|
||||
|
||||
```
|
||||
CS3D_REF: main
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
CS3D_REF: 4.18.2
|
||||
```
|
||||
|
||||
The same branch and version formats from the table below are supported. If no `CS3D_REF`
|
||||
line is found in the PR body, it defaults to `4.x`.
|
||||
|
||||
### Triggering via workflow_dispatch
|
||||
|
||||
Use **Actions > Playwright Tests > Run workflow** and set the `cs3d_ref` input:
|
||||
|
||||
| Input | Behavior |
|
||||
|-------|----------|
|
||||
| `4.x` (default) | Install latest published 4.x release |
|
||||
| `4.18.2` | Install exact version 4.18.2 |
|
||||
| `4.18.2-beta.3` | Install exact prerelease |
|
||||
| `4.17.x` | Install latest 4.17.x release |
|
||||
| `main` | Clone and build CS3D `main` branch from source |
|
||||
| `myorg:feat/foo` | Clone from `github.com/myorg/cornerstone3D.git`, branch `feat/foo` |
|
||||
|
||||
### Branch vs Version Behavior
|
||||
|
||||
**Version path** (e.g., `4.x`, `4.18.2`):
|
||||
- Installs OHIF dependencies normally
|
||||
- Updates all `@cornerstonejs/*` versions in workspace package.json files
|
||||
- Re-installs to fetch the specified versions from npm
|
||||
- Runs all tests
|
||||
- Builds and deploys a Netlify preview
|
||||
- The tested version is logged in workflow annotations
|
||||
|
||||
**Branch path** (e.g., `main`, `myorg:feat/foo`):
|
||||
- Clones CS3D into `libs/@cornerstonejs`
|
||||
- Builds CS3D from source (`build:esm`)
|
||||
- Links built packages into OHIF's `node_modules`
|
||||
- Runs all tests
|
||||
- Builds and deploys a Netlify preview
|
||||
- **Intentionally fails** at the end to prevent merging — re-run with a published version before merge
|
||||
|
||||
### Version Commit on Merge
|
||||
|
||||
The CS3D version update is **not committed** during the PR workflow. The tested version is
|
||||
recorded in workflow annotations (`::notice::` messages). To apply the version update:
|
||||
|
||||
1. After the PR is approved and the version test passes, note the tested version from the logs
|
||||
2. Run `node .scripts/cs3d-set-version.mjs <version>` locally or as part of the merge process
|
||||
3. Commit the updated package.json files
|
||||
|
||||
## Local Development
|
||||
|
||||
### Setting Up a CS3D Worktree
|
||||
|
||||
For local development, use the CS3D repo's `link:cs3d` script to create a git worktree.
|
||||
This shares a single git repository across multiple OHIF checkouts:
|
||||
|
||||
```bash
|
||||
# From your cornerstone3D repo:
|
||||
bun run link:cs3d /path/to/ohif main
|
||||
# or with a specific branch:
|
||||
bun run link:cs3d /path/to/ohif origin:feat/my-feature
|
||||
```
|
||||
|
||||
This creates `libs/@cornerstonejs` as a worktree and generates `link-cs3d.js` / `unlink-cs3d.js`
|
||||
helper scripts. See the [Local Linking](./link.md) docs for more on the linking workflow.
|
||||
|
||||
### Package Scripts
|
||||
|
||||
Once `libs/@cornerstonejs` exists (via worktree or clone):
|
||||
|
||||
```bash
|
||||
# Switch branches in the existing worktree
|
||||
yarn cs3d:checkout <branch-name>
|
||||
|
||||
# Install dependencies and build ESM
|
||||
yarn cs3d:build
|
||||
|
||||
# Symlink CS3D packages into node_modules/@cornerstonejs
|
||||
yarn cs3d:link
|
||||
|
||||
# Remove symlinks and restore packages from npm registry
|
||||
yarn cs3d:unlink
|
||||
```
|
||||
|
||||
:::note
|
||||
`cs3d:checkout` requires `libs/@cornerstonejs` to already exist. It runs
|
||||
`git fetch && git checkout` inside that directory.
|
||||
:::
|
||||
|
||||
### Wildcard Versions
|
||||
|
||||
The `cs3d-resolve-version.mjs` script resolves patterns like `4.x` or `4.17.x`:
|
||||
|
||||
```bash
|
||||
node .scripts/cs3d-resolve-version.mjs 4.x
|
||||
# prints: 4.19.1 (or whatever the latest 4.x release is)
|
||||
```
|
||||
|
||||
### Updating All CS3D Versions
|
||||
|
||||
```bash
|
||||
node .scripts/cs3d-set-version.mjs 4.19.0
|
||||
# Updates all @cornerstonejs/* dependencies across the workspace
|
||||
```
|
||||
|
||||
This updates the 8 main CS3D packages (adapters, ai, core, dicom-image-loader,
|
||||
labelmap-interpolation, nifti-volume-loader, polymorphic-segmentation, tools)
|
||||
but not codec packages.
|
||||
@ -19,7 +19,7 @@ test.describe('3D four up Test', async () => {
|
||||
|
||||
await attemptAction(() => reduce3DViewportSize(page), 10, 100);
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
await mainToolbarPageObject.waitForVolumeLoad();
|
||||
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
|
||||
@ -17,7 +17,7 @@ test.describe('3D main Test', async () => {
|
||||
test('should render 3D main correctly.', async ({ page, mainToolbarPageObject }) => {
|
||||
await mainToolbarPageObject.layoutSelection.threeDMain.click();
|
||||
await attemptAction(() => reduce3DViewportSize(page), 10, 100);
|
||||
await page.waitForTimeout(5000);
|
||||
await mainToolbarPageObject.waitForVolumeLoad();
|
||||
await checkForScreenshot(page, page, screenShotPaths.threeDMain.threeDMainDisplayedCorrectly);
|
||||
});
|
||||
});
|
||||
|
||||
@ -17,7 +17,7 @@ test.describe('3D only Test', async () => {
|
||||
test('should render 3D only correctly.', async ({ page, mainToolbarPageObject }) => {
|
||||
await mainToolbarPageObject.layoutSelection.threeDOnly.click();
|
||||
await attemptAction(() => reduce3DViewportSize(page), 10, 100);
|
||||
await page.waitForTimeout(5000);
|
||||
await mainToolbarPageObject.waitForVolumeLoad();
|
||||
// Use a 4 percent diff pixel ratio to account for slight color differences in the 3D viewport
|
||||
await checkForScreenshot({
|
||||
page,
|
||||
|
||||
@ -18,7 +18,7 @@ test.describe('3D primary Test', async () => {
|
||||
await mainToolbarPageObject.layoutSelection.threeDPrimary.click();
|
||||
|
||||
await attemptAction(() => reduce3DViewportSize(page), 10, 100);
|
||||
await page.waitForTimeout(5000);
|
||||
await mainToolbarPageObject.waitForVolumeLoad();
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
page,
|
||||
|
||||
@ -28,7 +28,7 @@ test('should display the arrow tool and allow free-form text to be entered', asy
|
||||
|
||||
await DOMOverlayPageObject.viewport.measurementTracking.confirm.click();
|
||||
|
||||
await page.waitForTimeout(2000);
|
||||
await mainToolbarPageObject.waitForVolumeLoad();
|
||||
|
||||
await checkForScreenshot({
|
||||
page,
|
||||
@ -42,7 +42,7 @@ test('should display the arrow tool and allow free-form text to be entered', asy
|
||||
|
||||
await DOMOverlayPageObject.dialog.input.fillAndSave('Neil Peart was the drummer for Rush');
|
||||
|
||||
await page.waitForTimeout(2000);
|
||||
await mainToolbarPageObject.waitForVolumeLoad();
|
||||
|
||||
await checkForScreenshot({
|
||||
page,
|
||||
@ -56,7 +56,7 @@ test('should display the arrow tool and allow free-form text to be entered', asy
|
||||
.nthMeasurement(0)
|
||||
.actions.rename('Drummer annotation arrow');
|
||||
|
||||
await page.waitForTimeout(2000);
|
||||
await mainToolbarPageObject.waitForVolumeLoad();
|
||||
|
||||
await checkForScreenshot({
|
||||
page,
|
||||
|
||||
@ -39,6 +39,7 @@ test('should display the long series name properly within the series select butt
|
||||
const mode = 'viewer';
|
||||
await visitStudy(page, studyInstanceUID, mode, 2000);
|
||||
|
||||
await mainToolbarPageObject.waitForVolumeLoad();
|
||||
await mainToolbarPageObject.moreTools.tagBrowser.click();
|
||||
const dicomTagBrowser = DOMOverlayPageObject.dialog.dicomTagBrowser;
|
||||
|
||||
|
||||
@ -8,5 +8,6 @@ test.beforeEach(async ({ page }) => {
|
||||
|
||||
test('should invert the image', async ({ page, mainToolbarPageObject }) => {
|
||||
await mainToolbarPageObject.moreTools.invert.click();
|
||||
await mainToolbarPageObject.waitForVolumeLoad();
|
||||
await checkForScreenshot(page, page, screenShotPaths.invert.invertDisplayedCorrectly);
|
||||
});
|
||||
|
||||
@ -14,8 +14,7 @@ test('should launch MPR with unhydrated RTSTRUCT chosen from the data overlay me
|
||||
}) => {
|
||||
await mainToolbarPageObject.layoutSelection.MPR.click();
|
||||
|
||||
// Wait 5 seconds for MPR to load. This is necessary in particular when screen shots are added or replaced.
|
||||
await page.waitForTimeout(10000);
|
||||
await mainToolbarPageObject.waitForVolumeLoad();
|
||||
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
@ -35,8 +34,7 @@ test('should launch MPR with unhydrated RTSTRUCT chosen from the data overlay me
|
||||
// Adding an overlay should not show the LOAD button.
|
||||
await assertNumberOfModalityLoadBadges({ page, expectedCount: 0 });
|
||||
|
||||
// Wait 5 seconds for RT to load. This is necessary in particular when screen shots are added or replaced.
|
||||
await page.waitForTimeout(5000);
|
||||
await mainToolbarPageObject.waitForVolumeLoad();
|
||||
|
||||
await checkForScreenshot({
|
||||
page,
|
||||
|
||||
@ -10,6 +10,7 @@ test.beforeEach(async ({ page }) => {
|
||||
|
||||
test('should display multiple segmentation overlays (both SEG and RT)', async ({
|
||||
page,
|
||||
mainToolbarPageObject,
|
||||
rightPanelPageObject,
|
||||
viewportPageObject,
|
||||
}) => {
|
||||
@ -20,24 +21,21 @@ test('should display multiple segmentation overlays (both SEG and RT)', async ({
|
||||
await dataOverlayPageObject.toggle();
|
||||
await dataOverlayPageObject.addSegmentation('2d-tta_nnU-Net_Segmentation');
|
||||
|
||||
// A short wait after each overlay is selected to ensure it loads.
|
||||
await page.waitForTimeout(5000);
|
||||
await mainToolbarPageObject.waitForVolumeLoad();
|
||||
|
||||
// Adding an overlay should not show the LOAD button.
|
||||
assertNumberOfModalityLoadBadges({ page, expectedCount: 0 });
|
||||
|
||||
await dataOverlayPageObject.addSegmentation('Segmentation');
|
||||
|
||||
// A short wait after each overlay is selected to ensure it loads.
|
||||
await page.waitForTimeout(5000);
|
||||
await mainToolbarPageObject.waitForVolumeLoad();
|
||||
|
||||
// Adding an overlay should not show the LOAD button.
|
||||
assertNumberOfModalityLoadBadges({ page, expectedCount: 0 });
|
||||
|
||||
await dataOverlayPageObject.addSegmentation('3d_lowres-tta_nnU-Net_Segmentation');
|
||||
|
||||
// A short wait after each overlay is selected to ensure it loads.
|
||||
await page.waitForTimeout(5000);
|
||||
await mainToolbarPageObject.waitForVolumeLoad();
|
||||
|
||||
// Adding an overlay should not show the LOAD button.
|
||||
assertNumberOfModalityLoadBadges({ page, expectedCount: 0 });
|
||||
@ -61,7 +59,7 @@ test('should display multiple segmentation overlays (both SEG and RT)', async ({
|
||||
// Navigate to image 56.
|
||||
await press({ page, key: 'ArrowDown', nTimes: 55 });
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
await mainToolbarPageObject.waitForVolumeLoad();
|
||||
|
||||
await checkForScreenshot({
|
||||
page,
|
||||
@ -73,8 +71,7 @@ test('should display multiple segmentation overlays (both SEG and RT)', async ({
|
||||
|
||||
await dataOverlayPageObject.addSegmentation('Series 3 - RTSTRUCT');
|
||||
|
||||
// A short wait after each overlay is selected to ensure it loads.
|
||||
await page.waitForTimeout(5000);
|
||||
await mainToolbarPageObject.waitForVolumeLoad();
|
||||
|
||||
// Adding an overlay should not show the LOAD button.
|
||||
assertNumberOfModalityLoadBadges({ page, expectedCount: 0 });
|
||||
|
||||
@ -24,7 +24,7 @@ test('should launch MPR with unhydrated RTSTRUCT chosen from the data overlay me
|
||||
// Hide the overlay menu.
|
||||
await dataOverlayPageObject.toggle();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
await mainToolbarPageObject.waitForVolumeLoad();
|
||||
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
@ -34,7 +34,7 @@ test('should launch MPR with unhydrated RTSTRUCT chosen from the data overlay me
|
||||
|
||||
await mainToolbarPageObject.layoutSelection.MPR.click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
await mainToolbarPageObject.waitForVolumeLoad();
|
||||
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { test } from 'playwright-test-coverage';
|
||||
import { visitStudy, checkForScreenshot, screenShotPaths } from './utils';
|
||||
import { test, visitStudy, checkForScreenshot, screenShotPaths } from './utils';
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
const studyInstanceUID =
|
||||
@ -8,7 +7,8 @@ test.beforeEach(async ({ page }) => {
|
||||
await visitStudy(page, studyInstanceUID, mode, 10000);
|
||||
});
|
||||
|
||||
test('should properly display MPR for MR', async ({ page }) => {
|
||||
test('should properly display MPR for MR', async ({ page, mainToolbarPageObject }) => {
|
||||
await mainToolbarPageObject.waitForVolumeLoad();
|
||||
await page.getByTestId('side-panel-header-right').click();
|
||||
// await page.getByTestId('study-browser-thumbnail-no-image').dblclick();
|
||||
await checkForScreenshot(page, page, screenShotPaths.mpr2.mprDisplayedCorrectly);
|
||||
|
||||
@ -7,6 +7,11 @@ export class MainToolbarPageObject {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
async waitForVolumeLoad(): Promise<void> {
|
||||
await this.page.waitForTimeout(2000);
|
||||
await this.page.waitForLoadState('networkidle', { timeout: 120000 });
|
||||
}
|
||||
|
||||
get crosshairs() {
|
||||
const button = this.page.getByTestId('Crosshairs');
|
||||
return {
|
||||
@ -18,6 +23,7 @@ export class MainToolbarPageObject {
|
||||
}
|
||||
get layoutSelection() {
|
||||
const page = this.page;
|
||||
const self = this;
|
||||
|
||||
const button = page.getByTestId('Layout');
|
||||
const layoutSelection = {
|
||||
@ -46,6 +52,7 @@ export class MainToolbarPageObject {
|
||||
async click() {
|
||||
await layoutSelection.click();
|
||||
await button.click();
|
||||
await self.waitForVolumeLoad();
|
||||
},
|
||||
};
|
||||
},
|
||||
@ -56,6 +63,7 @@ export class MainToolbarPageObject {
|
||||
async click() {
|
||||
await layoutSelection.click();
|
||||
await button.click();
|
||||
await self.waitForVolumeLoad();
|
||||
},
|
||||
};
|
||||
},
|
||||
@ -66,6 +74,7 @@ export class MainToolbarPageObject {
|
||||
async click() {
|
||||
await layoutSelection.click();
|
||||
await button.click();
|
||||
await self.waitForVolumeLoad();
|
||||
},
|
||||
};
|
||||
},
|
||||
@ -76,6 +85,7 @@ export class MainToolbarPageObject {
|
||||
async click() {
|
||||
await layoutSelection.click();
|
||||
await button.click();
|
||||
await self.waitForVolumeLoad();
|
||||
},
|
||||
};
|
||||
},
|
||||
@ -86,6 +96,7 @@ export class MainToolbarPageObject {
|
||||
async click() {
|
||||
await layoutSelection.click();
|
||||
await button.click();
|
||||
await self.waitForVolumeLoad();
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
import { execa } from 'execa';
|
||||
import semver from 'semver';
|
||||
import fs from 'fs/promises';
|
||||
import { spawnSync } from 'child_process';
|
||||
|
||||
async function run() {
|
||||
// Log build context for diagnosing GitHub build issues (OHIF/CS3D branch and version)
|
||||
spawnSync('node', ['.scripts/log-build-context.mjs'], { stdio: 'inherit', cwd: process.cwd() });
|
||||
|
||||
const { stdout: branchName } = await execa('git', ['rev-parse', '--abbrev-ref', 'HEAD']);
|
||||
console.log('Current branch:', branchName);
|
||||
|
||||
|
||||
56
yarn.lock
56
yarn.lock
@ -1946,10 +1946,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||
|
||||
"@cornerstonejs/adapters@4.19.0":
|
||||
version "4.19.0"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-4.19.0.tgz#6e1035a0617ddcb6938eaf6100ef5f86e7df398b"
|
||||
integrity sha512-321AA/3CNwe4bE7NHtKz1agTr6ckvxga1iM8ohIDPHL5GLc0Ooj4kRJMjEatTe+WmeDa4lug3VhV2FxmqCPjTg==
|
||||
"@cornerstonejs/adapters@4.20.0":
|
||||
version "4.20.0"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-4.20.0.tgz#94e21f2955d87d2c0ba47ebedaad77ee621f7ecf"
|
||||
integrity sha512-OxplEaHadms6mZ5fX8o9zkMVw7rSjxP6+KRovBAqLXlXsM9hj7MgencWG2JX6SR2bUXvHVusiV9cdECcDMNvsg==
|
||||
dependencies:
|
||||
"@babel/runtime-corejs2" "7.26.10"
|
||||
buffer "6.0.3"
|
||||
@ -1957,10 +1957,10 @@
|
||||
gl-matrix "3.4.3"
|
||||
ndarray "1.0.19"
|
||||
|
||||
"@cornerstonejs/ai@4.19.0":
|
||||
version "4.19.0"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/ai/-/ai-4.19.0.tgz#04d44c620632c095fda5987c7a5d07e2c26a9389"
|
||||
integrity sha512-BWIbvUDLzmB0SEZhvFmhrhGEXdXplZkY5qEUfXCsbVcrUs9KsOrFrxLzTCRnTTnIX+Ybad9KoZWrwISmmMI3PQ==
|
||||
"@cornerstonejs/ai@4.20.0":
|
||||
version "4.20.0"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/ai/-/ai-4.20.0.tgz#9ee423cc99c2122360c8359f643a8e470717fcf5"
|
||||
integrity sha512-65wl8mXy/N6DUjLlNZvKLgWTGWVu4kWDupxNU5p7Pd3ZxU6RnbG6d3pcM30D/bcQEuUWLEQBDodtBeJEsxJxoA==
|
||||
dependencies:
|
||||
"@babel/runtime-corejs2" "7.26.10"
|
||||
buffer "6.0.3"
|
||||
@ -1996,20 +1996,20 @@
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-openjph/-/codec-openjph-2.4.7.tgz#784394d05d8cf735640e9c3baa206535ee8e0376"
|
||||
integrity sha512-qvP4q4JDib7mi9r7LqKOwqz7YZ8gjtDX4ZCezeYf8+eb7MBXCz5uXAMeVF3yz9Axw4XiIMdB/pqXkm8tqCl13w==
|
||||
|
||||
"@cornerstonejs/core@4.19.0":
|
||||
version "4.19.0"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-4.19.0.tgz#45406e3ae5dfb07727b090f9e33b234c035b31c9"
|
||||
integrity sha512-t8v1JStDS+TJc50UA82BOCD0D9U4SD0VHuofRCXfPVd/LfDcLyUmcmoDuEeHTMCHGFm16j+nc3a/tqBiC0ZOxA==
|
||||
"@cornerstonejs/core@4.20.0":
|
||||
version "4.20.0"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-4.20.0.tgz#9381f113879dd9fc2847c8e4d9e624602751bbef"
|
||||
integrity sha512-rcrctEIcyyAwQ6zcVt1wbYoTPyH6YNLNBOBB/aLeJZfLqGAfca+Cgf5K+KSGFJX1gZOdQZmYGmAF9P58B9PNVw==
|
||||
dependencies:
|
||||
"@kitware/vtk.js" "34.15.1"
|
||||
comlink "4.4.2"
|
||||
gl-matrix "3.4.3"
|
||||
loglevel "1.9.2"
|
||||
|
||||
"@cornerstonejs/dicom-image-loader@4.19.0":
|
||||
version "4.19.0"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-4.19.0.tgz#426d65626d1c68208ab22d85763da528a16c118e"
|
||||
integrity sha512-aW7tNpYAnLZcrx6x9pPs2lDm/K00/1vzlca7CBZ8ihTZcHb2qPpzEsIPZ3F48udzy/Onl/pcw8IDEWTGWDnRzg==
|
||||
"@cornerstonejs/dicom-image-loader@4.20.0":
|
||||
version "4.20.0"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-4.20.0.tgz#bf6425f2829268311b3fbd6a36bb584bdc431fc6"
|
||||
integrity sha512-A7N2ekKEMEEKbw0QecbmgtL89LMpLZDkyzt2a97cZM9qyUdhdETyzL8m6guVtP10Ga5l9Aq9mFt2ifGtwTw0wA==
|
||||
dependencies:
|
||||
"@cornerstonejs/codec-charls" "1.2.3"
|
||||
"@cornerstonejs/codec-libjpeg-turbo-8bit" "1.2.2"
|
||||
@ -2021,25 +2021,25 @@
|
||||
pako "2.1.0"
|
||||
uuid "9.0.1"
|
||||
|
||||
"@cornerstonejs/labelmap-interpolation@4.19.0":
|
||||
version "4.19.0"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/labelmap-interpolation/-/labelmap-interpolation-4.19.0.tgz#101cb6f7f7eb64ee9a2933cfe2ef71af66abfa05"
|
||||
integrity sha512-nQgZhNACFsi1frS7kpFf8+wywweHZFQjYRZ27OuaILUhcd4c5Rcz+4t3mfnzdqTuxtg3+ewPG+7oKyCFIUMrgw==
|
||||
"@cornerstonejs/labelmap-interpolation@4.20.0":
|
||||
version "4.20.0"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/labelmap-interpolation/-/labelmap-interpolation-4.20.0.tgz#152fea1a574f825bed2cd0a69013ebb4405dcda7"
|
||||
integrity sha512-VDUkvRZPCk98NkBFH0qFNEfjQoyYp2Th2+0KAJtDPeA0aqSPhugh14uJQ5uKEkDzZFUG/TUpeaHi1kldx6C5Gw==
|
||||
dependencies:
|
||||
"@itk-wasm/morphological-contour-interpolation" "1.1.0"
|
||||
itk-wasm "1.0.0-b.165"
|
||||
|
||||
"@cornerstonejs/polymorphic-segmentation@4.19.0":
|
||||
version "4.19.0"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/polymorphic-segmentation/-/polymorphic-segmentation-4.19.0.tgz#79491ee8293c53008973286b59bc38b88426ebba"
|
||||
integrity sha512-WmB938EDefT21YBYDC2rZReJyyI0fS9QsIoc9FkJOEky6GdDWbpFRulqz1X0XGbsr2jbAQUh9p1KJaraEtXkIw==
|
||||
"@cornerstonejs/polymorphic-segmentation@4.20.0":
|
||||
version "4.20.0"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/polymorphic-segmentation/-/polymorphic-segmentation-4.20.0.tgz#d4981f9df051217cddf6a69730386339fe69b5d2"
|
||||
integrity sha512-tsMqAd/GrBeEFB2WU2K+YsGXeaP/1yD635yO1udpG2dloRaJrvFiK1dFMFCBLK3Xd768ZS1nq/MZEel00+vYxA==
|
||||
dependencies:
|
||||
"@icr/polyseg-wasm" "0.4.0"
|
||||
|
||||
"@cornerstonejs/tools@4.19.0":
|
||||
version "4.19.0"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-4.19.0.tgz#1db6bd62988c6fd4fb2497bedadffdbe16109c04"
|
||||
integrity sha512-yDK3I3U4tYDUWhZh3/NNBWWwqBd5X5qAfkn6tba5KMwKMLtjSm11s+Wg5O4BWOooW/XRflwj28VtE+Kgivlsag==
|
||||
"@cornerstonejs/tools@4.20.0":
|
||||
version "4.20.0"
|
||||
resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-4.20.0.tgz#58d834f80513689c354e052b9641516a62d24ad8"
|
||||
integrity sha512-kphlW17eohBRk8MXEgdufM2t8MC5JqdlWUCfXu5rfg0KS1ut6iSWGAxFS+12noPR5qDzfVEYnD+4NkL37jg8pw==
|
||||
dependencies:
|
||||
"@types/offscreencanvas" "2019.7.3"
|
||||
comlink "4.4.2"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user