Skip to content

Commit 47c4b91

Browse files
committed
refactor: Use JS regular expression syntax, not path-to-regexp, in RegexRouter.
1 parent 7e37f6f commit 47c4b91

File tree

7 files changed

+153
-66
lines changed

7 files changed

+153
-66
lines changed

companion/lib/Service/OscApi.ts

+17-16
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { CoreBase } from '../Core/Base.js'
22
import { parseColorToNumber, rgb } from '../Resources/Util.js'
33
import { formatLocation } from '@companion-app/shared/ControlId.js'
44
import { RegexRouter } from './RegexRouter.js'
5+
import { Bank, Location, Page, VariableName } from './RoutePatterns.js'
56
import type { Registry } from '../Registry.js'
67
import type { OscReceivedMessage } from 'osc'
78
import type { ControlLocation } from '@companion-app/shared/Model/Common.js'
@@ -50,7 +51,7 @@ export class ServiceOscApi extends CoreBase {
5051
}
5152

5253
#setupLegacyOscRoutes(): void {
53-
this.#router.addPath('/press/bank/:page/:bank', (match: Record<string, string>, message: OscReceivedMessage) => {
54+
this.#router.addRoute(`/press/bank/${Page}/${Bank}`, (match: Record<string, string>, message: OscReceivedMessage) => {
5455
if (!this.#isLegacyRouteAllowed()) return
5556

5657
const controlId = this.page.getControlIdAtOldBankIndex(Number(match.page), Number(match.bank))
@@ -73,7 +74,7 @@ export class ServiceOscApi extends CoreBase {
7374
}
7475
})
7576

76-
this.#router.addPath('/style/bgcolor/:page/:bank', (match: Record<string, string>, message: OscReceivedMessage) => {
77+
this.#router.addRoute(`/style/bgcolor/${Page}/${Bank}`, (match: Record<string, string>, message: OscReceivedMessage) => {
7778
if (!this.#isLegacyRouteAllowed()) return
7879

7980
if (message.args.length > 2) {
@@ -95,7 +96,7 @@ export class ServiceOscApi extends CoreBase {
9596
}
9697
})
9798

98-
this.#router.addPath('/style/color/:page/:bank', (match: Record<string, string>, message: OscReceivedMessage) => {
99+
this.#router.addRoute(`/style/color/${Page}/${Bank}`, (match: Record<string, string>, message: OscReceivedMessage) => {
99100
if (!this.#isLegacyRouteAllowed()) return
100101

101102
if (message.args.length > 2) {
@@ -117,7 +118,7 @@ export class ServiceOscApi extends CoreBase {
117118
}
118119
})
119120

120-
this.#router.addPath('/style/text/:page/:bank', (match: Record<string, string>, message: OscReceivedMessage) => {
121+
this.#router.addRoute(`/style/text/${Page}/${Bank}`, (match: Record<string, string>, message: OscReceivedMessage) => {
121122
if (!this.#isLegacyRouteAllowed()) return
122123

123124
if (message.args.length > 0) {
@@ -137,7 +138,7 @@ export class ServiceOscApi extends CoreBase {
137138
}
138139
})
139140

