mirror of
https://github.com/tcgdex/cards-database.git
synced 2025-04-25 12:22:14 +00:00
fix: Invalid card when searching using the set and localid (#472)
This commit is contained in:
parent
8684fb14e4
commit
33007d83bc
22
.bruno/fixes/471-invalid-set-sorting.bru
Normal file
22
.bruno/fixes/471-invalid-set-sorting.bru
Normal file
@ -0,0 +1,22 @@
|
||||
meta {
|
||||
name: 471-invalid-set-sorting
|
||||
type: http
|
||||
seq: 2
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{BASE_URL}}/v2/en/sets/swsh12/10
|
||||
body: none
|
||||
auth: none
|
||||
}
|
||||
|
||||
assert {
|
||||
res.body.id: eq swsh12-010
|
||||
res.status: eq 200
|
||||
}
|
||||
|
||||
docs {
|
||||
Validate the issue seen in
|
||||
|
||||
https://github.com/tcgdex/cards-database/issues/471
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"compile": "bun compiler/index.ts",
|
||||
"dev": "bun --watch --hot src/index.ts",
|
||||
"dev": "bun --watch src/index.ts",
|
||||
"validate": "tsc --noEmit --project ./tsconfig.json",
|
||||
"start": "bun src/index.ts"
|
||||
},
|
||||
|
@ -69,7 +69,7 @@ export default class Card implements LocalCard {
|
||||
}
|
||||
|
||||
public static findOne(lang: SupportedLanguages, query: Query<SDKCard>) {
|
||||
const res = handleValidation(this.getAll(lang), query)
|
||||
const res = handleSort(handleValidation(this.getAll(lang), query), query)
|
||||
if (res.length === 0) {
|
||||
return undefined
|
||||
}
|
||||
|
@ -30,8 +30,8 @@ const endpointToField: Record<string, keyof SDKCard> = {
|
||||
}
|
||||
|
||||
server
|
||||
// Midleware that handle caching
|
||||
.use(apicache.middleware('1 day', (req: Request) => req.method === 'GET', {}))
|
||||
// Midleware that handle caching only in production and on GET requests
|
||||
.use(apicache.middleware('1 day', (req: Request) => process.env.NODE_ENV === 'production' && req.method === 'GET', {}))
|
||||
|
||||
// .get('/cache/performance', (req, res) => {
|
||||
// res.json(apicache.getPerformance())
|
||||
@ -186,23 +186,23 @@ server
|
||||
let result: any | undefined
|
||||
switch (endpoint) {
|
||||
case 'cards':
|
||||
result = Card.findOne(lang, { filters: { id }})?.full()
|
||||
result = Card.findOne(lang, { filters: { id }, strict: true })?.full()
|
||||
if (!result) {
|
||||
result = Card.findOne(lang, { filters: { name: id }})?.full()
|
||||
result = Card.findOne(lang, { filters: { name: id }, strict: true })?.full()
|
||||
}
|
||||
break
|
||||
|
||||
case 'sets':
|
||||
result = Set.findOne(lang, { filters: { id }})?.full()
|
||||
result = Set.findOne(lang, { filters: { id }, strict: true })?.full()
|
||||
if (!result) {
|
||||
result = Set.findOne(lang, {filters: { name: id }})?.full()
|
||||
result = Set.findOne(lang, {filters: { name: id }, strict: true })?.full()
|
||||
}
|
||||
break
|
||||
|
||||
case 'series':
|
||||
result = Serie.findOne(lang, { filters: { id }})?.full()
|
||||
result = Serie.findOne(lang, { filters: { id }, strict: true })?.full()
|
||||
if (!result) {
|
||||
result = Serie.findOne(lang, { filters: { name: id }})?.full()
|
||||
result = Serie.findOne(lang, { filters: { name: id }, strict: true })?.full()
|
||||
}
|
||||
break
|
||||
default:
|
||||
@ -242,7 +242,7 @@ server
|
||||
switch (endpoint) {
|
||||
case 'sets':
|
||||
result = Card
|
||||
.findOne(lang, { filters: { localId: subid, set: id }})?.full()
|
||||
.findOne(lang, { filters: { localId: subid, set: id }, strict: true})?.full()
|
||||
break
|
||||
}
|
||||
if (!result) {
|
||||
|
4
server/src/interfaces.d.ts
vendored
4
server/src/interfaces.d.ts
vendored
@ -28,6 +28,10 @@ export interface Query<T extends {} = {}> {
|
||||
*/
|
||||
filters?: Partial<{ [Key in keyof T]: T[Key] extends object ? string | number | Array<string | number> : T[Key] | Array<T[Key]> }>
|
||||
|
||||
/**
|
||||
* instead of filtering text search it will search using the full string
|
||||
*/
|
||||
strict?: boolean
|
||||
/**
|
||||
* data sorting
|
||||
*
|
||||
|
@ -59,9 +59,15 @@ export function betterSorter(a: string, b: string) {
|
||||
*
|
||||
* @param validator the validation object
|
||||
* @param value the value to validate
|
||||
* @param strict change how the results are fetched
|
||||
* @returns `true` if valid else `false`
|
||||
*/
|
||||
export function validateItem(validator: any | Array<any>, value: any): boolean {
|
||||
export function validateItem(validator: any | Array<any>, value: any, strict: boolean = false): boolean {
|
||||
// convert to number is possible
|
||||
if (/^\d+$/.test(validator)) {
|
||||
validator = parseInt(validator)
|
||||
}
|
||||
|
||||
if (typeof value === 'object') {
|
||||
// invert signal so that an early exit mean that a match was found!
|
||||
return !objectLoop(value, (v) => {
|
||||
@ -69,14 +75,14 @@ export function validateItem(validator: any | Array<any>, value: any): boolean {
|
||||
if (typeof v === 'object') return true
|
||||
|
||||
// check for each childs until one match
|
||||
return !validateItem(validator, v)
|
||||
return !validateItem(validator, v, strict)
|
||||
})
|
||||
}
|
||||
|
||||
// loop to validate for an array
|
||||
if (Array.isArray(validator)) {
|
||||
for (const sub of validator) {
|
||||
const res = validateItem(sub, value)
|
||||
const res = validateItem(sub, value, strict)
|
||||
if (res) {
|
||||
return true
|
||||
}
|
||||
@ -84,8 +90,12 @@ export function validateItem(validator: any | Array<any>, value: any): boolean {
|
||||
return false
|
||||
}
|
||||
if (typeof validator === 'string') {
|
||||
// run a string validation
|
||||
return value.toString().toLowerCase().includes(validator.toLowerCase())
|
||||
// run a strict string validation
|
||||
if (strict) {
|
||||
return value.toString().toLowerCase() === validator.toLowerCase()
|
||||
} else {
|
||||
return value.toString().toLowerCase().includes(validator.toLowerCase())
|
||||
}
|
||||
} else if (typeof validator === 'number') {
|
||||
// run a number validation
|
||||
if (typeof value === 'number') {
|
||||
@ -197,6 +207,6 @@ export function handleValidation(data: Array<any>, query: Query) {
|
||||
}
|
||||
|
||||
return data.filter((v) => objectLoop(filters, (valueToValidate, key) => {
|
||||
return validateItem(valueToValidate, v[key])
|
||||
return validateItem(valueToValidate, v[key], query.strict)
|
||||
}))
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user