Skip to content

Refactored type definitions #1119

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

Merged
merged 42 commits into from
Mar 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
266ece7
Updated types generation script
delvedor Mar 16, 2020
6f32178
Refactored api method definitions
delvedor Mar 16, 2020
da815b2
Updated test
delvedor Mar 16, 2020
5f72949
Removed unused dependencies
delvedor Mar 16, 2020
bcbd8d7
Fixed definition
delvedor Mar 16, 2020
bbf23d5
Updated test
delvedor Mar 16, 2020
87e5d63
Updated docs
delvedor Mar 16, 2020
313b3bd
Improved events type definitions
delvedor Mar 16, 2020
575cdba
Updated test
delvedor Mar 16, 2020
6c67cd8
Minor fixes in the type definitons
delvedor Mar 17, 2020
44930c9
More type test
delvedor Mar 17, 2020
0225067
Merge branch 'master' into improve-typescript-test
delvedor Mar 17, 2020
3b25cad
Improved Transport type definitions
delvedor Mar 17, 2020
a26cff1
Updated test
delvedor Mar 17, 2020
eda409d
Addressed comments
delvedor Mar 18, 2020
a236b21
Code generation
delvedor Mar 18, 2020
4f30b94
Use RequestBody, Response and Context everywhere, also default Contex…
delvedor Mar 18, 2020
39427ed
Updated test
delvedor Mar 18, 2020
154f9a2
body -> hasBody
delvedor Mar 19, 2020
f9a3828
Merge branch 'master' into improve-typescript-test
delvedor Mar 19, 2020
dfd91e3
Merge branch 'master' into improve-typescript-test
delvedor Mar 19, 2020
8aefac5
Fixed conflicts
delvedor Mar 19, 2020
6325189
Updated code generation
delvedor Mar 20, 2020
a180027
Improved request body type definition
delvedor Mar 20, 2020
a4d4e1f
Merge branch 'master' into improve-typescript-test
delvedor Mar 20, 2020
fa1ba75
Updated code generation
delvedor Mar 20, 2020
bae02ac
Use BodyType for both request and reponses generics
delvedor Mar 20, 2020
00c0a6a
API generation
delvedor Mar 20, 2020
c35ed2c
Updated test
delvedor Mar 20, 2020
180e004
Updated docs
delvedor Mar 20, 2020
7ed5f54
Use BodyType also in ReponseError
delvedor Mar 20, 2020
009fc9e
Merge branch 'master' into improve-typescript-test
delvedor Mar 20, 2020
7163fc7
Removed useless client generics
delvedor Mar 20, 2020
190dc4c
Renamed generics and types
delvedor Mar 20, 2020
bb9f1f8
Updated test
delvedor Mar 20, 2020
95ebb1f
Updated docs
delvedor Mar 20, 2020
10991d8
Test ResponseBody as well
delvedor Mar 20, 2020
41dd8f9
Simplify overloads
delvedor Mar 23, 2020
91204d5
API generation
delvedor Mar 23, 2020
832c7a4
Updated test
delvedor Mar 23, 2020
a959778
Merge branch 'master' into improve-typescript-test
delvedor Mar 23, 2020
e2f82a8
Updated error types
delvedor Mar 23, 2020
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
226 changes: 114 additions & 112 deletions api/requestParams.d.ts

Large diffs are not rendered by default.

47 changes: 39 additions & 8 deletions docs/typescript.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,14 @@ request for instance, you can access them via `RequestParams.Search`.
Every API that supports a body, accepts a
https://www.typescriptlang.org/docs/handbook/generics.html[generics] which
represents the type of the request body, if you don't configure anything, it
will default to `any`.
will default to `RequestBody`. +
`RequestBody`, along with `RequestNDBody` and `ResponseBody` are defined inside the client, and it looks like this:
[source,ts]
----
type RequestBody<T = Record<string, any>> = T | string | Buffer | ReadableStream
type RequestNDBody<T = Record<string, any>[]> = T | string[] | Buffer | ReadableStream
type ResponseBody<T = Record<string, any>> = T | string | boolean | ReadableStream
----