140-
this.#router.addPath('/rescan', (_match: Record<string, string>, _message: OscReceivedMessage) => {
141+
this.#router.addRoute('/rescan', (_match: Record<string, string>, _message: OscReceivedMessage) => {
141142
if (!this.#isLegacyRouteAllowed()) return
142143

143144
this.logger.info('Got /rescan 1')
@@ -149,22 +150,22 @@ export class ServiceOscApi extends CoreBase {
149150

150151
#setupNewOscRoutes() {
151152
// controls by location
152-
this.#router.addPath('/location/:page/:row/:column/press', this.#locationPress)
153-
this.#router.addPath('/location/:page/:row/:column/down', this.#locationDown)
154-
this.#router.addPath('/location/:page/:row/:column/up', this.#locationUp)
155-
this.#router.addPath('/location/:page/:row/:column/rotate-left', this.#locationRotateLeft)
156-
this.#router.addPath('/location/:page/:row/:column/rotate-right', this.#locationRotateRight)
157-
this.#router.addPath('/location/:page/:row/:column/step', this.#locationStep)
153+
this.#router.addRoute(`/location/${Location}/press`, this.#locationPress)
154+
this.#router.addRoute(`/location/${Location}/down`, this.#locationDown)
155+
this.#router.addRoute(`/location/${Location}/up`, this.#locationUp)
156+
this.#router.addRoute(`/location/${Location}/rotate-left`, this.#locationRotateLeft)
157+
this.#router.addRoute(`/location/${Location}/rotate-right`, this.#locationRotateRight)
158+
this.#router.addRoute(`/location/${Location}/step`, this.#locationStep)
158159

159-
this.#router.addPath('/location/:page/:row/:column/style/text', this.#locationSetStyleText)
160-
this.#router.addPath('/location/:page/:row/:column/style/color', this.#locationSetStyleColor)
161-
this.#router.addPath('/location/:page/:row/:column/style/bgcolor', this.#locationSetStyleBgcolor)
160+
this.#router.addRoute(`/location/${Location}/style/text`, this.#locationSetStyleText)
161+
this.#router.addRoute(`/location/${Location}/style/color`, this.#locationSetStyleColor)
162+
this.#router.addRoute(`/location/${Location}/style/bgcolor`, this.#locationSetStyleBgcolor)
162163

163164
// custom variables
164-
this.#router.addPath('/custom-variable/:name/value', this.#customVariableSetValue)
165+
this.#router.addRoute(`/custom-variable/${VariableName}/value`, this.#customVariableSetValue)
165166

166167
// surfaces
167-
this.#router.addPath('/surfaces/rescan', this.#surfacesRescan)
168+
this.#router.addRoute('/surfaces/rescan', this.#surfacesRescan)
168169
}
169170

170171
/**

companion/lib/Service/RegexRouter.ts

+4-21
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { pathToRegexp } from 'path-to-regexp'
2-
31
/**
42
* A regex based route
53
*/
@@ -51,25 +49,10 @@ export class RegexRouter {
5149
/**
5250
* Add a route to the router
5351
*/
54-
addRegex(regexp: RegExp, handler: RouteHandler): void {
55-
if (!regexp || !handler) throw new Error('Invalid route parameters')
56-
this.#routes.push({ regexp, handler })
57-
}
58-
59-
/**
60-
* Add a route to the router, using the express style path syntax
61-
*/
62-
addPath(path: string, handler: PathRouteHandler): void {
63-
const { regexp, keys } = pathToRegexp(path)
64-
65-
this.addRegex(regexp, (match, ...args) => {
66-
const values: Record<string, string> = {}
67-
for (let i = 0; i < keys.length; i++) {
68-
const key = keys[i]
69-
values[key.name] = values[key.name] ?? match[i + 1]
70-
}
71-
72-
return handler(values, ...args)
52+
addRoute(route: string, handler: PathRouteHandler): void {
53+
this.#routes.push({
54+
regexp: new RegExp(`^${route}$`, 'i'),
55+
handler: (match, ...args) => handler(match.groups ?? {}, ...args),
7356
})
7457
}
7558
}
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Historic parsing behavior mapped variables to non-'/'-delimiter characters.
2+
// Continue to do so even if matching something more precise would be more
3+
// sensible.
4+
export const Element = '[^/]+?'
5+
6+
export const Page = `(?<page>${Element})`
7+
export const Location = `${Page}/(?<row>${Element})/(?<column>${Element})`
8+
9+
export const Bank = `(?<bank>${Element})`
10+
11+
export const VariableName = `(?<name>${Element})`

companion/lib/Service/TcpUdpApi.ts

+39-26
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,23 @@ import { CoreBase } from '../Core/Base.js'
22
import { parseColorToNumber } from '../Resources/Util.js'
33
import { formatLocation } from '@companion-app/shared/ControlId.js'
44
import { RegexRouter } from './RegexRouter.js'
5+
import { Bank, Element, Location, Page, VariableName } from './RoutePatterns.js'
56
import type { ControlLocation } from '@companion-app/shared/Model/Common.js'
67
import type { Registry } from '../Registry.js'
78
import type { UserConfigModel } from '@companion-app/shared/Model/UserConfigModel.js'
89

10+
const SurfaceId = `(?<surfaceId>${Element})`
11+
const Step = `(?<step>${Element})`
12+
13+
const MatchAnyCharactersIfSpacePrecedes = '(?<= ).*'
14+
const MatchZeroCharactersIfNoSpacePrecedes = '(?<! )'
15+
const TextRequiringPrecedingSpace =
16+
`(?<text>${MatchAnyCharactersIfSpacePrecedes}|${MatchZeroCharactersIfNoSpacePrecedes})`
17+
18+
const VariableValue = `(?<value>.*)`
19+
20+
const Color = `(?<color>${Element})`
21+
922
/**
1023
* Common API command processing for {@link ServiceTcp} and {@link ServiceUdp}.
1124
*
@@ -71,7 +84,7 @@ export class ServiceTcpUdpApi extends CoreBase {
7184
}
7285

7386
#setupLegacyRoutes() {
74-
this.#router.addPath('page-set :page :surfaceId', (match) => {
87+
this.#router.addRoute(`page-set ${Page} ${SurfaceId}`, (match) => {
7588
this.#checkLegacyRouteAllowed()
7689

7790
const page = Number(match.page)
@@ -85,7 +98,7 @@ export class ServiceTcpUdpApi extends CoreBase {
8598
return `If ${surfaceId} is connected`
8699
})
87100

88-
this.#router.addPath('page-up :surfaceId', (match) => {
101+
this.#router.addRoute(`page-up ${SurfaceId}`, (match) => {
89102
this.#checkLegacyRouteAllowed()
90103

91104
const surfaceId = match.surfaceId
@@ -95,7 +108,7 @@ export class ServiceTcpUdpApi extends CoreBase {
95108
return `If ${surfaceId} is connected`
96109
})
97110

98-
this.#router.addPath('page-down :surfaceId', (match) => {
111+
this.#router.addRoute(`page-down ${SurfaceId}`, (match) => {
99112
this.#checkLegacyRouteAllowed()
100113

101114
const surfaceId = match.surfaceId
@@ -105,7 +118,7 @@ export class ServiceTcpUdpApi extends CoreBase {
105118
return `If ${surfaceId} is connected`
106119
})
107120

108-
this.#router.addPath('bank-press :page :bank', (match) => {
121+
this.#router.addRoute(`bank-press ${Page} ${Bank}`, (match) => {
109122
this.#checkLegacyRouteAllowed()
110123

111124
const controlId = this.page.getControlIdAtOldBankIndex(Number(match.page), Number(match.bank))
@@ -123,7 +136,7 @@ export class ServiceTcpUdpApi extends CoreBase {
123136
}, 20)
124137
})
125138

126-
this.#router.addPath('bank-down :page :bank', (match) => {
139+
this.#router.addRoute(`bank-down ${Page} ${Bank}`, (match) => {
127140
this.#checkLegacyRouteAllowed()
128141

129142
const controlId = this.page.getControlIdAtOldBankIndex(Number(match.page), Number(match.bank))
@@ -136,7 +149,7 @@ export class ServiceTcpUdpApi extends CoreBase {
136149
}
137150
})
138151

139-
this.#router.addPath('bank-up :page :bank', (match) => {
152+
this.#router.addRoute(`bank-up ${Page} ${Bank}`, (match) => {
140153
this.#checkLegacyRouteAllowed()
141154

142155
const controlId = this.page.getControlIdAtOldBankIndex(Number(match.page), Number(match.bank))
@@ -149,7 +162,7 @@ export class ServiceTcpUdpApi extends CoreBase {
149162
}
150163
})
151164

152-
this.#router.addPath('bank-step :page :bank :step', (match) => {
165+
this.#router.addRoute(`bank-step ${Page} ${Bank} ${Step}`, (match) => {
153166
this.#checkLegacyRouteAllowed()
154167

155168
const controlId = this.page.getControlIdAtOldBankIndex(Number(match.page), Number(match.bank))
@@ -167,7 +180,7 @@ export class ServiceTcpUdpApi extends CoreBase {
167180
if (!control.stepMakeCurrent(step)) throw new ApiMessageError('Step out of range')
168181
})
169182

170-
this.#router.addPath('style bank :page :bank text{ *text}', (match) => {
183+
this.#router.addRoute(`style bank ${Page} ${Bank} text ?${TextRequiringPrecedingSpace}`, (match) => {
171184
this.#checkLegacyRouteAllowed()
172185

173186
const controlId = this.page.getControlIdAtOldBankIndex(Number(match.page), Number(match.bank))
@@ -184,7 +197,7 @@ export class ServiceTcpUdpApi extends CoreBase {
184197
}
185198
})
186199

187-
this.#router.addPath('style bank :page :bank bgcolor #:color', (match) => {
200+
this.#router.addRoute(`style bank ${Page} ${Bank} bgcolor #${Color}`, (match) => {
188201
this.#checkLegacyRouteAllowed()
189202

190203
const controlId = this.page.getControlIdAtOldBankIndex(Number(match.page), Number(match.bank))
@@ -202,7 +215,7 @@ export class ServiceTcpUdpApi extends CoreBase {
202215
}
203216
})
204217

205-
this.#router.addPath('style bank :page :bank color #:color', (match) => {
218+
this.#router.addRoute(`style bank ${Page} ${Bank} color #${Color}`, (match) => {
206219
this.#checkLegacyRouteAllowed()
207220

208221
const controlId = this.page.getControlIdAtOldBankIndex(Number(match.page), Number(match.bank))
@@ -220,7 +233,7 @@ export class ServiceTcpUdpApi extends CoreBase {
220233
}
221234
})
222235

223-
this.#router.addPath('rescan', async () => {
236+
this.#router.addRoute('rescan', async () => {
224237
this.#checkLegacyRouteAllowed()
225238

226239
this.logger.debug('Rescanning USB')
@@ -235,27 +248,27 @@ export class ServiceTcpUdpApi extends CoreBase {
235248

236249
#setupNewRoutes() {
237250
// surface pages
238-
this.#router.addPath('surface :surfaceId page-set :page', this.#surfaceSetPage)
239-
this.#router.addPath('surface :surfaceId page-up', this.#surfacePageUp)
240-
this.#router.addPath('surface :surfaceId page-down', this.#surfacePageDown)
251+
this.#router.addRoute(`surface ${SurfaceId} page-set ${Page}`, this.#surfaceSetPage)
252+
this.#router.addRoute(`surface ${SurfaceId} page-up`, this.#surfacePageUp)
253+
this.#router.addRoute(`surface ${SurfaceId} page-down`, this.#surfacePageDown)
241254

242255
// control by location
243-
this.#router.addPath('location :page/:row/:column press', this.#locationPress)
244-
this.#router.addPath('location :page/:row/:column down', this.#locationDown)
245-
this.#router.addPath('location :page/:row/:column up', this.#locationUp)
246-
this.#router.addPath('location :page/:row/:column rotate-left', this.#locationRotateLeft)
247-
this.#router.addPath('location :page/:row/:column rotate-right', this.#locationRotateRight)
248-
this.#router.addPath('location :page/:row/:column set-step :step', this.#locationSetStep)
256+
this.#router.addRoute(`location ${Location} press`, this.#locationPress)
257+
this.#router.addRoute(`location ${Location} down`, this.#locationDown)
258+
this.#router.addRoute(`location ${Location} up`, this.#locationUp)
259+
this.#router.addRoute(`location ${Location} rotate-left`, this.#locationRotateLeft)
260+
this.#router.addRoute(`location ${Location} rotate-right`, this.#locationRotateRight)
261+
this.#router.addRoute(`location ${Location} set-step ${Step}`, this.#locationSetStep)
249262

250-
this.#router.addPath('location :page/:row/:column style text{ *text}', this.#locationStyleText)
251-
this.#router.addPath('location :page/:row/:column style color :color', this.#locationStyleColor)
252-
this.#router.addPath('location :page/:row/:column style bgcolor :bgcolor', this.#locationStyleBgcolor)
263+
this.#router.addRoute(`location ${Location} style text ?${TextRequiringPrecedingSpace}`, this.#locationStyleText)
264+
this.#router.addRoute(`location ${Location} style color ${Color}`, this.#locationStyleColor)
265+
this.#router.addRoute(`location ${Location} style bgcolor ${Color}`, this.#locationStyleBgcolor)
253266

254267
// surfaces
255-
this.#router.addPath('surfaces rescan', this.#surfacesRescan)
268+
this.#router.addRoute('surfaces rescan', this.#surfacesRescan)
256269

257270
// custom variables
258-
this.#router.addPath('custom-variable :name set-value {*value}', this.#customVariableSetValue)
271+
this.#router.addRoute(`custom-variable ${VariableName} set-value ${VariableValue}`, this.#customVariableSetValue)
259272
}
260273

261274
/**
@@ -440,7 +453,7 @@ export class ServiceTcpUdpApi extends CoreBase {
440453

441454
const control = this.controls.getControl(controlId)
442455
if (control && control.supportsStyle) {
443-
const color = parseColorToNumber(match.bgcolor)
456+
const color = parseColorToNumber(match.color)
444457

445458
control.styleSetFields({ bgcolor: color })
446459
} else {

companion/package.json

-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@
8383
"osc": "2.4.5",
8484
"p-debounce": "^4.0.0",
8585
"p-queue": "^8.0.1",
86-
"path-to-regexp": "^8.2.0",
8786
"selfsigned": "^2.4.1",
8887
"semver": "^7.6.3",
8988
"shuttle-control-usb": "^1.5.0",

0 commit comments

Comments
 (0)