Skip to content

Commit 3c31a46

Browse files
committed
feat: add in operator
1 parent 83fbf30 commit 3c31a46

4 files changed

Lines changed: 70 additions & 4 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,11 @@ PATCH /profile
140140
- `gt``>`
141141
- `gte``>=`
142142
- `ne``!=`
143+
- 'in' → `[].includes`
143144

144145
```
145146
GET /posts?views_gt=9000
147+
GET /posts?id_in[]=1&id_in[]=2
146148
```
147149

148150
### Range

src/app.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import assert from 'node:assert/strict'
1+
import assert from 'node:assert/strict'
22
import { writeFileSync } from 'node:fs'
33
import { join } from 'node:path'
44
import test from 'node:test'

src/service.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,31 @@ await test('find', async (t) => {
138138
params: { views_ne: post1.views.toString() },
139139
res: [post2, post3],
140140
},
141+
{
142+
name: POSTS,
143+
params: { id_in: [post1.id, post3.id] },
144+
res: [post1, post3],
145+
},
146+
{
147+
name: POSTS,
148+
params: { id_in: post2.id },
149+
res: [post2],
150+
},
151+
{
152+
name: POSTS,
153+
params: { views_in: [post1.views.toString(), post3.views.toString()] },
154+
res: [post1, post3],
155+
},
156+
{
157+
name: POSTS,
158+
params: { views_in: post2.views.toString() },
159+
res: [post2],
160+
},
161+
{
162+
name: POSTS,
163+
params: { views_in: ['xxx', post2.views.toString()] },
164+
res: [post2],
165+
},
141166
{
142167
name: POSTS,
143168
params: { views_lt: (post1.views + 1).toString() },

src/service.ts

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const Condition = {
2828
gt: 'gt',
2929
gte: 'gte',
3030
ne: 'ne',
31+
in: 'in',
3132
default: '',
3233
} as const
3334

@@ -197,12 +198,24 @@ export class Service {
197198
// Convert query params to conditions
198199
const conds: [string, Condition, string | string[]][] = []
199200
for (const [key, value] of Object.entries(query)) {
200-
if (value === undefined || typeof value !== 'string') {
201+
if (value === undefined) {
201202
continue
202203
}
203-
const re = /_(lt|lte|gt|gte|ne)$/
204+
const re = /_(lt|lte|gt|gte|ne|in)$/
204205
const reArr = re.exec(key)
205206
const op = reArr?.at(1)
207+
208+
if (Array.isArray(value)) {
209+
if (op === Condition.in && value.every((item) => typeof item === 'string')) {
210+
const field = key.replace(re, '')
211+
conds.push([field, op, value])
212+
}
213+
continue
214+
}
215+
216+
if (typeof value !== 'string') {
217+
continue
218+
}
206219
if (op && isCondition(op)) {
207220
const field = key.replace(re, '')
208221
conds.push([field, op, value])
@@ -218,7 +231,7 @@ export class Service {
218231
let filtered = items
219232
for (const [key, op, paramValue] of conds) {
220233
filtered = filtered.filter((item: Item) => {
221-
if (paramValue && !Array.isArray(paramValue)) {
234+
if (!Array.isArray(paramValue)) {
222235
// https://github.com/sindresorhus/dot-prop/issues/95
223236
const itemValue: unknown = getProperty(item, key)
224237
switch (op) {
@@ -262,6 +275,16 @@ export class Service {
262275
}
263276
break
264277
}
278+
// item_in=value
279+
case Condition.in: {
280+
switch (typeof itemValue) {
281+
case 'number':
282+
return itemValue === parseInt(paramValue)
283+
case 'string':
284+
return itemValue === paramValue
285+
}
286+
return false
287+
}
265288
// item=value
266289
case Condition.default: {
267290
switch (typeof itemValue) {
@@ -277,6 +300,22 @@ export class Service {
277300
}
278301
}
279302
}
303+
304+
if (Array.isArray(paramValue)) {
305+
const itemValue: unknown = getProperty(item, key)
306+
switch (op) {
307+
case Condition.in: {
308+
switch (typeof itemValue) {
309+
case 'number':
310+
return paramValue.some((pv) => itemValue === parseInt(pv))
311+
case 'string':
312+
return paramValue.includes(itemValue)
313+
}
314+
return false
315+
}
316+
}
317+
}
318+
280319
return true
281320
})
282321
}

0 commit comments

Comments
 (0)