Skip to content

Commit d15594b

Browse files
improve: replace myzod with fast-validator
1 parent 519ef87 commit d15594b

19 files changed

Lines changed: 373 additions & 295 deletions

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
"@performanc/voice": "github:PerformanC/voice",
1818
"@toddynnn/symphonia-decoder": "1.0.6",
1919
"@toddynnn/voice-opus": "^1.0.1",
20+
"fastest-validator": "^1.19.1",
2021
"jsdom": "^27.4.0",
21-
"mp4box": "^2.3.0",
22-
"myzod": "^1.12.1"
22+
"mp4box": "^2.3.0"
2323
},
2424
"devDependencies": {
2525
"@biomejs/biome": "^2.3.10",

src/api/decodeTrack.js

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,29 @@
1-
import myzod from 'myzod'
1+
import Validator from 'fastest-validator'
22
import { decodeTrack, logger, sendErrorResponse } from '../utils.js'
33

4-
const decodeTrackSchema = myzod.object({
5-
encodedTrack: myzod.string()
4+
const v = new Validator({ haltOnFirstError: true })
5+
6+
const checkDecodeTrack = v.compile({
7+
encodedTrack: {
8+
type: 'string',
9+
empty: false,
10+
messages: {
11+
required: 'Missing encodedTrack parameter.',
12+
string: 'Missing encodedTrack parameter.',
13+
stringEmpty: 'Missing encodedTrack parameter.'
14+
}
15+
}
616
})
717

818
function handler(_nodelink, req, res, sendResponse, parsedUrl) {
9-
const result = decodeTrackSchema.try({
10-
encodedTrack: parsedUrl.searchParams.get('encodedTrack')
11-
})
19+
const data = {
20+
encodedTrack: parsedUrl.searchParams.get('encodedTrack') ?? undefined
21+
}
22+
23+
const validation = checkDecodeTrack(data)
1224

13-
if (result instanceof myzod.ValidationError) {
14-
const errorMessage = result.message || 'Missing encodedTrack parameter.'
25+
if (validation !== true) {
26+
const errorMessage = validation?.[0]?.message || 'Missing encodedTrack parameter.'
1527
sendErrorResponse(
1628
req,
1729
res,
@@ -24,19 +36,20 @@ function handler(_nodelink, req, res, sendResponse, parsedUrl) {
2436
return
2537
}
2638

27-
const encodedTrack = result.encodedTrack.replace(/ /g, '+')
39+
const encodedTrack = data.encodedTrack.replace(/ /g, '+')
2840

2941
try {
3042
logger('debug', 'Tracks', `Decoding track: ${encodedTrack}`)
3143
const decodedTrack = decodeTrack(encodedTrack)
44+
3245
if (decodedTrack.details) {
3346
decodedTrack.pluginInfo = {
3447
...decodedTrack.pluginInfo,
3548
details: decodedTrack.details
3649
}
37-
3850
delete decodedTrack.details
3951
}
52+
4053
sendResponse(req, res, decodedTrack, 200)
4154
} catch (err) {
4255
logger('error', 'Tracks', `Failed to decode track ${encodedTrack}:`, err)
@@ -51,6 +64,7 @@ function handler(_nodelink, req, res, sendResponse, parsedUrl) {
5164
)
5265
}
5366
}
67+
5468
export default {
5569
handler
56-
}
70+
}

src/api/decodeTracks.js

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
1-
import myzod from 'myzod'
1+
import Validator from 'fastest-validator'
22
import { decodeTrack, logger, sendErrorResponse } from '../utils.js'
33

4-
const decodeTracksSchema = myzod.array(myzod.string()).min(1)
4+
const v = new Validator({ haltOnFirstError: true })
5+
6+
const decodeTracksSchema = v.compile({
7+
$$root: true,
8+
type: 'array',
9+
items: 'string',
10+
min: 1,
11+
messages: {
12+
arrayMin: 'encodedTracks parameter must be a non-empty array of strings.',
13+
array: 'encodedTracks parameter must be a non-empty array of strings.'
14+
}
15+
})
516

617
function handler(_nodelink, req, res, sendResponse, parsedUrl) {
7-
const result = decodeTracksSchema.try(req.body)
18+
const validation = decodeTracksSchema(req.body)
819

9-
if (result instanceof myzod.ValidationError) {
10-
const errorMessage =
11-
result.message ||
12-
'encodedTracks parameter must be a non-empty array of strings.'
20+
if (validation !== true) {
21+
const errorMessage = validation?.[0]?.message || 'encodedTracks parameter must be a non-empty array of strings.'
1322
sendErrorResponse(
1423
req,
1524
res,
@@ -22,7 +31,7 @@ function handler(_nodelink, req, res, sendResponse, parsedUrl) {
2231
return
2332
}
2433

25-
const encodedTracks = result
34+
const encodedTracks = req.body
2635

2736
const decodedTracks = []
2837
logger('debug', 'Tracks', `Decoding ${encodedTracks.length} tracks.`)

src/api/encodeTrack.js

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
1-
import myzod from 'myzod'
1+
import Validator from 'fastest-validator'
22
import { encodeTrack, logger, sendErrorResponse } from '../utils.js'
33

4-
const encodeTrackSchema = myzod.object({
5-
track: myzod.string()
4+
const v = new Validator({ haltOnFirstError: true })
5+
6+
const encodeTrackSchema = v.compile({
7+
track: { type: 'string', empty: false, messages: { required: 'Missing track parameter.', stringEmpty: 'Missing track parameter.' } }
68
})
79

810
function handler(_nodelink, req, res, sendResponse, parsedUrl) {
9-
const result = encodeTrackSchema.try({
10-
track: parsedUrl.searchParams.get('track')
11-
})
11+
const data = {
12+
track: parsedUrl.searchParams.get('track') ?? undefined
13+
}
14+
15+
const validation = encodeTrackSchema(data)
1216

13-
if (result instanceof myzod.ValidationError) {
14-
const errorMessage = result.message || 'Missing track parameter.'
17+
if (validation !== true) {
18+
const errorMessage = validation?.[0]?.message || 'Missing track parameter.'
1519
sendErrorResponse(
1620
req,
1721
res,
@@ -24,7 +28,7 @@ function handler(_nodelink, req, res, sendResponse, parsedUrl) {
2428
return
2529
}
2630

27-
const track = result.track
31+
const track = data.track
2832

2933
try {
3034
logger('debug', 'Tracks', `Encoding track: ${track}`)

src/api/encodedTracks.js

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,31 @@
1-
import myzod from 'myzod'
1+
import Validator from 'fastest-validator'
22
import { encodeTrack, logger, sendErrorResponse } from '../utils.js'
33

4-
const encodedTracksSchema = myzod
5-
.array(
6-
myzod
7-
.object({
8-
encoded: myzod.string(),
9-
info: myzod.object({}).allowUnknownKeys()
10-
})
11-
.allowUnknownKeys()
12-
)
13-
.min(1)
4+
const v = new Validator({ haltOnFirstError: true })
5+
6+
const encodedTracksSchema = v.compile({
7+
$$root: true,
8+
type: 'array',
9+
min: 1,
10+
items: {
11+
type: 'object',
12+
props: {
13+
encoded: { type: 'string', empty: false },
14+
info: { type: 'object', optional: false }
15+
},
16+
$$strict: false
17+
},
18+
messages: {
19+
arrayMin: 'tracks parameter must be an array and cannot be empty.'
20+
}
21+
})
1422

1523
function handler(_nodelink, req, res, sendResponse, parsedUrl) {
16-
const result = encodedTracksSchema.try(req.body)
24+
const validation = encodedTracksSchema(req.body)
1725

18-
if (result instanceof myzod.ValidationError) {
26+
if (validation !== true) {
1927
const errorMessage =
20-
result.message || 'tracks parameter must be an array and cannot be empty.'
28+
validation?.[0]?.message || 'tracks parameter must be an array and cannot be empty.'
2129
sendErrorResponse(
2230
req,
2331
res,
@@ -30,7 +38,7 @@ function handler(_nodelink, req, res, sendResponse, parsedUrl) {
3038
return
3139
}
3240

33-
const tracks = result
41+
const tracks = req.body
3442

3543
const encodedTracks = []
3644
logger('debug', 'Tracks', `Encoding ${tracks.length} tracks.`)

src/api/loadChapters.js

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,29 @@
1-
import myzod from 'myzod'
1+
import Validator from 'fastest-validator'
22
import { decodeTrack, logger, sendErrorResponse } from '../utils.js'
33

4-
const loadChaptersSchema = myzod.object({
5-
encodedTrack: myzod.string()
4+
const v = new Validator({ haltOnFirstError: true })
5+
6+
const loadChaptersSchema = v.compile({
7+
encodedTrack: {
8+
type: 'string',
9+
empty: false,
10+
messages: {
11+
required: 'Missing encodedTrack parameter.',
12+
string: 'Missing encodedTrack parameter.',
13+
stringEmpty: 'Missing encodedTrack parameter.'
14+
}
15+
}
616
})
717

818
async function handler(nodelink, req, res, sendResponse, parsedUrl) {
9-
const result = loadChaptersSchema.try({
10-
encodedTrack: parsedUrl.searchParams.get('encodedTrack')
11-
})
19+
const data = {
20+
encodedTrack: parsedUrl.searchParams.get('encodedTrack') ?? undefined
21+
}
22+
23+
const validation = loadChaptersSchema(data)
1224

13-
if (result instanceof myzod.ValidationError) {
14-
const errorMessage = result.message || 'Missing encodedTrack parameter.'
25+
if (validation !== true) {
26+
const errorMessage = validation?.[0]?.message || 'Missing encodedTrack parameter.'
1527
return sendErrorResponse(
1628
req,
1729
res,
@@ -22,7 +34,7 @@ async function handler(nodelink, req, res, sendResponse, parsedUrl) {
2234
)
2335
}
2436

25-
const encodedTrack = result.encodedTrack.replace(/ /g, '+')
37+
const encodedTrack = data.encodedTrack.replace(/ /g, '+')
2638

2739
try {
2840
const decodedTrack = decodeTrack(encodedTrack)

src/api/loadLyrics.js

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
1-
import myzod from 'myzod'
1+
import Validator from 'fastest-validator'
22
import { decodeTrack, logger, sendErrorResponse } from '../utils.js'
33

4-
const loadLyricsSchema = myzod.object({
5-
encodedTrack: myzod.string(),
6-
lang: myzod.string().optional()
4+
const v = new Validator({ haltOnFirstError: true })
5+
6+
const loadLyricsSchema = v.compile({
7+
encodedTrack: { type: 'string', empty: false, messages: { required: 'Missing encodedTrack parameter.', stringEmpty: 'Missing encodedTrack parameter.' } },
8+
lang: { type: 'string', optional: true }
79
})
810

911
async function handler(nodelink, req, res, sendResponse, parsedUrl) {
10-
const result = loadLyricsSchema.try({
11-
encodedTrack: parsedUrl.searchParams.get('encodedTrack'),
12+
const data = {
13+
encodedTrack: parsedUrl.searchParams.get('encodedTrack') ?? undefined,
1214
lang: parsedUrl.searchParams.get('lang') || undefined
13-
})
15+
}
16+
17+
const validation = loadLyricsSchema(data)
1418

15-
if (result instanceof myzod.ValidationError) {
16-
const errorMessage = result.message || 'Missing encodedTrack parameter.'
19+
if (validation !== true) {
20+
const errorMessage = validation?.[0]?.message || 'Missing encodedTrack parameter.'
1721
logger('warn', 'Lyrics', errorMessage)
1822
return sendErrorResponse(
1923
req,
@@ -25,8 +29,8 @@ async function handler(nodelink, req, res, sendResponse, parsedUrl) {
2529
)
2630
}
2731

28-
const encodedTrack = result.encodedTrack.replace(/ /g, '+')
29-
const language = result.lang
32+
const encodedTrack = data.encodedTrack.replace(/ /g, '+')
33+
const language = data.lang
3034

3135
try {
3236
const decodedTrack = decodeTrack(encodedTrack)

src/api/loadStream.js

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import { pipeline } from 'node:stream'
2-
import myzod from 'myzod'
2+
import Validator from 'fastest-validator'
33
import { createPCMStream } from '../playback/processing/streamProcessor.js'
44
import { decodeTrack, logger, sendErrorResponse } from '../utils.js'
55

6-
const loadStreamSchema = myzod.object({
7-
encodedTrack: myzod.string(),
8-
volume: myzod.number().min(0).max(1000).optional(),
9-
position: myzod.number().min(0).optional(),
10-
filters: myzod.unknown().optional()
6+
const v = new Validator({ haltOnFirstError: true })
7+
8+
const loadStreamSchema = v.compile({
9+
encodedTrack: { type: 'string', empty: false },
10+
volume: { type: 'number', min: 0, max: 1000, optional: true },
11+
position: { type: 'number', min: 0, optional: true },
12+
filters: { type: 'any', optional: true }
1113
})
1214

1315
async function handler(nodelink, req, res, _sendResponse, parsedUrl) {
@@ -22,10 +24,10 @@ async function handler(nodelink, req, res, _sendResponse, parsedUrl) {
2224
)
2325
}
2426

25-
let result
27+
let data
2628
try {
2729
if (req.method === 'POST') {
28-
result = loadStreamSchema.try(req.body)
30+
data = req.body
2931
} else {
3032
const filtersRaw = parsedUrl.searchParams.get('filters')
3133
let filters
@@ -37,8 +39,8 @@ async function handler(nodelink, req, res, _sendResponse, parsedUrl) {
3739
}
3840
}
3941

40-
result = loadStreamSchema.try({
41-
encodedTrack: parsedUrl.searchParams.get('encodedTrack'),
42+
data = {
43+
encodedTrack: parsedUrl.searchParams.get('encodedTrack') ?? undefined,
4244
volume: parsedUrl.searchParams.get('volume')
4345
? Number(parsedUrl.searchParams.get('volume'))
4446
: undefined,
@@ -51,21 +53,23 @@ async function handler(nodelink, req, res, _sendResponse, parsedUrl) {
5153
)
5254
: undefined,
5355
filters
54-
})
56+
}
5557
}
5658

57-
if (result instanceof myzod.ValidationError) {
59+
const validation = loadStreamSchema(data)
60+
61+
if (validation !== true) {
5862
return sendErrorResponse(
5963
req,
6064
res,
6165
400,
6266
'Bad Request',
63-
result.message,
67+
validation?.[0]?.message || 'Invalid parameters',
6468
parsedUrl.pathname
6569
)
6670
}
6771

68-
const { encodedTrack, volume = 100, position = 0, filters = {} } = result
72+
const { encodedTrack, volume = 100, position = 0, filters = {} } = data
6973
const decodedTrack = decodeTrack(encodedTrack.replace(/ /g, '+'))
7074

7175
if (!decodedTrack) {

0 commit comments

Comments
 (0)