Support for Elasticsearch 7.7 (#1192)

This commit is contained in:
Tomas Della Vedova
2020-05-14 09:55:54 +02:00
committed by GitHub
parent be6257380e
commit 51169d5efa
258 changed files with 15839 additions and 1485 deletions

View File

@ -0,0 +1,269 @@
// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information
import { expectType, expectError } from 'tsd'
import { Readable as ReadableStream } from 'stream';
import { TransportRequestCallback } from '../../lib/Transport'
import { Client, ApiError } from '../../'
const client = new Client({
node: 'http://localhost:9200'
})
interface SearchBody {
query: {
match: { foo: string }
}
}
interface ShardsResponse {
total: number;
successful: number;
failed: number;
skipped: number;
}
interface Explanation {
value: number;
description: string;
details: Explanation[];
}
interface SearchResponse<T> {
took: number;
timed_out: boolean;
_scroll_id?: string;
_shards: ShardsResponse;
hits: {
total: number;
max_score: number;
hits: Array<{
_index: string;
_type: string;
_id: string;
_score: number;
_source: T;
_version?: number;
_explanation?: Explanation;
fields?: any;
highlight?: any;
inner_hits?: any;
matched_queries?: string[];
sort?: string[];
}>;
};
aggregations?: any;
}
interface Source {
foo: string
}
// body that does not respect the RequestBody constraint
expectError(
client.search({
index: 'hello',
body: 42
}).then(console.log)
)
// No generics (promise style)
{
const response = await client.search({
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
})
expectType<Record<string, any>>(response.body)
expectType<unknown>(response.meta.context)
}
// Define only the response body (promise style)
{
const response = await client.search<SearchResponse<Source>>({
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
})
expectType<SearchResponse<Source>>(response.body)
expectType<unknown>(response.meta.context)
}
// Define response body and request body (promise style)
{
const response = await client.search<SearchResponse<Source>, SearchBody>({
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
})
expectType<SearchResponse<Source>>(response.body)
expectType<unknown>(response.meta.context)
}
// Define response body, request body and the context (promise style)
{
const response = await client.search<SearchResponse<Source>, SearchBody, string>({
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
})
expectType<SearchResponse<Source>>(response.body)
expectType<string>(response.meta.context)
}
// Send request body as string (promise style)
{
const response = await client.search({
index: 'test',
body: 'hello world'
})
expectType<Record<string, any>>(response.body)
expectType<unknown>(response.meta.context)
}
// Send request body as buffer (promise style)
{
const response = await client.search({
index: 'test',
body: Buffer.from('hello world')
})
expectType<Record<string, any>>(response.body)
expectType<unknown>(response.meta.context)
}
// Send request body as readable stream (promise style)
{
const response = await client.search({
index: 'test',
body: new ReadableStream()
})
expectType<Record<string, any>>(response.body)
expectType<unknown>(response.meta.context)
}
// No generics (callback style)
{
const result = client.search({
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
}, (err, response) => {
expectType<ApiError>(err)
expectType<Record<string, any>>(response.body)
expectType<unknown>(response.meta.context)
})
expectType<TransportRequestCallback>(result)
}
// Define only the response body (callback style)
{
const result = client.search<SearchResponse<Source>>({
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
}, (err, response) => {
expectType<ApiError>(err)
expectType<SearchResponse<Source>>(response.body)
expectType<unknown>(response.meta.context)
})
expectType<TransportRequestCallback>(result)
}
// Define response body and request body (callback style)
{
const result = client.search<SearchResponse<Source>, SearchBody>({
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
}, (err, response) => {
expectType<ApiError>(err)
expectType<SearchResponse<Source>>(response.body)
expectType<unknown>(response.meta.context)
})
expectType<TransportRequestCallback>(result)
}
// Define response body, request body and the context (callback style)
{
const result = client.search<SearchResponse<Source>, SearchBody, string>({
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
}, (err, response) => {
expectType<ApiError>(err)
expectType<SearchResponse<Source>>(response.body)
expectType<string>(response.meta.context)
})
expectType<TransportRequestCallback>(result)
}
// Send request body as string (callback style)
{
const result = client.search({
index: 'test',
body: 'hello world'
}, (err, response) => {
expectType<ApiError>(err)
expectType<Record<string, any>>(response.body)
expectType<unknown>(response.meta.context)
})
expectType<TransportRequestCallback>(result)
}
// Send request body as buffer (callback style)
{
const result = client.search({
index: 'test',
body: Buffer.from('hello world')
}, (err, response) => {
expectType<ApiError>(err)
expectType<Record<string, any>>(response.body)
expectType<unknown>(response.meta.context)
})
expectType<TransportRequestCallback>(result)
}
// Send request body as readable stream (callback style)
{
const result = client.search({
index: 'test',
body: new ReadableStream()
}, (err, response) => {
expectType<ApiError>(err)
expectType<Record<string, any>>(response.body)
expectType<unknown>(response.meta.context)
})
expectType<TransportRequestCallback>(result)
}

View File

@ -0,0 +1,65 @@
// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information
import { expectType } from 'tsd'
import { TransportRequestCallback } from '../../lib/Transport'
import { Client, ApiError } from '../../'
const client = new Client({
node: 'http://localhost:9200'
})
// No generics (promise style)
{
const response = await client.cat.count({ index: 'test' })
expectType<Record<string, any>>(response.body)
expectType<unknown>(response.meta.context)
}
// Define only the response body (promise style)
{
const response = await client.cat.count<string>({ index: 'test' })
expectType<string>(response.body)
expectType<unknown>(response.meta.context)
}
// Define response body and the context (promise style)
{
const response = await client.cat.count<string, string>({ index: 'test' })
expectType<string>(response.body)
expectType<string>(response.meta.context)
}
// No generics (callback style)
{
const result = client.cat.count({ index: 'test' }, (err, response) => {
expectType<ApiError>(err)
expectType<Record<string, any>>(response.body)
expectType<unknown>(response.meta.context)
})
expectType<TransportRequestCallback>(result)
}
// Define only the response body (callback style)
{
const result = client.cat.count<string>({ index: 'test' }, (err, response) => {
expectType<ApiError>(err)
expectType<string>(response.body)
expectType<unknown>(response.meta.context)
})
expectType<TransportRequestCallback>(result)
}
// Define response body and the context (callback style)
{
const result = client.cat.count<string, string>({ index: 'test' }, (err, response) => {
expectType<ApiError>(err)
expectType<string>(response.body)
expectType<string>(response.meta.context)
})
expectType<TransportRequestCallback>(result)
}

View File

@ -0,0 +1,618 @@
// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information
import { URL } from 'url'
import { expectType, expectError } from 'tsd'
import { TransportGetConnectionOptions } from '../../lib/Transport'
import {
Client,
Serializer,
Connection,
ConnectionPool,
Transport,
errors
} from '../../'
/**
* `node` option
*/
expectType<Client>(
new Client({
node: 'http://localhost:9200'
})
)
expectType<Client>(
new Client({
nodes: ['http://localhost:9200', 'http://localhost:9200']
})
)
expectType<Client>(
new Client({
node: {
url: new URL('http://localhost:9200'),
id: 'my-node'
}
})
)
expectType<Client>(
new Client({
nodes: [{
url: new URL('http://localhost:9200'),
id: 'my-node-1'
}, {
url: new URL('http://localhost:9201'),
id: 'my-node-2'
}]
})
)
expectError<errors.ConfigurationError>(
new Client({
node: 42
})
)
expectError<errors.ConfigurationError>(
new Client({
node: {
url: 'http://localhost:9200',
id: 'my-node'
}
})
)
/**
* `maxRetries` option
*/
expectType<Client>(
new Client({
node: 'http://localhost:9200',
maxRetries: 5
})
)
expectError<errors.ConfigurationError>(
new Client({
node: 'http://localhost:9200',
maxRetries: 'five'
})
)
/**
* `requestTimeout` option
*/
expectType<Client>(
new Client({
node: 'http://localhost:9200',
requestTimeout: 5
})
)
expectError<errors.ConfigurationError>(
new Client({
node: 'http://localhost:9200',
requestTimeout: 'five'
})
)
/**
* `pingTimeout` option
*/
expectType<Client>(
new Client({
node: 'http://localhost:9200',
pingTimeout: 5
})
)
expectError<errors.ConfigurationError>(
new Client({
node: 'http://localhost:9200',
pingTimeout: 'five'
})
)
/**
* `sniffInterval` option
*/
expectType<Client>(
new Client({
node: 'http://localhost:9200',
sniffInterval: 5
})
)
expectType<Client>(
new Client({
node: 'http://localhost:9200',
sniffInterval: false
})
)
expectError<errors.ConfigurationError>(
new Client({
node: 'http://localhost:9200',
sniffInterval: 'five'
})
)
/**
* `sniffOnStart` option
*/
expectType<Client>(
new Client({
node: 'http://localhost:9200',
sniffOnStart: true
})
)
expectError<errors.ConfigurationError>(
new Client({
node: 'http://localhost:9200',
sniffOnStart: 'no'
})
)
/**
* `sniffEndpoint` option
*/
expectType<Client>(
new Client({
node: 'http://localhost:9200',
sniffEndpoint: '/custom'
})
)
expectError<errors.ConfigurationError>(
new Client({
node: 'http://localhost:9200',
sniffEndpoint: false
})
)
/**
* `sniffOnConnectionFault` option
*/
expectType<Client>(
new Client({
node: 'http://localhost:9200',
sniffOnConnectionFault: true
})
)
expectError<errors.ConfigurationError>(
new Client({
node: 'http://localhost:9200',
sniffOnConnectionFault: 'yes'
})
)
/**
* `resurrectStrategy` option
*/
expectType<Client>(
new Client({
node: 'http://localhost:9200',
resurrectStrategy: 'ping'
})
)
expectType<Client>(
new Client({
node: 'http://localhost:9200',
resurrectStrategy: 'optimistic'
})
)
expectType<Client>(
new Client({
node: 'http://localhost:9200',
resurrectStrategy: 'none'
})
)
expectError<errors.ConfigurationError>(
new Client({
node: 'http://localhost:9200',
resurrectStrategy: 'custom'
})
)
/**
* `suggestCompression` option
*/
expectType<Client>(
new Client({
node: 'http://localhost:9200',
suggestCompression: true
})
)
expectError<errors.ConfigurationError>(
new Client({
node: 'http://localhost:9200',
suggestCompression: 'no'
})
)
/**
* `compression` option
*/
expectType<Client>(
new Client({
node: 'http://localhost:9200',
compression: 'gzip'
})
)
expectError<errors.ConfigurationError>(
new Client({
node: 'http://localhost:9200',
compression: 'deflate'
})
)
/**
* `headers` option
*/
expectType<Client>(
new Client({
node: 'http://localhost:9200',
headers: { foo: 'bar' }
})
)
expectError<errors.ConfigurationError>(
new Client({
node: 'http://localhost:9200',
headers: 'foo=bar'
})
)
/**
* `opaqueIdPrefix` option
*/
expectType<Client>(
new Client({
node: 'http://localhost:9200',
opaqueIdPrefix: 'foo-'
})
)
expectError<errors.ConfigurationError>(
new Client({
node: 'http://localhost:9200',
opaqueIdPrefix: 42
})
)
/**
* `name` option
*/
expectType<Client>(
new Client({
node: 'http://localhost:9200',
name: 'foo'
})
)
expectError<errors.ConfigurationError>(
new Client({
node: 'http://localhost:9200',
name: 42
})
)
/**
* `auth` option
*/
expectType<Client>(
new Client({
node: 'http://localhost:9200',
auth: {
username: 'username',
password: 'password'
}
})
)
expectType<Client>(
new Client({
node: 'http://localhost:9200',
auth: {
apiKey: 'abcd'
}
})
)
expectType<Client>(
new Client({
node: 'http://localhost:9200',
auth: {
apiKey: {
api_key: 'foo',
id: 'bar'
}
}
})
)
expectError<errors.ConfigurationError>(
new Client({
node: 'http://localhost:9200',
auth: 'password'
})
)
/**
* `cloud` option
*/
expectType<Client>(
new Client({
cloud: {
id: 'localhost:9200'
}
})
)
expectError<errors.ConfigurationError>(
new Client({
cloud: {
id: 42
}
})
)
/**
* `agent` option
*/
expectType<Client>(
new Client({
node: 'http://localhost:9200',
agent: {
keepAlive: true,
keepAliveMsecs: 42,
maxSockets: 42,
maxFreeSockets: 42
}
})
)
expectError<errors.ConfigurationError>(
new Client({
node: 'http://localhost:9200',
agent: {
keepAlive: 'yes',
keepAliveMsecs: true,
maxSockets: 'all',
maxFreeSockets: null
}
})
)
/**
* `ssl` option
*/
expectType<Client>(
new Client({
node: 'http://localhost:9200',
ssl: {
ca: 'cert',
rejectUnauthorized: true
}
})
)
expectError<errors.ConfigurationError>(
new Client({
node: 'http://localhost:9200',
ssl: {
ca: 42,
rejectUnauthorized: 'yes'
}
})
)
/**
* `generateRequestId` option
*/
expectType<Client>(
new Client({
node: 'http://localhost:9200',
generateRequestId (params, options) {
return 'id'
}
})
)
expectError<errors.ConfigurationError>(
new Client({
node: 'http://localhost:9200',
generateRequestId: 'id'
})
)
/**
* `nodeSelector` option
*/
expectType<Client>(
new Client({
node: 'http://localhost:9200',
nodeSelector (connections) {
return connections[0]
}
})
)
expectType<Client>(
new Client({
node: 'http://localhost:9200',
nodeSelector: 'round-robin'
})
)
expectError<errors.ConfigurationError>(
new Client({
node: 'http://localhost:9200',
nodeSelector (connections) {
return 'id'
}
})
)
/**
* `nodeFilter` option
*/
expectType<Client>(
new Client({
node: 'http://localhost:9200',
nodeFilter (connection) {
return true
}
})
)
expectError<errors.ConfigurationError>(
new Client({
node: 'http://localhost:9200',
nodeFilter (connection) {
return 'id'
}
})
)
/**
* `Serializer` option
*/
{
class CustomSerializer extends Serializer {
deserialize (str: string) {
return super.deserialize(str)
}
}
expectType<Client>(
new Client({
node: 'http://localhost:9200',
Serializer: CustomSerializer
})
)
}
{
class CustomSerializer {
deserialize (str: string) {
return JSON.parse(str)
}
}
expectError<errors.ConfigurationError>(
new Client({
node: 'http://localhost:9200',
Serializer: CustomSerializer
})
)
}
/**
* `Connection` option
*/
{
class CustomConnection extends Connection {
close () {
return super.close()
}
}
expectType<Client>(
new Client({
node: 'http://localhost:9200',
Connection: CustomConnection
})
)
}
{
class CustomConnection {
close () {
return Promise.resolve()
}
}
expectError<errors.ConfigurationError>(
new Client({
node: 'http://localhost:9200',
Connection: CustomConnection
})
)
}
/**
* `ConnectionPool` option
*/
{
class CustomConnectionPool extends ConnectionPool {
empty () {
return super.empty()
}
}
expectType<Client>(
new Client({
node: 'http://localhost:9200',
ConnectionPool: CustomConnectionPool
})
)
}
{
class CustomConnectionPool {
empty () {
return this
}
}
expectError<errors.ConfigurationError>(
new Client({
node: 'http://localhost:9200',
ConnectionPool: CustomConnectionPool
})
)
}
/**
* `Transport` option
*/
{
class CustomTransport extends Transport {
getConnection (opts: TransportGetConnectionOptions) {
return super.getConnection(opts)
}
}
expectType<Client>(
new Client({
node: 'http://localhost:9200',
Transport: CustomTransport
})
)
}
{
class CustomTransport {
getConnection (opts: TransportGetConnectionOptions) {
return null
}
}
expectError<errors.ConfigurationError>(
new Client({
node: 'http://localhost:9200',
Transport: CustomTransport
})
)
}

123
test/types/client.test-d.ts Normal file
View File

@ -0,0 +1,123 @@
// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information
import { expectType } from 'tsd'
import { Client, ApiError, ApiResponse, RequestEvent, ResurrectEvent } from '../../'
import { TransportRequestCallback, TransportRequestPromise } from '../..//lib/Transport';
const client = new Client({
node: 'http://localhost:9200'
})
client.on('request', (err, meta) => {
expectType<ApiError>(err)
expectType<RequestEvent>(meta)
})
client.on('response', (err, meta) => {
expectType<ApiError>(err)
expectType<RequestEvent>(meta)
})
client.on('sniff', (err, meta) => {
expectType<ApiError>(err)
expectType<RequestEvent>(meta)
})
client.on('resurrect', (err, meta) => {
expectType<null>(err)
expectType<ResurrectEvent>(meta)
})
// Test all overloads
// Callbacks style
{
const result = client.info((err, result) => {
expectType<ApiError>(err)
expectType<ApiResponse>(result)
})
expectType<TransportRequestCallback>(result)
expectType<void>(result.abort())
}
{
const result = client.info({ pretty: true }, (err, result) => {
expectType<ApiError>(err)
expectType<ApiResponse>(result)
})
expectType<TransportRequestCallback>(result)
expectType<void>(result.abort())
}
{
const result = client.info({ pretty: true }, { ignore: [404] }, (err, result) => {
expectType<ApiError>(err)
expectType<ApiResponse>(result)
})
expectType<TransportRequestCallback>(result)
expectType<void>(result.abort())
}
// Promise style
{
const promise = client.info()
expectType<TransportRequestPromise<ApiResponse>>(promise)
promise
.then(result => expectType<ApiResponse>(result))
.catch((err: ApiError) => expectType<ApiError>(err))
expectType<void>(promise.abort())
}
{
const promise = client.info({ pretty: true })
expectType<TransportRequestPromise<ApiResponse>>(promise)
promise
.then(result => expectType<ApiResponse>(result))
.catch((err: ApiError) => expectType<ApiError>(err))
expectType<void>(promise.abort())
}
{
const promise = client.info({ pretty: true }, { ignore: [404] })
expectType<TransportRequestPromise<ApiResponse>>(promise)
promise
.then(result => expectType<ApiResponse>(result))
.catch((err: ApiError) => expectType<ApiError>(err))
expectType<void>(promise.abort())
}
// Promise style with async await
{
const promise = client.info()
expectType<TransportRequestPromise<ApiResponse>>(promise)
expectType<void>(promise.abort())
try {
expectType<ApiResponse>(await promise)
} catch (err) {
expectType<any>(err)
}
}
{
const promise = client.info({ pretty: true })
expectType<TransportRequestPromise<ApiResponse>>(promise)
expectType<void>(promise.abort())
try {
expectType<ApiResponse>(await promise)
} catch (err) {
expectType<any>(err)
}
}
{
const promise = client.info({ pretty: true }, { ignore: [404] })
expectType<TransportRequestPromise<ApiResponse>>(promise)
expectType<void>(promise.abort())
try {
expectType<ApiResponse>(await promise)
} catch (err) {
expectType<any>(err)
}
}

View File

@ -0,0 +1,95 @@
// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information
import { expectType, expectAssignable } from 'tsd'
import { URL } from 'url'
import {
BaseConnectionPool,
ConnectionPool,
CloudConnectionPool,
Connection
} from '../../'
{
const pool = new BaseConnectionPool({
Connection: Connection,
ssl: { ca: 'stirng' },
emit: (event, ...args) => true,
agent: { keepAlive: true },
auth: { username: 'username', password: 'password' }
})
expectType<BaseConnectionPool>(pool)
expectType<Connection[]>(pool.connections)
expectType<number>(pool.size)
expectType<BaseConnectionPool>(pool.markAlive(new Connection()))
expectType<BaseConnectionPool>(pool.markDead(new Connection()))
expectType<Connection | null>(pool.getConnection({
filter (node) { return true },
selector (connections) { return connections[0] },
requestId: 'id',
name: 'name',
now: Date.now()
}))
expectType<Connection>(pool.addConnection({}))
expectType<BaseConnectionPool>(pool.removeConnection(new Connection()))
expectType<BaseConnectionPool>(pool.empty())
expectType<BaseConnectionPool>(pool.update([]))
expectType<any[]>(pool.nodesToHost([], 'https'))
expectType<{ url: URL }>(pool.urlToHost('url'))
}
{
const pool = new ConnectionPool({
Connection: Connection,
ssl: { ca: 'stirng' },
emit: (event, ...args) => true,
agent: { keepAlive: true },
auth: { username: 'username', password: 'password' },
pingTimeout: 1000,
resurrectStrategy: 'ping',
sniffEnabled: true
})
expectAssignable<ConnectionPool>(pool)
expectType<Connection[]>(pool.connections)
expectType<number>(pool.size)
expectType<string[]>(pool.dead)
expectAssignable<ConnectionPool>(pool.markAlive(new Connection()))
expectAssignable<ConnectionPool>(pool.markDead(new Connection()))
expectType<Connection | null>(pool.getConnection({
filter (node) { return true },
selector (connections) { return connections[0] },
requestId: 'id',
name: 'name',
now: Date.now()
}))
expectType<Connection>(pool.addConnection({}))
expectAssignable<ConnectionPool>(pool.removeConnection(new Connection()))
expectAssignable<ConnectionPool>(pool.empty())
expectAssignable<ConnectionPool>(pool.update([]))
expectType<any[]>(pool.nodesToHost([], 'https'))
expectType<{ url: URL }>(pool.urlToHost('url'))
expectType<void>(pool.resurrect({
now: Date.now(),
requestId: 'id',
name: 'name'
}))
}
{
const pool = new CloudConnectionPool({
Connection: Connection,
ssl: { ca: 'stirng' },
emit: (event, ...args) => true,
agent: { keepAlive: true },
auth: { username: 'username', password: 'password' }
})
expectAssignable<CloudConnectionPool>(pool)
expectType<Connection | null>(pool.cloudConnection)
expectType<Connection | null>(pool.getConnection())
}

View File

@ -0,0 +1,26 @@
// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information
import { expectType } from 'tsd'
import { URL } from 'url'
import { Connection } from '../../'
const conn = new Connection({
url: new URL('http://localhost:9200'),
ssl: { ca: 'string' },
id: 'id',
headers: {},
agent: { keepAlive: false },
status: 'alive',
roles: { master: true },
auth: { username: 'username', password: 'password' }
})
expectType<Connection>(conn)
expectType<URL>(conn.url)
expectType<string>(conn.id)
expectType<Record<string, any>>(conn.headers)
expectType<number>(conn.deadCount)
expectType<number>(conn.resurrectTimeout)
expectType<string>(conn.status)

View File

@ -0,0 +1,89 @@
// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information
import { expectType } from 'tsd'
import { errors, ApiResponse, Connection } from '../../'
const response = {
body: {},
statusCode: 200,
headers: {},
warnings: null,
meta: {
context: {},
name: 'name',
request: {
params: { method: 'GET', path: '/' },
options: {},
id: 42
},
connection: new Connection(),
attempts: 0,
aborted: false,
}
}
{
const err = new errors.ElasticsearchClientError()
expectType<string>(err.name)
expectType<string>(err.message)
}
{
const err = new errors.TimeoutError('message', response)
expectType<string>(err.name)
expectType<string>(err.message)
expectType<ApiResponse>(err.meta)
}
{
const err = new errors.ConnectionError('message', response)
expectType<string>(err.name)
expectType<string>(err.message)
expectType<ApiResponse>(err.meta)
}
{
const err = new errors.NoLivingConnectionsError('message', response)
expectType<string>(err.name)
expectType<string>(err.message)
expectType<ApiResponse>(err.meta)
}
{
const err = new errors.SerializationError('message', {})
expectType<string>(err.name)
expectType<string>(err.message)
expectType<any>(err.data)
}
{
const err = new errors.DeserializationError('message', 'data')
expectType<string>(err.name)
expectType<string>(err.message)
expectType<string>(err.data)
}
{
const err = new errors.ConfigurationError('message')
expectType<string>(err.name)
expectType<string>(err.message)
}
{
const err = new errors.ResponseError(response)
expectType<string>(err.name)
expectType<string>(err.message)
expectType<ApiResponse>(err.meta)
expectType<Record<string, any>>(err.body)
expectType<number>(err.statusCode)
expectType<Record<string, any>>(err.headers)
}
{
const err = new errors.RequestAbortedError('message', response)
expectType<string>(err.name)
expectType<string>(err.message)
expectType<ApiResponse>(err.meta)
}

View File

@ -0,0 +1,432 @@
// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information
import { expectType, expectError, expectAssignable } from 'tsd'
import { Client } from '../../'
import {
BulkHelper,
BulkStats,
BulkHelperOptions,
ScrollSearchResponse,
OnDropDocument
} from '../../lib/Helpers'
const client = new Client({
node: 'http://localhost:9200'
})
/// .helpers.bulk
const b = client.helpers.bulk<Record<string, any>>({
datasource: [],
onDocument (doc) {
expectType<Record<string, any>>(doc)
return { index: { _index: 'test' } }
},
flushBytes: 5000000,
concurrency: 5,
retries: 3,
wait: 5000,
onDrop (doc) {
expectType<OnDropDocument<Record<string, any>>>(doc)
},
refreshOnCompletion: true,
pipeline: 'my-pipeline'
})
expectType<BulkHelper<BulkStats>>(b)
expectType<BulkHelper<BulkStats>>(b.abort())
b.then(stats => expectType<BulkStats>(stats))
// body can't be provided
expectError(
client.helpers.bulk({
datasource: [],
onDocument (doc) {
return { index: { _index: 'test' } }
},
body: []
})
)
// test onDocument actions
// index
{
const options = {
datasource: [],
onDocument (doc: Record<string, any>) {
return { index: { _index: 'test' } }
}
}
expectAssignable<BulkHelperOptions<Record<string, any>>>(options)
}
// create
{
const options = {
datasource: [],
onDocument (doc: Record<string, any>) {
return { create: { _index: 'test' } }
}
}
expectAssignable<BulkHelperOptions<Record<string, any>>>(options)
}
// update
{
// without `:BulkHelperOptions` this test cannot pass
// but if we write these options inline inside
// a `.helper.bulk`, it works as expected
const options: BulkHelperOptions<Record<string, any>> = {
datasource: [],
onDocument (doc: Record<string, any>) {
return [{ update: { _index: 'test' } }, doc]
}
}
expectAssignable<BulkHelperOptions<Record<string, any>>>(options)
}
// delete
{
const options = {
datasource: [],
onDocument (doc: Record<string, any>) {
return { delete: { _index: 'test' } }
}
}
expectAssignable<BulkHelperOptions<Record<string, any>>>(options)
}
/// .helpers.scrollSearch
// just search params
{
async function test () {
const scrollSearch = client.helpers.scrollSearch({
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
})
for await (const response of scrollSearch) {
expectAssignable<ScrollSearchResponse>(response)
}
}
}
// search params and options
{
async function test () {
const scrollSearch = client.helpers.scrollSearch({
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
}, { ignore: [404] })
for await (const response of scrollSearch) {
expectAssignable<ScrollSearchResponse>(response)
expectType<Record<string, any>>(response.body)
expectType<unknown[]>(response.documents)
expectType<unknown>(response.meta.context)
}
}
}
// with type defs
{
interface ShardsResponse {
total: number;
successful: number;
failed: number;
skipped: number;
}
interface Explanation {
value: number;
description: string;
details: Explanation[];
}
interface SearchResponse<T> {
took: number;
timed_out: boolean;
_scroll_id?: string;
_shards: ShardsResponse;
hits: {
total: number;
max_score: number;
hits: Array<{
_index: string;
_type: string;
_id: string;
_score: number;
_source: T;
_version?: number;
_explanation?: Explanation;
fields?: any;
highlight?: any;
inner_hits?: any;
matched_queries?: string[];
sort?: string[];
}>;
};
aggregations?: any;
}
interface Source {
foo: string
}
async function test () {
const scrollSearch = client.helpers.scrollSearch<Source, SearchResponse<Source>>({
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
})
for await (const response of scrollSearch) {
expectAssignable<ScrollSearchResponse>(response)
expectType<SearchResponse<Source>>(response.body)
expectType<Source[]>(response.documents)
expectType<unknown>(response.meta.context)
}
}
}
{
interface SearchBody {
query: {
match: { foo: string }
}
}
interface ShardsResponse {
total: number;
successful: number;
failed: number;
skipped: number;
}
interface Explanation {
value: number;
description: string;
details: Explanation[];
}
interface SearchResponse<T> {
took: number;
timed_out: boolean;
_scroll_id?: string;
_shards: ShardsResponse;
hits: {
total: number;
max_score: number;
hits: Array<{
_index: string;
_type: string;
_id: string;
_score: number;
_source: T;
_version?: number;
_explanation?: Explanation;
fields?: any;
highlight?: any;
inner_hits?: any;
matched_queries?: string[];
sort?: string[];
}>;
};
aggregations?: any;
}
interface Source {
foo: string
}
async function test () {
const scrollSearch = client.helpers.scrollSearch<Source, SearchResponse<Source>, SearchBody, string>({
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
})
for await (const response of scrollSearch) {
expectAssignable<ScrollSearchResponse>(response)
expectType<SearchResponse<Source>>(response.body)
expectType<Source[]>(response.documents)
expectType<string>(response.meta.context)
}
}
}
/// .helpers.scrollDocuments
// just search params
{
async function test () {
const scrollDocuments = client.helpers.scrollDocuments({
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
})
for await (const document of scrollDocuments) {
expectType<unknown>(document)
}
}
}
// search params and options
{
async function test () {
const scrollDocuments = client.helpers.scrollDocuments({
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
}, { ignore: [404] })
for await (const document of scrollDocuments) {
expectType<unknown>(document)
}
}
}
// with type defs
{
interface Source {
foo: string
}
async function test () {
const scrollDocuments = client.helpers.scrollDocuments<Source>({
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
})
for await (const document of scrollDocuments) {
expectType<Source>(document)
}
}
}
{
interface SearchBody {
query: {
match: { foo: string }
}
}
interface Source {
foo: string
}
async function test () {
const scrollDocuments = client.helpers.scrollDocuments<Source, SearchBody>({
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
})
for await (const document of scrollDocuments) {
expectType<Source>(document)
}
}
}
/// .helpers.search
// just search params
{
const p = client.helpers.search({
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
})
expectType<Promise<unknown[]>>(p)
expectType<unknown[]>(await p)
}
// search params and options
{
const p = client.helpers.search({
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
}, { ignore: [404] })
expectType<Promise<unknown[]>>(p)
expectType<unknown[]>(await p)
}
// with type defs
{
interface Source {
foo: string
}
const p = client.helpers.search<Source>({
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
})
expectType<Promise<Source[]>>(p)
expectType<Source[]>(await p)
}
{
interface SearchBody {
query: {
match: { foo: string }
}
}
interface Source {
foo: string
}
const p = client.helpers.search<Source, SearchBody>({
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
})
expectType<Promise<Source[]>>(p)
expectType<Source[]>(await p)
}

View File

@ -1,170 +0,0 @@
// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information
'use strict'
import {
Client,
ApiResponse,
RequestParams,
RequestEvent,
ResurrectEvent,
events,
errors,
ClientExtendsCallbackOptions,
NodeOptions
} from '../../index'
import { TransportRequestParams, TransportRequestOptions } from '../../lib/Transport'
import { URL } from 'url'
const client = new Client({ node: 'http://localhost:9200' })
const nodeOpts: NodeOptions = {
url: new URL('http://localhost:9200'),
id: 'winteriscoming',
headers: { 'foo': 'bar' },
roles: {
master: false,
data: true,
ingest: false,
ml: false
}
}
const client2 = new Client({ node: nodeOpts })
const clientBasicAuth = new Client({
node: 'http://localhost:9200',
auth: { username: 'foo', password: 'bar' }
})
const clientApiKeyString = new Client({
node: 'http://localhost:9200',
auth: { apiKey: 'foobar' }
})
const clientApiKeyObject = new Client({
node: 'http://localhost:9200',
auth: {
apiKey: {
id: 'foo',
api_key: 'bar'
}
}
})
client.on(events.RESPONSE, (err: errors.ElasticsearchClientError | null, request: RequestEvent) => {
if (err) console.log(err)
const { body, statusCode } = request
const { params } = request.meta.request
console.log(params, body, statusCode)
})
client.on(events.RESURRECT, (err: errors.ElasticsearchClientError | null, meta: ResurrectEvent) => {})
// Callbacks
client.info((err: errors.ElasticsearchClientError | null, result: ApiResponse) => {})
client.index({
index: 'test',
type: 'test',
id: 'test',
body: { hello: 'world' }
}, (err: errors.ElasticsearchClientError | null, result: ApiResponse) => {})
// request options
client.index({
index: 'test',
type: 'test',
id: 'test',
body: { hello: 'world' }
}, {
maxRetries: 2,
ignore: [404],
requestTimeout: 2000,
headers: { foo: 'bar' },
querystring: { baz: 'faz' },
compression: 'gzip',
asStream: false
}, (err: errors.ElasticsearchClientError | null, result: ApiResponse) => {})
// Promises
client.info()
.then((result: ApiResponse) => {})
.catch((err: errors.ElasticsearchClientError) => {})
client.index({
index: 'test',
type: 'test',
id: 'test',
body: { hello: 'world' }
})
.then((result: ApiResponse) => {})
.catch((err: errors.ElasticsearchClientError) => {})
// request options
client.index({
index: 'test',
type: 'test',
id: 'test',
body: { hello: 'world' }
}, {
maxRetries: 2,
ignore: [404],
requestTimeout: 2000
})
.then((result: ApiResponse) => {})
.catch((err: errors.ElasticsearchClientError) => {})
// --- Use generics ---
// Define the search parameters
interface SearchBody {
query: {
match: { foo: string }
}
}
const searchParams: RequestParams.Search<SearchBody> = {
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
}
// Define the interface of the search response
interface SearchResponse<T> {
hits: {
hits: Array<{
_source: T;
}>
}
}
// Define the interface of the source object
interface Source {
foo: string
}
client.search(searchParams)
.then((response: ApiResponse<SearchResponse<Source>>) => console.log(response))
.catch((err: errors.ElasticsearchClientError) => {})
// extend client
client.extend('namespace.method', (options: ClientExtendsCallbackOptions) => {
return function (params: any) {
const requestParams: TransportRequestParams = {
method: 'GET',
path: '/',
querystring: {}
}
const requestOptions: TransportRequestOptions = {
ignore: [404],
maxRetries: 5
}
return options.makeRequest(requestParams, requestOptions)
}
})

View File

@ -0,0 +1,13 @@
// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information
import { expectType } from 'tsd'
import { Serializer } from '../../'
const serializer = new Serializer()
expectType<string>(serializer.serialize({}))
expectType<any>(serializer.deserialize(''))
expectType<string>(serializer.ndserialize([]))
expectType<string>(serializer.qserialize({}))

View File

@ -0,0 +1,156 @@
// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information
import { Readable as ReadableStream } from 'stream';
import { expectType, expectAssignable, expectError } from 'tsd'
import {
Transport,
Connection,
ConnectionPool,
Serializer
} from '../..'
import {
TransportRequestParams,
TransportRequestOptions,
TransportRequestCallback,
RequestEvent,
ApiError,
RequestBody,
RequestNDBody,
ApiResponse
} from '../../lib/Transport'
const params = {
method: 'POST',
path: '/search',
body: { foo: 'bar' },
querystring: { baz: 'faz' }
}
const options = {
ignore: [404],
requestTimeout: 5000,
maxRetries: 3,
asStream: false,
headers: {},
querystring: {},
id: 'id',
context: {},
warnings: ['warn'],
opaqueId: 'id'
}
const response = {
body: {},
statusCode: 200,
headers: {},
warnings: null,
meta: {
context: {},
name: 'name',
request: {
params,
options,
id: 'id'
},
connection: new Connection(),
attempts: 0,
aborted: false
}
}
expectAssignable<TransportRequestParams>(params)
expectAssignable<TransportRequestParams>({ method: 'GET', path: '/' })
expectAssignable<TransportRequestOptions>(options)
expectAssignable<RequestEvent>(response)
expectAssignable<ApiResponse>(response)
// verify that RequestBody, RequestNDBody and ResponseBody works as expected
interface TestBody { hello: string }
expectAssignable<RequestBody>({ foo: 'bar' })
expectAssignable<RequestBody<TestBody>>({ hello: 'world' })
expectError<RequestBody<TestBody>>({ foo: 'bar' })
expectAssignable<RequestBody>('string')
expectAssignable<RequestBody<TestBody>>('string')
expectAssignable<RequestBody>(Buffer.from('hello world'))
expectAssignable<RequestBody>(new ReadableStream())
expectAssignable<RequestNDBody>([{ foo: 'bar' }])
expectAssignable<RequestNDBody<TestBody>[]>([{ hello: 'world' }])
expectError<RequestNDBody>({ foo: 'bar' })
expectError<RequestNDBody<TestBody>[]>([{ foo: 'bar' }])
expectAssignable<RequestNDBody>(['string'])
expectAssignable<RequestNDBody>(Buffer.from('hello world'))
expectAssignable<RequestNDBody>(new ReadableStream())
const transport = new Transport({
emit: (event, ...args) => true,
serializer: new Serializer(),
connectionPool: new ConnectionPool(),
maxRetries: 5,
requestTimeout: 1000,
suggestCompression: true,
compression: 'gzip',
sniffInterval: 1000,
sniffOnConnectionFault: true,
sniffEndpoint: '/sniff',
sniffOnStart: false
})
expectType<Transport>(transport)
expectType<TransportRequestCallback>(transport.request(params, options, (err, result) => {}))
// body as object
transport.request(params, options, (err, result) => {
expectType<ApiError>(err)
expectType<ApiResponse>(result)
})
// body as string
transport.request({
method: 'POST',
path: '/search',
body: 'hello world',
querystring: { baz: 'faz' }
}, options, (err, result) => {
expectType<ApiError>(err)
expectType<ApiResponse>(result)
})
// body as Buffer
transport.request({
method: 'POST',
path: '/search',
body: Buffer.from('hello world'),
querystring: { baz: 'faz' }
}, options, (err, result) => {
expectType<ApiError>(err)
expectType<ApiResponse>(result)
})
// body as ReadableStream
transport.request({
method: 'POST',
path: '/search',
body: new ReadableStream(),
querystring: { baz: 'faz' }
}, options, (err, result) => {
expectType<ApiError>(err)
expectType<ApiResponse>(result)
})
const promise = transport.request(params, options)
expectType<Promise<ApiResponse>>(promise)
promise.then(result => expectType<ApiResponse>(result))
expectType<ApiResponse>(await promise)
// body that does not respect the RequestBody constraint
expectError(
transport.request({
method: 'POST',
path: '/',
body: 42
})
)

View File

@ -1,11 +0,0 @@
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"noEmit": true,
"strict": true
},
"files": [
"./index.ts"
]
}