Skip to content
Merged
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ const params = {
}
```

**Note:** This requires addok to support array values in filters. Make sure your addok version supports the new filter API.

### Reverse geocode

```js
Expand Down
38 changes: 17 additions & 21 deletions lib/params.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,26 +56,6 @@ export function validateLonLat(lon, lat) {
return [lon, lat]
}

export function formatFilterValue(value) {
if (typeof value === 'string') {
return value
}

if (Array.isArray(value)) {
// Validate that all elements are strings
for (const item of value) {
if (typeof item !== 'string') {
throw createError(400, 'filter values must be strings or arrays of strings')
}
}

// Join with '+' separator for addok multi-value filters
return value.join('+')
}

throw createError(400, 'filter values must be strings or arrays of strings')
}

export function validateFilters(filters) {
if (typeof filters !== 'object' || Array.isArray(filters)) {
throw createError(400, 'filters are not valid')
Expand All @@ -84,7 +64,23 @@ export function validateFilters(filters) {
const validatedFilters = {}

for (const [key, value] of Object.entries(pickBy(filters))) {
validatedFilters[key] = formatFilterValue(value)
// Validate that value is either a string or an array of strings
if (typeof value === 'string') {
validatedFilters[key] = value
} else if (Array.isArray(value)) {
// Skip empty arrays
if (value.length === 0) {
continue
}

if (!value.every(item => typeof item === 'string')) {
throw createError(400, 'filter values must be strings or arrays of strings')
}

validatedFilters[key] = value
} else {
throw createError(400, 'filter values must be strings or arrays of strings')
}
}

return validatedFilters
Expand Down
38 changes: 13 additions & 25 deletions test/params.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
validateLimit,
validateAutocomplete,
validateLonLat,
formatFilterValue,
validateFilters,
validateParams
} from '../lib/params.js'
Expand Down Expand Up @@ -81,36 +80,17 @@ test('validateFilters', t => {
t.throws(() => validateFilters('a'), {message: 'filters are not valid'})
})

test('formatFilterValue', t => {
// String values (backward compatibility)
t.is(formatFilterValue('bar'), 'bar')
t.is(formatFilterValue('75001'), '75001')

// Array values (new feature)
t.is(formatFilterValue(['bar', 'baz']), 'bar+baz')
t.is(formatFilterValue(['75001', '75002', '75003']), '75001+75002+75003')
t.is(formatFilterValue(['single']), 'single')

// Empty array
t.is(formatFilterValue([]), '')

// Invalid values
t.throws(() => formatFilterValue(123), {message: 'filter values must be strings or arrays of strings'})
t.throws(() => formatFilterValue(['valid', 123]), {message: 'filter values must be strings or arrays of strings'})
t.throws(() => formatFilterValue({foo: 'bar'}), {message: 'filter values must be strings or arrays of strings'})
})

test('validateFilters with array values', t => {
// Single string values (backward compatibility)
t.deepEqual(validateFilters({postcode: '75001'}), {postcode: '75001'})

// Array values
t.deepEqual(validateFilters({postcode: ['75001', '75002']}), {postcode: '75001+75002'})
// Array values - preserved as arrays
t.deepEqual(validateFilters({postcode: ['75001', '75002']}), {postcode: ['75001', '75002']})
t.deepEqual(validateFilters({
postcode: ['75001', '75002'],
citycode: '75056'
}), {
postcode: '75001+75002',
postcode: ['75001', '75002'],
citycode: '75056'
})

Expand All @@ -120,12 +100,20 @@ test('validateFilters with array values', t => {
postcode: ['75001', '75002', '75003']
}), {
type: 'street',
postcode: '75001+75002+75003'
postcode: ['75001', '75002', '75003']
})

// Single item array
t.deepEqual(validateFilters({postcode: ['75001']}), {postcode: ['75001']})

// Empty array - should be ignored
t.deepEqual(validateFilters({postcode: []}), {})
t.deepEqual(validateFilters({postcode: [], type: 'street'}), {type: 'street'})

// Invalid filter values
t.throws(() => validateFilters({postcode: 123}), {message: 'filter values must be strings or arrays of strings'})
t.throws(() => validateFilters({postcode: ['valid', 123]}), {message: 'filter values must be strings or arrays of strings'})
t.throws(() => validateFilters({postcode: {foo: 'bar'}}), {message: 'filter values must be strings or arrays of strings'})
})

test('validateParams / all params', t => {
Expand Down Expand Up @@ -157,7 +145,7 @@ test('validateParams / filters with array values', t => {
}), {
q: 'rue de la paix',
filters: {
postcode: '75001+75002',
postcode: ['75001', '75002'],
type: 'street'
}
})
Expand Down
Loading