For example:

Expand Down Expand Up @@ -49,7 +56,7 @@ const searchParams: RequestParams.Search = {

You can find the type definiton of a response in `ApiResponse`, which accepts a
generics as well if you want to specify the body type, otherwise it defaults to
`any`.
`BodyType`.

[source,ts]
----
Expand Down Expand Up @@ -137,19 +144,43 @@ interface Source {
foo: string
}

async function run (): Promise<void> {
// Define the search parameters
const searchParams: RequestParams.Search<SearchBody> = {
async function run () {
// All of the examples below are valid code, by default,
// the request body will be `RequestBody` and response will be `ResponseBody`.
const response = await client.search({
index: 'test',
body: {
query: {
match: { foo: 'bar' }
}
}
}
})
// body here is `ResponseBody`
console.log(response.body)

// Craft the final type definition
const response: ApiResponse<SearchResponse<Source>> = await client.search(searchParams)
// The first generic is the request body
const response = await client.search<SearchBody>({
index: 'test',
// Here the body must follow the `SearchBody` interface
body: {
query: {
match: { foo: 'bar' }
}
}
})
// body here is `ResponseBody`
console.log(response.body)

const response = await client.search<SearchBody, SearchResponse<Source>>({
index: 'test',
// Here the body must follow the `SearchBody` interface
body: {
query: {
match: { foo: 'bar' }
}
}
})
// Now you can have full type definition of the response
console.log(response.body)
}

Expand Down
2,850 changes: 2,266 additions & 584 deletions index.d.ts

Large diffs are not rendered by default.

67 changes: 37 additions & 30 deletions lib/Connection.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,43 @@
/// <reference types="node" />

import { URL } from 'url';
import { inspect, InspectOptions } from 'util';
import { inspect, InspectOptions } from 'util'
import { Readable as ReadableStream } from 'stream';
import { ApiKeyAuth, BasicAuth } from './pool'
import * as http from 'http';
import { ConnectionOptions as TlsConnectionOptions } from 'tls';
import * as http from 'http'
import { ConnectionOptions as TlsConnectionOptions } from 'tls'

export declare type agentFn = () => any;

interface ConnectionOptions {
url: URL;
ssl?: TlsConnectionOptions;
id?: string;
headers?: any;
headers?: Record<string, any>;
agent?: AgentOptions | agentFn;
status?: string;
roles?: any;
roles?: ConnectionRoles;
auth?: BasicAuth | ApiKeyAuth;
}

interface ConnectionRoles {
master?: boolean
data?: boolean
ingest?: boolean
ml?: boolean
}

interface RequestOptions extends http.ClientRequestArgs {
asStream?: boolean;
body?: any;
body?: string | Buffer | ReadableStream;
querystring?: string;
}

export interface AgentOptions {
keepAlive: boolean;
keepAliveMsecs: number;
maxSockets: number;
maxFreeSockets: number;
keepAlive?: boolean;
keepAliveMsecs?: number;
maxSockets?: number;
maxFreeSockets?: number;
}

export default class Connection {
Expand All @@ -47,27 +55,26 @@ export default class Connection {
INGEST: string;
ML: string;
};
url: URL;
ssl: TlsConnectionOptions | null;
id: string;
headers: any;
deadCount: number;
resurrectTimeout: number;
statuses: any;
roles: any;
makeRequest: any;
_openRequests: number;
_status: string;
_agent: http.Agent;
constructor(opts?: ConnectionOptions);
request(params: RequestOptions, callback: (err: Error | null, response: http.IncomingMessage | null) => void): http.ClientRequest;
close(): Connection;
setRole(role: string, enabled: boolean): Connection;
status: string;
buildRequestObject(params: any): http.ClientRequestArgs;
url: URL
ssl: TlsConnectionOptions | null
id: string
headers: Record<string, any>
status: string
roles: ConnectionRoles
deadCount: number
resurrectTimeout: number
makeRequest: any
_openRequests: number
_status: string
_agent: http.Agent
constructor(opts?: ConnectionOptions)
request(params: RequestOptions, callback: (err: Error | null, response: http.IncomingMessage | null) => void): http.ClientRequest
close(): Connection
setRole(role: string, enabled: boolean): Connection
buildRequestObject(params: any): http.ClientRequestArgs
// @ts-ignore
[inspect.custom](object: any, options: InspectOptions): string;
toJSON(): any;
[inspect.custom](object: any, options: InspectOptions): string
toJSON(): any
}

export {};
60 changes: 31 additions & 29 deletions lib/Transport.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,16 @@
// 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 { ConnectionPool, CloudConnectionPool } from './pool';
import Connection from './Connection';
import Serializer from './Serializer';
import * as errors from './errors';

export type ApiError = errors.ConfigurationError | errors.ConnectionError |
errors.DeserializationError | errors.SerializationError |
errors.NoLivingConnectionsError | errors.ResponseError |
errors.TimeoutError

export interface nodeSelectorFn {
(connections: Connection[]): Connection;
Expand All @@ -18,36 +25,33 @@ export interface generateRequestIdFn {
(params: TransportRequestParams, options: TransportRequestOptions): any;
}

declare type noopFn = (...args: any[]) => void;
declare type emitFn = (event: string | symbol, ...args: any[]) => boolean;

interface TransportOptions {
emit: emitFn & noopFn;
emit: (event: string | symbol, ...args: any[]) => boolean;
connectionPool: ConnectionPool | CloudConnectionPool;
serializer: Serializer;
maxRetries: number;
requestTimeout: number | string;
suggestCompression: boolean;
suggestCompression?: boolean;
compression?: 'gzip';
sniffInterval: number;
sniffOnConnectionFault: boolean;
sniffInterval?: number;
sniffOnConnectionFault?: boolean;
sniffEndpoint: string;
sniffOnStart: boolean;
sniffOnStart?: boolean;
nodeFilter?: nodeFilterFn;
nodeSelector?: string | nodeSelectorFn;
headers?: anyObject;
headers?: Record<string, any>;
generateRequestId?: generateRequestIdFn;
name: string;
name?: string;
opaqueIdPrefix?: string;
}

export interface RequestEvent<T = any, C = any> {
body: T;
export interface RequestEvent<TResponse = ResponseBody, TContext = unknown> {
body: TResponse;
statusCode: number | null;
headers: anyObject | null;
headers: Record<string, any> | null;
warnings: string[] | null;
meta: {
context: C;
context: TContext;
name: string;
request: {
params: TransportRequestParams;
Expand All @@ -66,31 +70,31 @@ export interface RequestEvent<T = any, C = any> {

// ApiResponse and RequestEvent are the same thing
// we are doing this for have more clear names
export interface ApiResponse<T = any, C = any> extends RequestEvent<T, C> {}
export interface ApiResponse<TResponse = ResponseBody, TContext = unknown> extends RequestEvent<TResponse, TContext> {}

declare type anyObject = {
[key: string]: any;
};
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 interface TransportRequestParams {
method: string;
path: string;
body?: anyObject;
bulkBody?: anyObject;
querystring?: anyObject;
body?: RequestBody;
bulkBody?: RequestNDBody;
querystring?: Record<string, any>;
}

export interface TransportRequestOptions {
ignore?: number[];
requestTimeout?: number | string;
maxRetries?: number;
asStream?: boolean;
headers?: anyObject;
querystring?: anyObject;
compression?: string;
headers?: Record<string, any>;
querystring?: Record<string, any>;
compression?: 'gzip';
id?: any;
context?: any;
warnings?: [string];
warnings?: string[];
opaqueId?: string;
}

Expand All @@ -114,7 +118,7 @@ export default class Transport {
SNIFF_ON_CONNECTION_FAULT: string;
DEFAULT: string;
};
emit: emitFn & noopFn;
emit: (event: string | symbol, ...args: any[]) => boolean;
connectionPool: ConnectionPool | CloudConnectionPool;
serializer: Serializer;
maxRetries: number;
Expand All @@ -130,9 +134,7 @@ export default class Transport {
_isSniffing: boolean;
constructor(opts: TransportOptions);
request(params: TransportRequestParams, options?: TransportRequestOptions): Promise<ApiResponse>;
request(params: TransportRequestParams, options?: TransportRequestOptions, callback?: (err: Error | null, result: ApiResponse) => void): TransportRequestCallback;
request(params: TransportRequestParams, options?: TransportRequestOptions, callback?: (err: ApiError, result: ApiResponse) => void): TransportRequestCallback;
getConnection(opts: TransportGetConnectionOptions): Connection | null;
sniff(opts?: TransportSniffOptions, callback?: (...args: any[]) => void): void;
}

export {};
10 changes: 5 additions & 5 deletions lib/errors.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// 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 } from './Transport'
import { ApiResponse, ResponseBody } from './Transport'

export declare class ElasticsearchClientError extends Error {
name: string;
Expand Down Expand Up @@ -33,8 +33,8 @@ export declare class NoLivingConnectionsError extends ElasticsearchClientError {
export declare class SerializationError extends ElasticsearchClientError {
name: string;
message: string;
data: object;
constructor(message: string, data: object);
data: any;
constructor(message: string, data: any);
}

export declare class DeserializationError extends ElasticsearchClientError {
Expand All @@ -54,8 +54,8 @@ export declare class ResponseError extends ElasticsearchClientError {
name: string;
message: string;
meta: ApiResponse;
body: any;
body: ResponseBody;
statusCode: number;
headers: any;
headers: Record<string, any>;
constructor(meta: ApiResponse);
}
11 changes: 6 additions & 5 deletions lib/pool/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

/// <reference types="node" />

import { URL } from 'url'
import { SecureContextOptions } from 'tls';
import Connection, { AgentOptions } from '../Connection';
import { nodeFilterFn, nodeSelectorFn } from '../Transport';
Expand All @@ -13,14 +14,12 @@ interface BaseConnectionPoolOptions {
agent?: AgentOptions;
auth?: BasicAuth | ApiKeyAuth;
emit: (event: string | symbol, ...args: any[]) => boolean;
pingTimeout?: number;
Connection: typeof Connection;
resurrectStrategy?: string;
}

interface ConnectionPoolOptions extends BaseConnectionPoolOptions {
pingTimeout?: number;
resurrectStrategy?: string;
resurrectStrategy?: 'ping' | 'optimistic' | 'none';
sniffEnabled?: boolean;
}

Expand Down Expand Up @@ -65,6 +64,8 @@ interface ResurrectEvent {

declare class BaseConnectionPool {
connections: Connection[];
size: number;
emit: (event: string | symbol, ...args: any[]) => boolean;
_ssl: SecureContextOptions | null;
_agent: AgentOptions | null;
auth: BasicAuth | ApiKeyAuth;
Expand Down Expand Up @@ -137,7 +138,7 @@ declare class BaseConnectionPool {
* @param {string} url
* @returns {object} host
*/
urlToHost(url: string): any;
urlToHost(url: string): { url: URL };
}

declare class ConnectionPool extends BaseConnectionPool {
Expand Down Expand Up @@ -167,7 +168,7 @@ declare class ConnectionPool extends BaseConnectionPool {
declare class CloudConnectionPool extends BaseConnectionPool {
cloudConnection: Connection | null
constructor(opts?: BaseConnectionPoolOptions);
getConnection(): Connection;
getConnection(): Connection | null;
}

declare function defaultNodeFilter(node: Connection): boolean;
Expand Down
Loading