Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

getOrCreate, Error Handler and CreateIndex Usage changes #436

Merged
merged 20 commits into from
Jun 16, 2020
Merged
Show file tree
Hide file tree
Changes from 18 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
10 changes: 5 additions & 5 deletions .code-samples.meilisearch.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ get_one_index_1: |-
list_all_indexes_1: |-
client.listIndexes()
create_an_index_1: |-
client.createIndex({ uid: 'movies' })
client.createIndex('movies')
update_an_index_1: |-
client.updateIndex({ uid: 'movies' })
client.updateIndex('movies', { primaryKey: 'movie_review_id' })
delete_an_index_1: |-
client.getIndex('movies').deleteIndex()
get_one_document_1: |-
Expand Down Expand Up @@ -322,7 +322,7 @@ getting_started_create_index_md: |-

var client = new MeiliSearch({ host: 'http://127.0.0.1:7700' })
const index = client
.createIndex({ uid: 'movies' })
.createIndex('movies')
.then((res) => console.log(res))
```

Expand Down Expand Up @@ -360,12 +360,12 @@ faceted_search_facet_filters_1: |-
client.getIndex('movies')
.search('thriller', {
facetFilters: [['genres:Horror', 'genres:Mystery'], 'director:Jordan Peele']
})
})
faceted_search_facets_distribution_1: |-
client.getIndex('movies')
.search('Batman', {
facetsDistribution: ['genres']
})
})
faceted_search_walkthrough_attributes_for_faceting_1: |-
client.getIndex('movies')
.updateAttributesForFaceting([
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
## V0.10 (released)

- BREAKING: Usage of createIndex changed #436
- Error Handler improved by adding a new MeiliSearchCommunicationError #436
- Refactor Error handler #436
- FEATURE: Add getOrCreateIndex method to meilisearch client #436


bidoubiwa marked this conversation as resolved.
Show resolved Hide resolved
## V0.10.1 (released)

- Fix bug where you could not import the CJS package from a ES6 node environment. #410

## V0.10 (released)
Expand Down
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ import MeiliSearch from 'meilisearch'
apiKey: 'masterKey',
})

const index = await client.createIndex({ uid: 'books' }) // If your index does not exists
const index = await client.createIndex('books') // If your index does not exists
// OR
const index = client.getIndex('books') // If your index exists

Expand Down Expand Up @@ -140,9 +140,9 @@ In this section, the examples contain the [`await` keyword](https://developer.mo

```javascript
// Create an index
const index = await client.createIndex({ uid: 'books' })
const index = await client.createIndex('books')
// Create an index and give the primary-key
const index = await client.createIndex({ uid: 'books', primaryKey: 'book_id' })
const index = await client.createIndex('books', { primaryKey: 'book_id' })
```

#### List all indexes <!-- omit in toc -->
Expand Down Expand Up @@ -325,19 +325,23 @@ A GitHub Action will be triggered and push the package on [npm](https://www.npmj

- Create new index:

`client.createIndex(data: IndexRequest): Promise<Index>`
`client.createIndex(uid: string, options?: IndexOptions): Promise<Index>`

- Get index object:

`client.getIndex(uid: string): Indexes`

- Get or create index if it does not exist

`client.getOrCreateIndex(uid: string, options?: IndexOptions): Promise<Index>`

- Show Index information:

`index.show(): Promise<IndexResponse>`

- Update Index:

`index.updateIndex(data: UpdateIndexRequest): Promise<IndexResponse>`
`index.updateIndex(data: IndexOptions): Promise<IndexResponse>`

- Delete Index:

Expand Down
2 changes: 1 addition & 1 deletion examples/search_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const addDataset = async () => {
console.log({ indexes, indexFound })

if (!indexFound) {
await meili.createIndex(index)
await meili.createIndex(index.uid)
}
const documents = await meili.getIndex(index.uid).getDocuments()
if (documents.length === 0) {
Expand Down
10 changes: 7 additions & 3 deletions examples/small_index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const config = {

var meili = new MeiliSearch(config)

const index = {
const newIndex = {
uid: 'movies_test',
}

Expand All @@ -30,6 +30,10 @@ const dataset = [
]

;(async () => {
await meili.createIndex(index)
await meili.getIndex(index.uid).addDocuments(dataset)
try {
const index = await meili.getOrCreateIndex(newIndex.uid)
await index.addDocuments(dataset)
} catch(e) {
console.error(e)
}
})()
15 changes: 15 additions & 0 deletions src/errors/http-error-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { AxiosError } from 'axios'
import MeiliSearchApiError from './meilisearch-api-error'
import MeiliSearchCommunicationError from './meilisearch-communication-error'

function httpErrorHandler(e: AxiosError, cachedStack?: string): void {
if (e.response !== undefined) {
throw new MeiliSearchApiError(e, cachedStack)
} else if (e.isAxiosError) {
throw new MeiliSearchCommunicationError(e.message)
} else {
throw e
}
}

export { httpErrorHandler }
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ const MeiliSearchApiError: Types.MeiliSearchApiErrorConstructor = class
extends Error
implements Types.MeiliSearchApiErrorInterface {
response?: Types.MeiliSearchApiErrorResponse
request?: Types.MeiliSearchApiErrorRequest
errorCode?: string
errorType?: string
errorLink?: string
stack?: string
type: string

constructor(error: AxiosError, cachedStack?: string) {
Expand All @@ -22,26 +25,16 @@ const MeiliSearchApiError: Types.MeiliSearchApiErrorConstructor = class
statusText: error.response.statusText,
path: error.response.config.url,
method: error.response.config.method,
body: error.response.data,
}

this.request = {
url: error.request._currentUrl,
path: error.config.url,
method: error.config.method,
}
// If a custom message was sent back by our API
// We change the error message to be more explicit
if (error.response.data?.message !== undefined) {
this.errorCode = error.response.data.errorCode
this.errorType = error.response.data.errorType
this.errorLink = error.response.data.errorLink
this.message = error.response.data.message
}
} else {
// If MeiliSearch did not answered
this.request = {
url: error.request._currentUrl,
path: error.config.url,
method: error.config.method,
}
}

// use cached Stack on error object to keep the call stack
Expand Down
11 changes: 11 additions & 0 deletions src/errors/meilisearch-communication-error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class MeiliSearchCommunicationError extends Error {
type: string
constructor(message: string) {
super(message)
this.name = 'MeiliSearchCommunicationError'
this.type = 'MeiliSearchCommunicationError'
Error.captureStackTrace(this, MeiliSearchCommunicationError)
}
}

export default MeiliSearchCommunicationError
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

'use strict'

import MeiliSearchTimeOutError from './custom-errors/meilisearch-timeout-error'
import MeiliSearchTimeOutError from './errors/meilisearch-timeout-error'
import MeiliAxiosWrapper from './meili-axios-wrapper'
import * as Types from './types'
import { sleep } from './utils'
Expand Down Expand Up @@ -153,7 +153,7 @@ class Index extends MeiliAxiosWrapper implements Types.IndexInterface {
* @method updateIndex
*/
async updateIndex(
data: Types.UpdateIndexRequest
data: Types.IndexOptions
): Promise<Types.IndexResponse> {
const url = `/indexes/${this.uid}`

Expand Down
12 changes: 6 additions & 6 deletions src/meili-axios-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import instance, {
AxiosResponse,
CancelTokenSource,
} from 'axios'
import MeiliSearchApiError from './custom-errors/meilisearch-error'
import { httpErrorHandler } from './errors/http-error-handler'
import * as Types from './types'

class MeiliAxiosWrapper implements Types.MeiliAxiosWrapperInterface {
Expand Down Expand Up @@ -55,7 +55,7 @@ class MeiliAxiosWrapper implements Types.MeiliAxiosWrapperInterface {
try {
return await this.instance.get(url, config)
} catch (e) {
throw new MeiliSearchApiError(e, cachedStack)
throw httpErrorHandler(e, cachedStack)
}
}

Expand All @@ -81,7 +81,7 @@ class MeiliAxiosWrapper implements Types.MeiliAxiosWrapperInterface {
try {
return await this.instance.post(url, data, config)
} catch (e) {
throw new MeiliSearchApiError(e, cachedStack)
throw httpErrorHandler(e, cachedStack)
}
}

Expand All @@ -94,7 +94,7 @@ class MeiliAxiosWrapper implements Types.MeiliAxiosWrapperInterface {
try {
return await this.instance.put(url, data, config)
} catch (e) {
throw new MeiliSearchApiError(e, cachedStack)
throw httpErrorHandler(e, cachedStack)
}
}

Expand All @@ -107,7 +107,7 @@ class MeiliAxiosWrapper implements Types.MeiliAxiosWrapperInterface {
try {
return await this.instance.patch(url, data, config)
} catch (e) {
throw new MeiliSearchApiError(e, cachedStack)
throw httpErrorHandler(e, cachedStack)
}
}

Expand All @@ -119,7 +119,7 @@ class MeiliAxiosWrapper implements Types.MeiliAxiosWrapperInterface {
try {
return await this.instance.delete(url, config)
} catch (e) {
throw new MeiliSearchApiError(e, cachedStack)
throw httpErrorHandler(e, cachedStack)
}
}
}
Expand Down
29 changes: 26 additions & 3 deletions src/meilisearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,32 @@ class Meilisearch extends MeiliAxiosWrapper
/**
* Return an Index instance
* @memberof Meilisearch
* @method Index
* @method getIndex
*/
getIndex(indexUid: string): Index {
return new Index(this.config, indexUid)
}

/**
* Get an index or create it if it does not exist
* @memberof Meilisearch
* @method getOrCreateIndex
*/
async getOrCreateIndex(
uid: string,
options: Types.IndexOptions = {}
): Promise<Index> {
try {
const index = await this.createIndex(uid, options)
return index
} catch (e) {
if (e.errorCode === 'index_already_exists') {
return this.getIndex(uid)
}
throw e
}
}

/**
* List all indexes in the database
* @memberof Meilisearch
Expand All @@ -44,10 +64,13 @@ class Meilisearch extends MeiliAxiosWrapper
* @memberof Meilisearch
* @method createIndex
*/
async createIndex(data: Types.IndexRequest): Promise<Index> {
async createIndex(
uid: string,
options: Types.IndexOptions = {}
): Promise<Index> {
const url = '/indexes'

const index = await this.post(url, data)
const index = await this.post(url, { ...options, uid })

return new Index(this.config, index.uid)
}
Expand Down
24 changes: 15 additions & 9 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import {
import { Index } from './index'
import MeiliAxiosWrapper from './meili-axios-wrapper'
import MeiliSearch from './meilisearch'
import MeiliSearchApiError from './custom-errors/meilisearch-error'
import MeiliSearchTimeOutError from './custom-errors/meilisearch-timeout-error'
import MeiliSearchApiError from './errors/meilisearch-api-error'
import MeiliSearchTimeOutError from './errors/meilisearch-timeout-error'
export { Index }
export { MeiliSearchApiError }
export { MeiliSearchTimeOutError }
Expand All @@ -35,6 +35,10 @@ export interface IndexRequest {
primaryKey?: string
}

export interface IndexOptions {
primaryKey?: string
}

export interface IndexResponse {
uid: string
name?: string
Expand All @@ -43,10 +47,6 @@ export interface IndexResponse {
updatedAt: Date
}

export interface UpdateIndexRequest {
primaryKey?: string
}

export interface AddDocumentParams {
primaryKey?: string
}
Expand Down Expand Up @@ -222,8 +222,9 @@ export interface SysInfoPretty {
export interface MeiliSearchInterface extends MeiliAxiosWrapper {
config: Config
getIndex: (indexUid: string) => Index
getOrCreateIndex: (uid: string, options?: IndexOptions) => Promise<Index>
listIndexes: () => Promise<IndexResponse[]>
createIndex: (data: IndexRequest) => Promise<Index>
createIndex: (uid: string, options?: IndexOptions) => Promise<Index>
getKeys: () => Promise<Keys>
isHealthy: () => Promise<boolean>
setHealthy: () => Promise<void>
Expand All @@ -241,7 +242,7 @@ export interface IndexInterface extends MeiliAxiosWrapperInterface {
getAllUpdateStatus: () => Promise<Update[]>
search: (query: string, options?: SearchParams) => Promise<SearchResponse>
show: () => Promise<IndexResponse>
updateIndex: (data: UpdateIndexRequest) => Promise<IndexResponse>
updateIndex: (indexData: IndexOptions) => Promise<IndexResponse>
deleteIndex: () => Promise<string>
getStats: () => Promise<IndexStats>
getDocuments: (options?: GetDocumentsParams) => Promise<Document[]>
Expand Down Expand Up @@ -306,7 +307,7 @@ export interface MeiliAxiosWrapperInterface {
url: string,
data: IndexRequest,
config?: AxiosRequestConfig
) => Promise<IndexResponse>) &
) => Promise<Index>) &
(<T = any, R = AxiosResponse<EnqueuedUpdate>>(
url: string,
data?: T,
Expand Down Expand Up @@ -336,6 +337,11 @@ export interface MeiliSearchApiErrorInterface extends Error {
name: string
message: string
stack?: string
errorCode?: string
errorType?: string
errorLink?: string
response?: MeiliSearchApiErrorResponse
request?: MeiliSearchApiErrorRequest
}
export interface MeiliSearchApiErrorResponse {
status?: number
Expand Down
Loading