Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/build-windows.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ jobs:
uses: actions/setup-node@v6
with:
node-version: '24'
cache: 'yarn'

- name: Enable Corepack
run: corepack enable
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/lint-and-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ jobs:
uses: actions/setup-node@v6
with:
node-version: '24'
cache: 'yarn'

- name: Enable Corepack
run: corepack enable
Expand Down Expand Up @@ -72,7 +71,6 @@ jobs:
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node_version }}
cache: 'yarn'

- name: Cache node_modules
uses: actions/cache@v5
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/publish-prerelease.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ jobs:
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node_version }}
cache: 'yarn'

- name: Prepare Environment
run: |
Expand Down Expand Up @@ -54,7 +53,6 @@ jobs:
uses: actions/setup-node@v6
with:
node-version: 24
cache: 'yarn'

- name: Check release is desired
id: do-publish
Expand Down
893 changes: 0 additions & 893 deletions .yarn/releases/yarn-4.1.1.cjs

This file was deleted.

2 changes: 0 additions & 2 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,3 @@ enableGlobalCache: false
httpTimeout: 100000

nodeLinker: node-modules

yarnPath: .yarn/releases/yarn-4.1.1.cjs
4 changes: 2 additions & 2 deletions apps/_boilerplate/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
]
},
"devDependencies": {
"lerna": "^6.6.1",
"rimraf": "^5.0.5"
"lerna": "^9.0.7",
"rimraf": "^6.1.3"
}
}
2 changes: 1 addition & 1 deletion apps/_boilerplate/packages/generic/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@
]
},
"devDependencies": {
"rimraf": "^5.0.5"
"rimraf": "^6.1.3"
}
}
4 changes: 2 additions & 2 deletions apps/appcontainer-node/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
]
},
"devDependencies": {
"lerna": "^6.6.1",
"rimraf": "^5.0.5"
"lerna": "^9.0.7",
"rimraf": "^6.1.3"
}
}
6 changes: 3 additions & 3 deletions apps/appcontainer-node/packages/generic/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
"dependencies": {
"@sofie-package-manager/api": "1.53.0",
"@sofie-package-manager/worker": "1.53.0",
"underscore": "^1.12.0"
"underscore": "^1.13.8"
},
"devDependencies": {
"@types/underscore": "^1.10.24",
"rimraf": "^5.0.5"
"@types/underscore": "^1.13.0",
"rimraf": "^6.1.3"
},
"prettier": "@sofie-automation/code-standard-preset/.prettierrc.json",
"engines": {
Expand Down
12 changes: 6 additions & 6 deletions apps/html-renderer/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,18 @@
"@html-renderer/generic": "1.53.0",
"@sofie-automation/shared-lib": "1.52.0-nightly-release52-20250110-120624-cb59dd9.0",
"@sofie-package-manager/api": "1.53.0",
"portfinder": "^1.0.32",
"tslib": "^2.1.0",
"ws": "^8.17.1",
"portfinder": "^1.0.38",
"tslib": "^2.8.1",
"ws": "^8.19.0",
"yargs": "^17.7.2"
},
"devDependencies": {
"@types/ws": "^8.5.4",
"@types/ws": "^8.18.1",
"archiver": "^7.0.1",
"electron": "35.7.5",
"electron-builder": "^24.13.3",
"lerna": "^6.6.1",
"rimraf": "^5.0.5"
"lerna": "^9.0.7",
"rimraf": "^6.1.3"
},
"build": {
"productName": "html-renderer",
Expand Down
2 changes: 1 addition & 1 deletion apps/html-renderer/packages/generic/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@
"@sofie-package-manager/api": "1.53.0"
},
"devDependencies": {
"rimraf": "^5.0.5"
"rimraf": "^6.1.3"
}
}
4 changes: 2 additions & 2 deletions apps/http-server/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
},
"dependencies": {
"@http-server/generic": "1.53.0",
"rimraf": "^5.0.5"
"rimraf": "^6.1.3"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "1) Search runtime code for rimraf imports/usages:"
rg -nP -C2 '\b(from\s+["'\'']rimraf["'\'']|require\(\s*["'\'']rimraf["'\'']\s*\)|\brimraf\s*\()' apps/http-server || true

echo
echo "2) Inspect package manifests in http-server workspace for rimraf placement:"
fd -a package.json apps/http-server -x sh -c 'echo "### $1"; rg -n "\"rimraf\"" "$1" || true' sh {}

Repository: Sofie-Automation/sofie-package-manager

Length of output: 389


🏁 Script executed:

cat -n apps/http-server/app/package.json | head -40

Repository: Sofie-Automation/sofie-package-manager

Length of output: 1201


🏁 Script executed:

cat -n apps/http-server/packages/generic/package.json | grep -A 5 -B 5 "rimraf"

Repository: Sofie-Automation/sofie-package-manager

Length of output: 828


Move rimraf from dependencies to devDependencies.

Line 15 places rimraf in dependencies, but it is used only in the build script (line 7: "build": "yarn rimraf dist ..."), not at runtime. The sibling package (packages/generic) correctly places the same tool in devDependencies. This unnecessarily adds rimraf to the production install surface.

Adjustment
 "dependencies": {
-    "@http-server/generic": "1.53.0",
-    "rimraf": "^6.1.3"
+    "@http-server/generic": "1.53.0"
 },
@@
 "devDependencies": {
-    "lerna": "^9.0.7"
+    "lerna": "^9.0.7",
+    "rimraf": "^6.1.3"
 }

Also applies to: 30-30

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/http-server/app/package.json` at line 15, The package.json currently
lists "rimraf" in dependencies but it's only used by the build script ("build":
"yarn rimraf dist ..."); remove the "rimraf" entry from the dependencies object
and add the same version string to devDependencies instead (mirroring
packages/generic), then update the lockfile by running your package manager
install (yarn or npm) so the move is reflected; also ensure you remove the
duplicate occurrence noted elsewhere and run the build script to verify nothing
breaks.

},
"prettier": "@sofie-automation/code-standard-preset/.prettierrc.json",
"engines": {
Expand All @@ -27,6 +27,6 @@
]
},
"devDependencies": {
"lerna": "^6.6.1"
"lerna": "^9.0.7"
}
}
31 changes: 15 additions & 16 deletions apps/http-server/packages/generic/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,27 @@
"dependencies": {
"@koa/bodyparser": "^6.1.0",
"@koa/cors": "^5.0.0",
"@koa/router": "^15.4.0",
"@sofie-package-manager/api": "1.53.0",
"koa": "^2.16.1",
"koa": "^3.1.2",
"koa-range": "^0.3.0",
"koa-router": "^8.0.8",
"mime-types": "^2.1.28",
"mime-types": "^3.0.2",
"pechkin": "^2.2.0",
"pretty-bytes": "^5.5.0",
"tslib": "^2.1.0",
"underscore": "^1.12.0",
"pretty-bytes": "^7.1.0",
"tslib": "^2.8.1",
"underscore": "^1.13.8",
"yargs": "^17.7.2"
},
"devDependencies": {
"@types/busboy": "^1.5.0",
"@types/koa": "^2.13.5",
"@types/koa-range": "^0.3.2",
"@types/koa-router": "^7.4.0",
"@types/koa__cors": "^4.0.0",
"@types/mime-types": "^2.1.0",
"@types/node": "^24",
"@types/underscore": "^1.10.24",
"@types/yargs": "^17.0.24",
"rimraf": "^5.0.5"
"@types/busboy": "^1.5.4",
"@types/koa": "^3.0.1",
"@types/koa-range": "^0.3.6",
"@types/koa__cors": "^5.0.1",
"@types/mime-types": "^3.0.1",
"@types/node": "^24.12.0",
"@types/underscore": "^1.13.0",
"@types/yargs": "^17.0.35",
"rimraf": "^6.1.3"
},
"prettier": "@sofie-automation/code-standard-preset/.prettierrc.json",
"engines": {
Expand Down
7 changes: 3 additions & 4 deletions apps/http-server/packages/generic/src/lib.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import Koa from 'koa'
import Router from 'koa-router'
import type { RouterContext } from '@koa/router'
import { Readable, Writable } from 'stream'

export type CTX = Koa.ParameterizedContext<any, Router.IRouterParamContext<any, any>>
export type CTXPost = Koa.ParameterizedContext<any, Router.IRouterParamContext<any, any>>
export type CTX = RouterContext<any, any>
export type CTXPost = RouterContext<any, any>
Comment on lines +1 to +5
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

For @koa/router15.x with koa 3.x, what is the recommended RouterContext generic typing for route handlers (state/context/params) to avoidany?

💡 Result:

In @koa/router 15.x (koajs/router) the exported RouterContext only has generics for:

RouterContext<StateT = DefaultState, ContextT = DefaultContext, BodyT = unknown>

and route params are not generic—they’re typed as Record<string, string> via RouterParameterContext/RouterContext (params and request.params). [1]

Recommended typing (avoid any): put your app-level types on the Router, then (optionally) annotate handlers with the matching RouterContext<StateT, ContextT, BodyT>.

import Router, { type RouterContext } from '@koa/router';

type AppState = { user?: { id: string } };
type AppContext = { requestId: string }; // whatever you add via declaration merging, etc.

const router = new Router<AppState, AppContext>();

router.get('/users/:id', async (ctx: RouterContext<AppState, AppContext>) => {
  // ctx.state is AppState
  // ctx is AppContext & router additions
  // ctx.params.id is string (Record<string, string>)
  const id = ctx.params.id;
});

If you need strongly-typed param keys (e.g. { id: string } instead of Record<string,string>), you must refine it yourself (e.g. an intersection/cast), because @koa/router 15.x doesn’t provide a params generic. [1]

Sources:
[1] @koa/router RouterContext / RouterParameterContext type definitions (koajs/router src/types.ts) (raw.githubusercontent.com)

Citations:


🏁 Script executed:

# First, check the package.json for version info
find . -name "package.json" -path "*/http-server/*" | head -5

Repository: Sofie-Automation/sofie-package-manager

Length of output: 166


🏁 Script executed:

# Search for usage of CTX and CTXPost in the codebase
rg "CTX|CTXPost" --type ts --type tsx -B 2 -A 2

Repository: Sofie-Automation/sofie-package-manager

Length of output: 109


🏁 Script executed:

# Look for any custom context or state type definitions
rg "type.*Context|type.*State" --type ts --type tsx | head -20

Repository: Sofie-Automation/sofie-package-manager

Length of output: 109


🏁 Script executed:

# Check package.json for koa and `@koa/router` versions
cat apps/http-server/packages/generic/package.json | grep -A 2 -B 2 "koa\|router"

Repository: Sofie-Automation/sofie-package-manager

Length of output: 529


🏁 Script executed:

# Search for CTX and CTXPost usage without file type
rg "CTX|CTXPost" -B 2 -A 2

Repository: Sofie-Automation/sofie-package-manager

Length of output: 4014


🏁 Script executed:

# Check the lib.ts file itself
cat -n apps/http-server/packages/generic/src/lib.ts

Repository: Sofie-Automation/sofie-package-manager

Length of output: 838


🏁 Script executed:

# Verify that DefaultState and DefaultContext are available from 'koa' types
cat apps/http-server/packages/generic/package.json | grep -A 5 "@types/koa"

Repository: Sofie-Automation/sofie-package-manager

Length of output: 318


🏁 Script executed:

# Quick check of `@types/koa` to confirm DefaultState/DefaultContext exports
find . -name "*.json" -path "*@types/koa*" 2>/dev/null | head -3

Repository: Sofie-Automation/sofie-package-manager

Length of output: 64


🏁 Script executed:

# Check what's imported from 'koa' or '@koa/router' in the broader codebase to see patterns
rg "from ['\"](koa|@koa)" --type ts | head -15

Repository: Sofie-Automation/sofie-package-manager

Length of output: 983


🏁 Script executed:

# Check if there are any custom context/state type definitions in the http-server packages
rg "interface|type.*Context|type.*State" apps/http-server/packages/generic/src --type ts -A 1 | head -25

Repository: Sofie-Automation/sofie-package-manager

Length of output: 822


Avoid exporting CTX/CTXPost as RouterContext<any, any>.

Lines 4–5 currently erase handler context typing across the package. Use Koa's standard DefaultState and DefaultContext to maintain compile-time type safety.

♻️ Proposed typing fix
 import type { RouterContext } from '@koa/router'
+import type { DefaultContext, DefaultState } from 'koa'
 import { Readable, Writable } from 'stream'
 
-export type CTX = RouterContext<any, any>
-export type CTXPost = RouterContext<any, any>
+export type CTX = RouterContext<DefaultState, DefaultContext>
+export type CTXPost = RouterContext<DefaultState, DefaultContext>
📝 Committable suggestion

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

Suggested change
import type { RouterContext } from '@koa/router'
import { Readable, Writable } from 'stream'
export type CTX = Koa.ParameterizedContext<any, Router.IRouterParamContext<any, any>>
export type CTXPost = Koa.ParameterizedContext<any, Router.IRouterParamContext<any, any>>
export type CTX = RouterContext<any, any>
export type CTXPost = RouterContext<any, any>
import type { RouterContext } from '@koa/router'
import type { DefaultContext, DefaultState } from 'koa'
import { Readable, Writable } from 'stream'
export type CTX = RouterContext<DefaultState, DefaultContext>
export type CTXPost = RouterContext<DefaultState, DefaultContext>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/http-server/packages/generic/src/lib.ts` around lines 1 - 5, The
exported CTX and CTXPost types currently alias RouterContext<any, any>, which
erases context/state typing; update their definitions to use Koa's DefaultState
and DefaultContext so compile-time types are preserved: replace occurrences of
RouterContext<any, any> for the CTX and CTXPost exports with
RouterContext<DefaultState, DefaultContext> (import DefaultState and
DefaultContext from 'koa') and keep the same export names (CTX, CTXPost).


export async function asyncPipe(readable: Readable, writable: Writable): Promise<void> {
return new Promise((resolve) => {
Expand Down
14 changes: 7 additions & 7 deletions apps/http-server/packages/generic/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { promisify } from 'util'
import fs from 'fs'
import Koa from 'koa'
import path from 'path'
import Router from 'koa-router'
import Router from '@koa/router'
import cors from '@koa/cors'
import { bodyParser } from '@koa/bodyparser'

Expand Down Expand Up @@ -61,7 +61,7 @@ export class PackageProxyServer {
await this._setUpRoutes()
}
private async _setUpRoutes(): Promise<void> {
this.router.all('(.*)', async (ctx, next) => {
this.router.all('{/*path}', async (ctx, next) => {
// Intercept and authenticate:

const apiKey: string | undefined =
Expand Down Expand Up @@ -95,13 +95,13 @@ export class PackageProxyServer {
this.router.get('/list', async (ctx) => {
await this.handleStorageHTMLList(ctx, async () => this.storage.listPackages())
})
this.router.get('/package/:path+', async (ctx) => {
this.router.get('/package/*path', async (ctx) => {
await this.handleStorage(ctx, async () => this.storage.getPackage(ctx.params.path))
})
this.router.head('/package/:path+', async (ctx) => {
this.router.head('/package/*path', async (ctx) => {
await this.handleStorage(ctx, async () => this.storage.headPackage(ctx.params.path))
})
this.router.post('/package/:path+', async (ctx) => {
this.router.post('/package/*path', async (ctx) => {
this.logger.debug(`POST ${ctx.request.URL}`)
Comment on lines +98 to 105
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In @koa/router v15+, for a named wildcard route parameter, is '/package/*path' valid, or should it be '/package/{/*path}'?

💡 Result:

In @koa/router v15+, a named wildcard (“splat”) parameter must be wrapped in braces:

  • Use: /package/{/*path}
  • Not: /package/*path (that syntax isn’t the documented v15+ form for a named wildcard)

The README’s example is router.get('/files/{/*path}', ...) with ctx.params.path containing the rest of the path. [1]


🏁 Script executed:

# Check `@koa/router` version and related dependencies
find . -name "package.json" -type f | head -5 | xargs grep -l "@koa/router\|koa.*router" 2>/dev/null

Repository: Sofie-Automation/sofie-package-manager

Length of output: 66


🏁 Script executed:

# Locate the server.ts file
find . -path "*/apps/http-server/packages/generic/src/server.ts" -type f

Repository: Sofie-Automation/sofie-package-manager

Length of output: 131


🏁 Script executed:

# Find package.json in the http-server package directory
find ./apps/http-server -name "package.json" -type f

Repository: Sofie-Automation/sofie-package-manager

Length of output: 166


🏁 Script executed:

# Read the server.ts file at the relevant lines
sed -n '95,110p; 123,128p; 137,142p' ./apps/http-server/packages/generic/src/server.ts

Repository: Sofie-Automation/sofie-package-manager

Length of output: 1159


🏁 Script executed:

# Check `@koa/router` version in the package.json
grep -A2 -B2 "@koa/router" ./apps/http-server/packages/generic/package.json

Repository: Sofie-Automation/sofie-package-manager

Length of output: 226


Update wildcard route patterns to @koa/router v15+ syntax.

Routes at lines 98, 101, 104, 126, and 140 use /package/*path and /uploadForm/*path. With @koa/router v15.4.0, the correct syntax for named wildcard parameters is /{/*path}. The current patterns will not match routes correctly.

🔧 Proposed route-pattern fix
-		this.router.get('/package/*path', async (ctx) => {
+		this.router.get('/package/{/*path}', async (ctx) => {
 			await this.handleStorage(ctx, async () => this.storage.getPackage(ctx.params.path))
 		})
-		this.router.head('/package/*path', async (ctx) => {
+		this.router.head('/package/{/*path}', async (ctx) => {
 			await this.handleStorage(ctx, async () => this.storage.headPackage(ctx.params.path))
 		})
-		this.router.post('/package/*path', async (ctx) => {
+		this.router.post('/package/{/*path}', async (ctx) => {
 			this.logger.debug(`POST ${ctx.request.URL}`)
 			const { files, fields } = await parseFormData(ctx.req, {
 				maxFileByteLength: MAX_UPLOAD_FILE_SIZE,
@@
-		this.router.delete('/package/*path', async (ctx) => {
+		this.router.delete('/package/{/*path}', async (ctx) => {
 			this.logger.debug(`DELETE ${ctx.request.URL}`)
 			await this.handleStorage(ctx, async () => this.storage.deletePackage(ctx.params.path))
 		})
@@
-		this.router.get('/uploadForm/*path', async (ctx) => {
+		this.router.get('/uploadForm/{/*path}', async (ctx) => {
 			// ctx.response.status = result.code
 			ctx.type = 'text/html'
 			ctx.body = (await fsReadFile(path.resolve('../static/uploadForm.html'), 'utf-8'))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/http-server/packages/generic/src/server.ts` around lines 98 - 105, The
route patterns using the older wildcard syntax (e.g. '/package/*path' and
'/uploadForm/*path') won't match under `@koa/router` v15+; update the router calls
in server.ts (the router.get/ head/ post handlers that call handleStorage and
storage.getPackage/headPackage, and the routes around the uploadForm handlers)
to use the new named wildcard syntax '/package/{/*path}' and
'/uploadForm/{/*path}' so Koa will correctly bind ctx.params.path for the
existing handleStorage, storage.getPackage, storage.headPackage and the upload
form handlers.

const { files, fields } = await parseFormData(ctx.req, {
maxFileByteLength: MAX_UPLOAD_FILE_SIZE,
Expand All @@ -123,7 +123,7 @@ export class PackageProxyServer {
}
}
})
this.router.delete('/package/:path+', async (ctx) => {
this.router.delete('/package/*path', async (ctx) => {
this.logger.debug(`DELETE ${ctx.request.URL}`)
await this.handleStorage(ctx, async () => this.storage.deletePackage(ctx.params.path))
})
Expand All @@ -137,7 +137,7 @@ export class PackageProxyServer {
info: this.storage.getInfo(),
}
})
this.router.get('/uploadForm/:path+', async (ctx) => {
this.router.get('/uploadForm/*path', async (ctx) => {
// ctx.response.status = result.code
ctx.type = 'text/html'
ctx.body = (await fsReadFile(path.resolve('../static/uploadForm.html'), 'utf-8'))
Expand Down
4 changes: 2 additions & 2 deletions apps/package-manager/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
]
},
"devDependencies": {
"lerna": "^6.6.1",
"rimraf": "^5.0.5"
"lerna": "^9.0.7",
"rimraf": "^6.1.3"
}
}
10 changes: 5 additions & 5 deletions apps/package-manager/packages/generic/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,20 @@
"typescript": "*"
},
"dependencies": {
"@parcel/watcher": "^2.3.0",
"@parcel/watcher": "^2.5.6",
"@sofie-package-manager/api": "1.53.0",
"@sofie-package-manager/expectation-manager": "1.53.0",
"@sofie-package-manager/worker": "1.53.0",
"data-store": "^4.0.3",
"deep-extend": "^0.6.0",
"fast-clone": "^1.5.13",
"underscore": "^1.12.0"
"underscore": "^1.13.8"
},
"devDependencies": {
"@types/deep-extend": "0.6.2",
"@types/underscore": "^1.10.24",
"jest": "*",
"rimraf": "^5.0.5"
"@types/underscore": "^1.13.0",
"jest": "^30.3.0",
"rimraf": "^6.1.3"
},
"prettier": "@sofie-automation/code-standard-preset/.prettierrc.json",
"engines": {
Expand Down
4 changes: 2 additions & 2 deletions apps/quantel-http-transformer-proxy/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
]
},
"devDependencies": {
"lerna": "^6.6.1",
"rimraf": "^5.0.5"
"lerna": "^9.0.7",
"rimraf": "^6.1.3"
}
}
35 changes: 17 additions & 18 deletions apps/quantel-http-transformer-proxy/packages/generic/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,31 @@
"dependencies": {
"@koa/bodyparser": "^6.1.0",
"@koa/cors": "^5.0.0",
"@koa/router": "^15.4.0",
"@sofie-package-manager/api": "1.53.0",
"got": "^11.8.6",
"koa": "^2.16.1",
"koa": "^3.1.2",
"koa-range": "^0.3.0",
"koa-ratelimit": "^5.0.1",
"koa-router": "^12.0.0",
"mime-types": "^2.1.28",
"pretty-bytes": "^5.5.0",
"tslib": "^2.1.0",
"underscore": "^1.12.0",
"koa-ratelimit": "^6.0.0",
"mime-types": "^3.0.2",
"pretty-bytes": "^7.1.0",
"tslib": "^2.8.1",
"underscore": "^1.13.8",
"xml2js": "^0.6.2",
"yargs": "^17.7.2"
},
"devDependencies": {
"@koa/cors": "^5.0.0",
"@types/koa": "^2.13.5",
"@types/koa-range": "^0.3.2",
"@types/koa-ratelimit": "^5.0.0",
"@types/koa-router": "^7.4.4",
"@types/koa__cors": "^4.0.0",
"@types/mime-types": "^2.1.0",
"@types/node": "^24",
"@types/underscore": "^1.10.24",
"@types/xml2js": "^0.4.7",
"@types/yargs": "^17.0.24",
"rimraf": "^5.0.5"
"@types/koa": "^3.0.1",
"@types/koa-range": "^0.3.6",
"@types/koa-ratelimit": "^5.0.5",
"@types/koa__cors": "^5.0.1",
"@types/mime-types": "^3.0.1",
"@types/node": "^24.12.0",
"@types/underscore": "^1.13.0",
"@types/xml2js": "^0.4.14",
"@types/yargs": "^17.0.35",
"rimraf": "^6.1.3"
},
"prettier": "@sofie-automation/code-standard-preset/.prettierrc.json",
"engines": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Koa from 'koa'
import Router from 'koa-router'
import Router from '@koa/router'
import cors from '@koa/cors'
import range from 'koa-range'
import ratelimit from 'koa-ratelimit'
Expand Down Expand Up @@ -69,7 +69,7 @@ export class QuantelHTTPTransformerProxy {
})

// Proxy
this.router.get('/(quantel|gv)/(.*)', async (ctx) => {
this.router.get(['/quantel{/*rest}', '/gv{/*rest}'], async (ctx) => {
try {
// this.logger.debug(`Pass-through requests to transformer: ${ctx.path}`)
if (!this.transformerURL) {
Expand Down Expand Up @@ -120,7 +120,7 @@ export class QuantelHTTPTransformerProxy {
}
}
})
this.router.get('/(.*)', async (ctx, next) => {
this.router.get('{/*path}', async (ctx, next) => {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check for similar route patterns in other files to ensure consistency
echo "=== Checking route patterns in http-server and similar apps ==="
rg -n --type ts '@koa/router|{/\*' apps/

Repository: Sofie-Automation/sofie-package-manager

Length of output: 266


🏁 Script executed:

#!/bin/bash
# First, find the server.ts file and examine the routes around line 123
echo "=== Locating server.ts ==="
fd -n "server.ts" apps/quantel-http-transformer-proxy/

echo "=== Examining routes in server.ts ==="
cat -n apps/quantel-http-transformer-proxy/packages/generic/src/server.ts | sed -n '110,135p'

echo "=== Checking package.json for dependencies ==="
cat apps/quantel-http-transformer-proxy/package.json | grep -A5 -B5 "path-to-regexp\|@koa"

Repository: Sofie-Automation/sofie-package-manager

Length of output: 1527


🏁 Script executed:

#!/bin/bash
# Search for similar route patterns more carefully
echo "=== Checking for router.get patterns with catch-all routes ==="
rg -n "router\.(get|post|put|delete)" apps/quantel-http-transformer-proxy/ -A1 -t ts | head -50

echo "=== Checking for Koa router usage patterns ==="
rg -n "@koa/router|new Router" apps/ -t ts | head -20

Repository: Sofie-Automation/sofie-package-manager

Length of output: 1425


🏁 Script executed:

#!/bin/bash
# Check for package.json files in the quantel-http-transformer-proxy
echo "=== Finding package.json files ==="
find apps/quantel-http-transformer-proxy -name "package.json" -type f

# Check the root package.json for dependencies
echo "=== Root package.json dependencies ==="
rg -A2 -B2 "@koa/router|path-to-regexp" package.json

# Check if there are any test files that demonstrate route patterns
echo "=== Looking for test files with router patterns ==="
find apps/quantel-http-transformer-proxy -name "*.test.ts" -o -name "*.spec.ts" | head -10

Repository: Sofie-Automation/sofie-package-manager

Length of output: 393


🏁 Script executed:

#!/bin/bash
# Look at the full context of the server.ts file to understand the router setup
echo "=== Full route definitions in server.ts ==="
rg -n "router\.(get|post|put|delete)" apps/quantel-http-transformer-proxy/packages/generic/src/server.ts -B1 -A3

# Check if there's documentation or comments about the route pattern
echo "=== Search for any comments about route patterns ==="
rg -n "catch.all|{/\*|path\}" apps/quantel-http-transformer-proxy/ -t ts -B2 -A2

Repository: Sofie-Automation/sofie-package-manager

Length of output: 950


🏁 Script executed:

#!/bin/bash
# Check package versions
echo "=== Checking `@koa/router` and dependencies in packages/generic/package.json ==="
cat apps/quantel-http-transformer-proxy/packages/generic/package.json | grep -A50 "dependencies"

echo "=== Checking `@koa/router` and dependencies in app/package.json ==="
cat apps/quantel-http-transformer-proxy/app/package.json | grep -A50 "dependencies"

Repository: Sofie-Automation/sofie-package-manager

Length of output: 1633


🏁 Script executed:

#!/bin/bash
# Check the test file to see how routes are tested
echo "=== Examining test file ==="
cat -n apps/quantel-http-transformer-proxy/app/src/__tests__/test.spec.ts | head -100

Repository: Sofie-Automation/sofie-package-manager

Length of output: 344


🌐 Web query:

@koa/router v15 path-to-regexp v8 catch-all route pattern {/*path}

💡 Result:

In @koa/router v15 (uses path-to-regexp v8), the catch-all is a named wildcard (you can’t use a bare *), and the equivalent of a “catch-all param” is:

  • Catch-all after a prefix (0 or more segments):

    router.all('/files/{/*path}', (ctx) => {
      // matches /files and /files/a/b/c
      ctx.body = ctx.params.path; // e.g. "a/b/c"
    });

    This is the documented wildcard form for v15. [1]

  • Catch-all for the whole app (0 or more segments, including /):

    router.all('/{/*path}', (ctx) => {
      // matches / and /anything/here
      ctx.body = ctx.params.path; // undefined for "/", or "anything/here"
    });
  • If you want only non-empty paths (i.e., match /a/b but not /), use the non-optional wildcard form:

    router.all('/*path', (ctx) => { /* ... */ });

    (Wildcard params are *name in path-to-regexp v8. [2])

Why {/*path} instead of {*path}? In path-to-regexp v8, the * wildcard still needs a name, and braces { ... } make that part optional; @koa/router’s README shows the wildcard as /{/*path}-style under a prefix. [1][2]

Sources

[1] @koa/router README (Wildcard parameters example) (raw.githubusercontent.com)
[2] pillarjs/path-to-regexp README (Wildcard *name, and optional groups with {}) (github.com)

Citations:


🌐 Web query:

path-to-regexp zero or more segments braces syntax

💡 Result:

In current path-to-regexp (v6+), the old + / * repeat modifiers aren’t used on params anymore. Instead: braces {...} create an optional group, and wildcards *name capture across multiple / segments. (github.com)

Zero or more path segments (the “*” behavior) is done by combining both:

/files{/*path}

This matches:

  • /files (zero segments)
  • /files/a
  • /files/a/b/c (many segments)

and path is captured as an array of segments. (github.com)

For comparison, one or more segments is just a wildcard:

/*path

(which does not match / by itself). (github.com)

Citations:


🌐 Web query:

@koa/router v15 root catch-all route pattern /{/*path} vs {/*path}

💡 Result:

In @koa/router v15 (uses path-to-regexp v8), the * wildcard must be named (e.g. *path) and braces {...} create an optional group. (github.com)

So:

  • /{/*path} = “match / and anything below it”

    • /*path is inside an optional group, so it can be absent (root /) or present (/a, /a/b, …).
    • This is the right pattern for a root catch-all.
      (github.com)
  • {/*path} (no leading / outside the group) = the whole route pattern starts with an optional /*path, meaning it can match the empty string as well as /....

    • Since Koa request paths always start with /, this is generally not what you want for a normal router route; use /{/*path} instead.
      (github.com)

Citations:


🏁 Script executed:

#!/bin/bash
# Check if there are similar catch-all patterns in the codebase
echo "=== Searching for catch-all route patterns ==="
rg -n "router\.(get|post|all)" apps/ -t ts | rg "{/\*|/\*" | head -20

# Check http-server app for comparison
echo "=== Checking http-server for route patterns ==="
rg -n "router\.(get|post|all)" apps/http-server/ -t ts -A1 | head -40

Repository: Sofie-Automation/sofie-package-manager

Length of output: 1923


Change catch-all route pattern from {/*path} to /{/*path}.

The pattern {/*path} is incorrect for a root catch-all. In path-to-regexp v8 (used by @koa/router v15.4.0), {/*path} without a leading / represents an optional group that can match an empty string, which does not work correctly with Koa routes. The correct pattern for matching all paths including the root / is /{/*path}.

Note: The http-server app also uses this same incorrect pattern on line 64 and should be corrected as well.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/quantel-http-transformer-proxy/packages/generic/src/server.ts` at line
123, Update the Koa route pattern: replace the incorrect catch-all string
"{/*path}" with the correct "/{/*path}" wherever it's used (e.g., the
this.router.get('{/*path}', async (ctx, next) => { ... }) route in server.ts);
also make the same replacement for the other occurrence in the http-server app
so the root "/" is properly matched.

const url = `${this.transformerURL}${ctx.path}` + (ctx.querystring ? `?${ctx.querystring}` : '')
try {
const initReq = await got(url, { responseType: 'buffer' })
Expand Down
6 changes: 3 additions & 3 deletions apps/single-app/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"@sofie-package-manager/api": "1.53.0",
"@sofie-package-manager/worker": "1.53.0",
"@sofie-package-manager/workforce": "1.53.0",
"underscore": "^1.12.0"
"underscore": "^1.13.8"
},
"prettier": "@sofie-automation/code-standard-preset/.prettierrc.json",
"engines": {
Expand All @@ -38,7 +38,7 @@
]
},
"devDependencies": {
"lerna": "^6.6.1",
"rimraf": "^5.0.5"
"lerna": "^9.0.7",
"rimraf": "^6.1.3"
}
}
4 changes: 2 additions & 2 deletions apps/worker/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
]
},
"devDependencies": {
"lerna": "^6.6.1",
"rimraf": "^5.0.5"
"lerna": "^9.0.7",
"rimraf": "^6.1.3"
}
}
Loading
Loading