Skip to content

Commit df4714f

Browse files
meili-bors[bot]a11rewbidoubiwa
authored
Merge #861
861: Allows passed API key to be a callback function r=bidoubiwa a=a11rew # Pull Request ## Related issue Fixes #765 ## What does this PR do? - Adds support for passing function as API key - Documents this feature in the README - Adds validation for `instantMeiliSearch` parameters - Ensures hostUrl is a string and throws an error if otherwise - Ensures apiKey is a string or a function that returns a string, throws errors if otherwise - Adds tests for `instantMeiliSearch` parameters validation ## PR checklist Please check if your PR fulfills the following requirements: - [x] Does this PR fix an existing issue, or have you listed the changes applied in the PR description (and why they are needed)? - [x] Have you read the contributing guidelines? - [x] Have you made sure that the title is accurate and descriptive of the changes? Thank you so much for contributing to Meilisearch! Co-authored-by: Andrew Glago <[email protected]> Co-authored-by: cvermand <[email protected]>
2 parents 3fe8699 + d9835fa commit df4714f

File tree

5 files changed

+116
-5
lines changed

5 files changed

+116
-5
lines changed

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ const searchClient = instantMeiliSearch(
7575
)
7676
```
7777

78+
### Parameters
79+
80+
- `Host` - URL of Meilisearch instance
81+
- `API Key` - Meilisearch access API Key. This can either be a string or a synchronous function that returns a string. ⚠️ Prefer using a key with only [search permissions](https://docs.meilisearch.com/learn/security/master_api_keys.html#master-key-and-api-keys) as it is used on your front-end.
82+
7883
## 💅 Customization
7984

8085
`instant-meilisearch` offers some options you can set to further fit your needs.
@@ -1089,4 +1094,4 @@ If you want to know more about the development workflow or want to contribute, p
10891094

10901095
<hr>
10911096

1092-
**Meilisearch** provides and maintains many **SDKs and Integration tools** like this one. We want to provide everyone with an **amazing search experience for any kind of project**. If you want to contribute, make suggestions, or just know what's going on right now, visit us in the [integration-guides](https://github.com/meilisearch/integration-guides) repository.
1097+
**Meilisearch** provides and maintains many **SDKs and Integration tools** like this one. We want to provide everyone with an **amazing search experience for any kind of project**. If you want to contribute, make suggestions, or just know what's going on right now, visit us in the [integration-guides](https://github.com/meilisearch/integration-guides) repository.

src/client/instant-meilisearch-client.ts

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,32 @@ import {
1515
import { createSearchContext } from '../contexts'
1616
import { SearchCache, cacheFirstFacetDistribution } from '../cache/'
1717
import { constructClientAgents } from './agents'
18+
import { validateInstantMeiliSearchParams } from '../utils'
1819

1920
/**
20-
* Instanciate SearchClient required by instantsearch.js.
21-
*
21+
* apiKey callback definition
22+
* @callback apiKeyCallback
23+
* @returns {string} - The apiKey to use
24+
*/
25+
26+
/**
27+
* Instantiate SearchClient required by instantsearch.js.
2228
* @param {string} hostUrl
23-
* @param {string} apiKey
29+
* @param {string | apiKeyCallback} apiKey
2430
* @param {InstantMeiliSearchOptions={}} meiliSearchOptions
2531
* @returns {InstantMeiliSearchInstance}
2632
*/
2733
export function instantMeiliSearch(
2834
hostUrl: string,
29-
apiKey = '',
35+
apiKey: string | (() => string) = '',
3036
instantMeiliSearchOptions: InstantMeiliSearchOptions = {}
3137
): InstantMeiliSearchInstance {
38+
// Validate parameters
39+
validateInstantMeiliSearchParams(hostUrl, apiKey)
40+
41+
// Resolve possible function to get apiKey
42+
apiKey = getApiKey(apiKey)
43+
3244
const clientAgents = constructClientAgents(
3345
instantMeiliSearchOptions.clientAgents
3446
)
@@ -104,3 +116,24 @@ export function instantMeiliSearch(
104116
},
105117
}
106118
}
119+
120+
/**
121+
* Resolves apiKey if it is a function
122+
* @param {string | apiKeyCallback} apiKey
123+
* @returns {string} api key value
124+
*/
125+
function getApiKey(apiKey: string | (() => string)): string {
126+
// If apiKey is function, call it to get the apiKey
127+
if (typeof apiKey === 'function') {
128+
const apiKeyFnValue = apiKey()
129+
if (typeof apiKeyFnValue !== 'string') {
130+
throw new TypeError(
131+
'Provided apiKey function (2nd parameter) did not return a string, expected string'
132+
)
133+
}
134+
135+
return apiKeyFnValue
136+
}
137+
138+
return apiKey
139+
}

src/utils/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export * from './array'
22
export * from './string'
33
export * from './number'
44
export * from './object'
5+
export * from './validate'

src/utils/validate.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* apiKey callback definition
3+
* @callback apiKeyCallback
4+
* @returns {string} - The apiKey to use
5+
*/
6+
7+
/**
8+
* Validates host and apiKey parameters, throws if invalid
9+
* @param hostUrl
10+
* @param apiKey
11+
*/
12+
export function validateInstantMeiliSearchParams(
13+
hostUrl: string,
14+
apiKey: string | (() => string)
15+
) {
16+
// Validate host url
17+
if (typeof hostUrl !== 'string') {
18+
throw new TypeError(
19+
'Provided hostUrl value (1st parameter) is not a string, expected string'
20+
)
21+
}
22+
23+
// Validate api key
24+
if (typeof apiKey !== 'string' && typeof apiKey !== 'function') {
25+
throw new TypeError(
26+
'Provided apiKey value (2nd parameter) is not a string or a function, expected string or function'
27+
)
28+
}
29+
}

tests/instantiation.tests.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { instantMeiliSearch } from '../src'
2+
3+
describe('InstantMeiliSearch instantiation', () => {
4+
test('instantiation with required params returns InstantMeiliSearchInstance', () => {
5+
const searchClient = instantMeiliSearch(
6+
'http://localhost:7700',
7+
'masterKey'
8+
)
9+
10+
expect(searchClient).toBeTruthy()
11+
})
12+
13+
test('instantiation with function as apiKey returns InstantMeiliSearchInstance', () => {
14+
const searchClient = instantMeiliSearch('http://localhost:7700', () => {
15+
return 'masterKey'
16+
})
17+
18+
expect(searchClient).toBeTruthy()
19+
})
20+
21+
test('instantiation without hostUrl throws error', () => {
22+
expect(() => {
23+
// @ts-expect-error
24+
instantMeiliSearch(undefined, 'masterKey')
25+
}).toThrow(TypeError)
26+
})
27+
28+
test('instantiation without apiKey as function or string throws error', () => {
29+
expect(() => {
30+
// @ts-expect-error
31+
instantMeiliSearch('http://localhost:7700', 123)
32+
}).toThrow(TypeError)
33+
})
34+
35+
test('instantiation with function that does not return string as apiKey throws error', () => {
36+
expect(() => {
37+
// @ts-expect-error
38+
instantMeiliSearch('http://localhost:7700', () => {
39+
return 123
40+
})
41+
}).toThrow(TypeError)
42+
})
43+
})

0 commit comments

Comments
 (0)