Switched request and response generics position (#1132)

* Updated code generation

* Switched request and response generics position

* Updated test

* API generation

* Removed unused generics

* Test type definitions for callback style API as well

* Fix comments

* Fix conflict

* API generation

* Updated type def
This commit is contained in:
Tomas Della Vedova
2020-04-06 12:45:27 +02:00
committed by GitHub
parent e67b55d163
commit 6779f3b11a
10 changed files with 2636 additions and 2339 deletions

4507
index.d.ts vendored

File diff suppressed because it is too large Load Diff

10
lib/Helpers.d.ts vendored
View File

@ -3,17 +3,17 @@
// See the LICENSE file in the project root for more information
import { Readable as ReadableStream } from 'stream'
import { TransportRequestOptions, ApiResponse, RequestBody, ResponseBody } from './Transport'
import { TransportRequestOptions, ApiResponse, RequestBody } from './Transport'
import { Search, Bulk } from '../api/requestParams'
export default class Helpers {
search<TRequestBody extends RequestBody, TDocument = unknown>(params: Search<TRequestBody>, options?: TransportRequestOptions): Promise<TDocument[]>
scrollSearch<TRequestBody extends RequestBody, TDocument = unknown, TResponse = ResponseBody, TContext = unknown>(params: Search<TRequestBody>, options?: TransportRequestOptions): AsyncIterable<ScrollSearchResponse<TDocument, TResponse, TContext>>
scrollDocuments<TRequestBody extends RequestBody, TDocument = unknown>(params: Search<TRequestBody>, options?: TransportRequestOptions): AsyncIterable<TDocument>
search<TDocument = unknown, TRequestBody extends RequestBody = Record<string, any>>(params: Search<TRequestBody>, options?: TransportRequestOptions): Promise<TDocument[]>
scrollSearch<TDocument = unknown, TResponse = Record<string, any>, TRequestBody extends RequestBody = Record<string, any>, TContext = unknown>(params: Search<TRequestBody>, options?: TransportRequestOptions): AsyncIterable<ScrollSearchResponse<TDocument, TResponse, TContext>>
scrollDocuments<TDocument = unknown, TRequestBody extends RequestBody = Record<string, any>>(params: Search<TRequestBody>, options?: TransportRequestOptions): AsyncIterable<TDocument>
bulk<TDocument = unknown>(options: BulkHelperOptions<TDocument>): BulkHelper<BulkStats>
}
export interface ScrollSearchResponse<TDocument = unknown, TResponse = ResponseBody, TContext = unknown> extends ApiResponse<TResponse, TContext> {
export interface ScrollSearchResponse<TDocument = unknown, TResponse = Record<string, any>, TContext = unknown> extends ApiResponse<TResponse, TContext> {
clear: () => Promise<void>
documents: TDocument[]
}

9
lib/Transport.d.ts vendored
View File

@ -45,7 +45,7 @@ interface TransportOptions {
opaqueIdPrefix?: string;
}
export interface RequestEvent<TResponse = ResponseBody, TContext = unknown> {
export interface RequestEvent<TResponse = Record<string, any>, TContext = unknown> {
body: TResponse;
statusCode: number | null;
headers: Record<string, any> | null;
@ -70,11 +70,10 @@ export interface RequestEvent<TResponse = ResponseBody, TContext = unknown> {
// ApiResponse and RequestEvent are the same thing
// we are doing this for have more clear names
export interface ApiResponse<TResponse = ResponseBody, TContext = unknown> extends RequestEvent<TResponse, TContext> {}
export interface ApiResponse<TResponse = Record<string, any>, TContext = unknown> extends RequestEvent<TResponse, TContext> {}
export type RequestBody<T = Record<string, any>> = T | string | Buffer | ReadableStream
export type RequestNDBody<T = Record<string, any>[]> = T | string[] | Buffer | ReadableStream
export type ResponseBody<T = Record<string, any>> = T | string | boolean | ReadableStream
export type RequestBody<T = Record<string, any>> = T | string | Buffer | ReadableStream
export type RequestNDBody<T = Record<string, any>[]> = T | string | string[] | Buffer | ReadableStream
export interface TransportRequestParams {
method: string;

24
lib/errors.d.ts vendored
View File

@ -2,31 +2,31 @@
// 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 { ApiResponse, ResponseBody } from './Transport'
import { ApiResponse } from './Transport'
export declare class ElasticsearchClientError extends Error {
name: string;
message: string;
}
export declare class TimeoutError extends ElasticsearchClientError {
export declare class TimeoutError<TResponse = Record<string, any>, TContext = unknown> extends ElasticsearchClientError {
name: string;
message: string;
meta: ApiResponse;
meta: ApiResponse<TResponse, TContext>;
constructor(message: string, meta: ApiResponse);
}
export declare class ConnectionError extends ElasticsearchClientError {
export declare class ConnectionError<TResponse = Record<string, any>, TContext = unknown> extends ElasticsearchClientError {
name: string;
message: string;
meta: ApiResponse;
meta: ApiResponse<TResponse, TContext>;
constructor(message: string, meta: ApiResponse);
}
export declare class NoLivingConnectionsError extends ElasticsearchClientError {
export declare class NoLivingConnectionsError<TResponse = Record<string, any>, TContext = unknown> extends ElasticsearchClientError {
name: string;
message: string;
meta: ApiResponse;
meta: ApiResponse<TResponse, TContext>;
constructor(message: string, meta: ApiResponse);
}
@ -50,19 +50,19 @@ export declare class ConfigurationError extends ElasticsearchClientError {
constructor(message: string);
}
export declare class ResponseError extends ElasticsearchClientError {
export declare class ResponseError<TResponse = Record<string, any>, TContext = unknown> extends ElasticsearchClientError {
name: string;
message: string;
meta: ApiResponse;
body: ResponseBody;
meta: ApiResponse<TResponse, TContext>;
body: TResponse;
statusCode: number;
headers: Record<string, any>;
constructor(meta: ApiResponse);
}
export declare class RequestAbortedError extends ElasticsearchClientError {
export declare class RequestAbortedError<TResponse = Record<string, any>, TContext = unknown> extends ElasticsearchClientError {
name: string;
message: string;
meta: ApiResponse;
meta: ApiResponse<TResponse, TContext>;
constructor(message: string, meta: ApiResponse);
}

View File

@ -180,36 +180,37 @@ function toPascalCase (str) {
function buildMethodDefinition (api, name, hasBody) {
const Name = toPascalCase(name)
const bodyType = ndjsonApiKey.includes(Name) ? 'RequestNDBody' : 'RequestBody'
const defaultBodyType = ndjsonApiKey.includes(Name) ? 'Record<string, any>[]' : 'Record<string, any>'
if (hasBody) {
let methods = [
{ key: `${api}<TRequestBody extends ${bodyType}, TResponse = ResponseBody, TContext = unknown>(params?: RequestParams.${Name}<TRequestBody>, options?: TransportRequestOptions)`, val: `TransportRequestPromise<ApiResponse<TResponse, TContext>>` },
{ key: `${api}<TRequestBody extends ${bodyType}, TResponse = ResponseBody, TContext = unknown>(callback: callbackFn<TResponse, TContext>)`, val: `TransportRequestCallback` },
{ key: `${api}<TRequestBody extends ${bodyType}, TResponse = ResponseBody, TContext = unknown>(params: RequestParams.${Name}<TRequestBody>, callback: callbackFn<TResponse, TContext>)`, val: `TransportRequestCallback` },
{ key: `${api}<TRequestBody extends ${bodyType}, TResponse = ResponseBody, TContext = unknown>(params: RequestParams.${Name}<TRequestBody>, options: TransportRequestOptions, callback: callbackFn<TResponse, TContext>)`, val: `TransportRequestCallback` }
{ key: `${api}<TResponse = Record<string, any>, TRequestBody extends ${bodyType} = ${defaultBodyType}, TContext = unknown>(params?: RequestParams.${Name}<TRequestBody>, options?: TransportRequestOptions)`, val: `TransportRequestPromise<ApiResponse<TResponse, TContext>>` },
{ key: `${api}<TResponse = Record<string, any>, TRequestBody extends ${bodyType} = ${defaultBodyType}, TContext = unknown>(callback: callbackFn<TResponse, TContext>)`, val: `TransportRequestCallback` },
{ key: `${api}<TResponse = Record<string, any>, TRequestBody extends ${bodyType} = ${defaultBodyType}, TContext = unknown>(params: RequestParams.${Name}<TRequestBody>, callback: callbackFn<TResponse, TContext>)`, val: `TransportRequestCallback` },
{ key: `${api}<TResponse = Record<string, any>, TRequestBody extends ${bodyType} = ${defaultBodyType}, TContext = unknown>(params: RequestParams.${Name}<TRequestBody>, options: TransportRequestOptions, callback: callbackFn<TResponse, TContext>)`, val: `TransportRequestCallback` }
]
if (isSnakeCased(api)) {
methods = methods.concat([
{ key: `${camelify(api)}<TRequestBody extends ${bodyType}, TResponse = ResponseBody, TContext = unknown>(params?: RequestParams.${Name}<TRequestBody>, options?: TransportRequestOptions)`, val: `TransportRequestPromise<ApiResponse<TResponse, TContext>>` },
{ key: `${camelify(api)}<TRequestBody extends ${bodyType}, TResponse = ResponseBody, TContext = unknown>(callback: callbackFn<TResponse, TContext>)`, val: `TransportRequestCallback` },
{ key: `${camelify(api)}<TRequestBody extends ${bodyType}, TResponse = ResponseBody, TContext = unknown>(params: RequestParams.${Name}<TRequestBody>, callback: callbackFn<TResponse, TContext>)`, val: `TransportRequestCallback` },
{ key: `${camelify(api)}<TRequestBody extends ${bodyType}, TResponse = ResponseBody, TContext = unknown>(params: RequestParams.${Name}<TRequestBody>, options: TransportRequestOptions, callback: callbackFn<TResponse, TContext>)`, val: `TransportRequestCallback` }
{ key: `${camelify(api)}<TResponse = Record<string, any>, TRequestBody extends ${bodyType} = ${defaultBodyType}, TContext = unknown>(params?: RequestParams.${Name}<TRequestBody>, options?: TransportRequestOptions)`, val: `TransportRequestPromise<ApiResponse<TResponse, TContext>>` },
{ key: `${camelify(api)}<TResponse = Record<string, any>, TRequestBody extends ${bodyType} = ${defaultBodyType}, TContext = unknown>(callback: callbackFn<TResponse, TContext>)`, val: `TransportRequestCallback` },
{ key: `${camelify(api)}<TResponse = Record<string, any>, TRequestBody extends ${bodyType} = ${defaultBodyType}, TContext = unknown>(params: RequestParams.${Name}<TRequestBody>, callback: callbackFn<TResponse, TContext>)`, val: `TransportRequestCallback` },
{ key: `${camelify(api)}<TResponse = Record<string, any>, TRequestBody extends ${bodyType} = ${defaultBodyType}, TContext = unknown>(params: RequestParams.${Name}<TRequestBody>, options: TransportRequestOptions, callback: callbackFn<TResponse, TContext>)`, val: `TransportRequestCallback` }
])
}
return methods
} else {
let methods = [
{ key: `${api}<TResponse = ResponseBody, TContext = unknown>(params?: RequestParams.${Name}, options?: TransportRequestOptions)`, val: `TransportRequestPromise<ApiResponse<TResponse, TContext>>` },
{ key: `${api}<TResponse = ResponseBody, TContext = unknown>(callback: callbackFn<TResponse, TContext>)`, val: `TransportRequestCallback` },
{ key: `${api}<TResponse = ResponseBody, TContext = unknown>(params: RequestParams.${Name}, callback: callbackFn<TResponse, TContext>)`, val: `TransportRequestCallback` },
{ key: `${api}<TResponse = ResponseBody, TContext = unknown>(params: RequestParams.${Name}, options: TransportRequestOptions, callback: callbackFn<TResponse, TContext>)`, val: `TransportRequestCallback` }
{ key: `${api}<TResponse = Record<string, any>, TContext = unknown>(params?: RequestParams.${Name}, options?: TransportRequestOptions)`, val: `TransportRequestPromise<ApiResponse<TResponse, TContext>>` },
{ key: `${api}<TResponse = Record<string, any>, TContext = unknown>(callback: callbackFn<TResponse, TContext>)`, val: `TransportRequestCallback` },
{ key: `${api}<TResponse = Record<string, any>, TContext = unknown>(params: RequestParams.${Name}, callback: callbackFn<TResponse, TContext>)`, val: `TransportRequestCallback` },
{ key: `${api}<TResponse = Record<string, any>, TContext = unknown>(params: RequestParams.${Name}, options: TransportRequestOptions, callback: callbackFn<TResponse, TContext>)`, val: `TransportRequestCallback` }
]
if (isSnakeCased(api)) {
methods = methods.concat([
{ key: `${camelify(api)}<TResponse = ResponseBody, TContext = unknown>(params?: RequestParams.${Name}, options?: TransportRequestOptions)`, val: `TransportRequestPromise<ApiResponse<TResponse, TContext>>` },
{ key: `${camelify(api)}<TResponse = ResponseBody, TContext = unknown>(callback: callbackFn<TResponse, TContext>)`, val: `TransportRequestCallback` },
{ key: `${camelify(api)}<TResponse = ResponseBody, TContext = unknown>(params: RequestParams.${Name}, callback: callbackFn<TResponse, TContext>)`, val: `TransportRequestCallback` },
{ key: `${camelify(api)}<TResponse = ResponseBody, TContext = unknown>(params: RequestParams.${Name}, options: TransportRequestOptions, callback: callbackFn<TResponse, TContext>)`, val: `TransportRequestCallback` }
{ key: `${camelify(api)}<TResponse = Record<string, any>, TContext = unknown>(params?: RequestParams.${Name}, options?: TransportRequestOptions)`, val: `TransportRequestPromise<ApiResponse<TResponse, TContext>>` },
{ key: `${camelify(api)}<TResponse = Record<string, any>, TContext = unknown>(callback: callbackFn<TResponse, TContext>)`, val: `TransportRequestCallback` },
{ key: `${camelify(api)}<TResponse = Record<string, any>, TContext = unknown>(params: RequestParams.${Name}, callback: callbackFn<TResponse, TContext>)`, val: `TransportRequestCallback` },
{ key: `${camelify(api)}<TResponse = Record<string, any>, TContext = unknown>(params: RequestParams.${Name}, options: TransportRequestOptions, callback: callbackFn<TResponse, TContext>)`, val: `TransportRequestCallback` }
])
}
return methods

View File

@ -3,8 +3,9 @@
// See the LICENSE file in the project root for more information
import { expectType, expectError } from 'tsd'
import { ResponseBody } from '../../lib/Transport'
import { Client } from '../../'
import { Readable as ReadableStream } from 'stream';
import { TransportRequestCallback } from '../../lib/Transport'
import { Client, ApiError } from '../../'
const client = new Client({
node: 'http://localhost:9200'
@ -59,7 +60,7 @@ interface Source {
foo: string
}
// Use a bad body
// body that does not respect the RequestBody constraint
expectError(
client.search({
index: 'hello',
@ -67,7 +68,7 @@ expectError(
}).then(console.log)
)
// No generics
// No generics (promise style)
{
const response = await client.search({
index: 'test',
@ -78,28 +79,13 @@ expectError(
}
})
expectType<ResponseBody>(response.body)
expectType<Record<string, any>>(response.body)
expectType<unknown>(response.meta.context)
}
// Define only the request body
// Define only the response body (promise style)
{
const response = await client.search<SearchBody>({
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
})
expectType<ResponseBody>(response.body)
expectType<unknown>(response.meta.context)
}
// Define request body and response body
{
const response = await client.search<SearchBody, SearchResponse<Source>>({
const response = await client.search<SearchResponse<Source>>({
index: 'test',
body: {
query: {
@ -112,9 +98,24 @@ expectError(
expectType<unknown>(response.meta.context)
}
// Define request body, response body and the context
// Define response body and request body (promise style)
{
const response = await client.search<SearchBody, SearchResponse<Source>, string>({
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: {
@ -126,3 +127,143 @@ expectError(
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

@ -3,22 +3,22 @@
// See the LICENSE file in the project root for more information
import { expectType } from 'tsd'
import { ResponseBody } from '../../lib/Transport'
import { Client } from '../../'
import { TransportRequestCallback } from '../../lib/Transport'
import { Client, ApiError } from '../../'
const client = new Client({
node: 'http://localhost:9200'
})
// No generics
// No generics (promise style)
{
const response = await client.cat.count({ index: 'test' })
expectType<ResponseBody>(response.body)
expectType<Record<string, any>>(response.body)
expectType<unknown>(response.meta.context)
}
// Define only the request body
// Define only the response body (promise style)
{
const response = await client.cat.count<string>({ index: 'test' })
@ -26,10 +26,40 @@ const client = new Client({
expectType<unknown>(response.meta.context)
}
// Define request body and the 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

@ -4,7 +4,6 @@
import { expectType } from 'tsd'
import { errors, ApiResponse, Connection } from '../../'
import { ResponseBody } from '../../lib/Transport'
const response = {
body: {},
@ -77,7 +76,7 @@ const response = {
expectType<string>(err.name)
expectType<string>(err.message)
expectType<ApiResponse>(err.meta)
expectType<ResponseBody>(err.body)
expectType<Record<string, any>>(err.body)
expectType<number>(err.statusCode)
expectType<Record<string, any>>(err.headers)
}

View File

@ -4,7 +4,6 @@
import { expectType, expectError, expectAssignable } from 'tsd'
import { Client } from '../../'
import { RequestBody, ResponseBody } from '../../lib/Transport'
import {
BulkHelper,
BulkStats,
@ -130,7 +129,7 @@ expectError(
for await (const response of scrollSearch) {
expectAssignable<ScrollSearchResponse>(response)
expectType<ResponseBody<Record<string, any>>>(response.body)
expectType<Record<string, any>>(response.body)
expectType<unknown[]>(response.documents)
expectType<unknown>(response.meta.context)
}
@ -138,6 +137,69 @@ expectError(
}
// 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: {
@ -189,7 +251,7 @@ expectError(
}
async function test () {
const scrollSearch = client.helpers.scrollSearch<SearchBody, Source, SearchResponse<Source>, string>({
const scrollSearch = client.helpers.scrollSearch<Source, SearchResponse<Source>, SearchBody, string>({
index: 'test',
body: {
query: {
@ -246,6 +308,27 @@ expectError(
}
// 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: {
@ -258,7 +341,7 @@ expectError(
}
async function test () {
const scrollDocuments = client.helpers.scrollDocuments<SearchBody, Source>({
const scrollDocuments = client.helpers.scrollDocuments<Source, SearchBody>({
index: 'test',
body: {
query: {
@ -306,6 +389,24 @@ expectError(
}
// 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: {
@ -317,7 +418,7 @@ expectError(
foo: string
}
const p = client.helpers.search<SearchBody, Source>({
const p = client.helpers.search<Source, SearchBody>({
index: 'test',
body: {
query: {

View File

@ -16,10 +16,9 @@ import {
TransportRequestCallback,
RequestEvent,
ApiError,
ApiResponse,
RequestBody,
RequestNDBody,
ResponseBody
ApiResponse
} from '../../lib/Transport'
const params = {
@ -85,14 +84,6 @@ expectAssignable<RequestNDBody>(['string'])
expectAssignable<RequestNDBody>(Buffer.from('hello world'))
expectAssignable<RequestNDBody>(new ReadableStream())
expectAssignable<ResponseBody>({ foo: 'bar' })
expectAssignable<ResponseBody<TestBody>>({ hello: 'world' })
expectError<ResponseBody<TestBody>>({ foo: 'bar' })
expectAssignable<ResponseBody>('string')
expectAssignable<ResponseBody<TestBody>>('string')
expectAssignable<ResponseBody>(true)
expectAssignable<ResponseBody>(new ReadableStream())
const transport = new Transport({
emit: (event, ...args) => true,
serializer: new Serializer(),
@ -110,16 +101,52 @@ const transport = new Transport({
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',