in typescript-generator/src/client.ts [200:421]
function createClientTypes (kibana = false): void {
let definitions = kibana ? kibanaDefinitions : clientDefinitions
const namespaces: string[] = []
for (let i = 0; i < model.endpoints.length; i++) {
const endpoint = model.endpoints[i]
if (isNested(endpoint.name)) {
if (namespaces.includes(getNamespace(endpoint))) {
definitions += ` ${generateDefinition(endpoint)}\n`
} else {
namespaces.push(getNamespace(endpoint))
if (model.endpoints[i - 1] != null && namespaces.includes(getNamespace(model.endpoints[i - 1]))) {
definitions += ' }\n'
}
definitions += ` ${camelify(getNamespace(endpoint))}: {\n`
definitions += ` ${generateDefinition(endpoint)}\n`
}
} else {
if (model.endpoints[i - 1] != null && namespaces.includes(getNamespace(model.endpoints[i - 1]))) {
definitions += ' }\n'
}
definitions += ` ${generateDefinition(endpoint)}\n`
}
}
if (isNested(model.endpoints[model.endpoints.length - 1].name)) {
definitions += ' }\n'
}
if (kibana) {
definitions += '}\n\nexport { KibanaClient }\n'
} else {
definitions += `}
export * as estypes from './types'
export {
Client,
Transport,
ConnectionPool,
BaseConnectionPool,
CloudConnectionPool,
Connection,
Serializer,
events,
errors,
ApiError,
ApiResponse,
RequestEvent,
ResurrectEvent,
ClientOptions,
NodeOptions,
ClientExtendsCallbackOptions
}`
}
writeFileSync(
join(__dirname, 'output.d.ts'),
definitions,
'utf8'
)
function generateDefinition (endpoint: M.Endpoint): string {
const name = isNested(endpoint.name)
? endpoint.name.split('.')[1]
: endpoint.name
const requestType = endpoint.request != null ? getType(endpoint.request) : null
const responseType = endpoint.response != null ? getType(endpoint.response) : null
if (requestType == null || responseType == null) {
let definition = `${camelify(name)}<TContext = unknown>(params?: TODO, options?: TransportRequestOptions): TransportRequestPromise<ApiResponse<TODO, TContext>>`
if (kibana) {
return definition
}
definition += `\n${indent()}${camelify(name)}<TContext = unknown>(callback: callbackFn<TODO, TContext>): TransportRequestCallback`
definition += `\n${indent()}${camelify(name)}<TContext = unknown>(params: TODO, callback: callbackFn<TODO, TContext>): TransportRequestCallback`
definition += `\n${indent()}${camelify(name)}<TContext = unknown>(params: TODO, options: TransportRequestOptions, callback: callbackFn<TODO, TContext>): TransportRequestCallback`
return definition
}
let requestDefinition = ''
let requestGenerics = ''
if (Array.isArray(requestType.generics)) {
requestDefinition = `T.${createName(requestType.name)}<${requestType.generics.map(unwrapGeneric).join(', ')}>`
requestGenerics = requestType.generics
.map(unwrapGeneric)
.map(unknownify)
.join(', ') + ', '
} else if (requestType === null) {
requestDefinition = 'TODO'
} else {
requestDefinition = `T.${createName(requestType.name)}`
}
let responseDefinition = ''
let responseGenerics = ''
if (Array.isArray(responseType.generics)) {
responseDefinition = `T.${createName(responseType.name)}<${responseType.generics.map(unwrapGeneric).map(avoidCollisions).join(', ')}>`
responseGenerics = responseType.generics
.map(unwrapGeneric)
.map(avoidCollisions)
.map(unknownify)
.join(', ') + ', '
} else if (responseType === null) {
responseDefinition = 'TODO'
} else {
responseDefinition = `T.${createName(responseType.name)}`
}
let definition = `${camelify(name)}<${responseGenerics}${requestGenerics}TContext = unknown>(params${isParamsRequired() ? '' : '?'}: ${requestDefinition}, options?: TransportRequestOptions): TransportRequestPromise<ApiResponse<${responseDefinition}, TContext>>`
if (kibana) {
return definition
}
if (!isParamsRequired()) {
definition += `\n${indent()}${camelify(name)}<${responseGenerics}${requestGenerics}TContext = unknown>(callback: callbackFn<${responseDefinition}, TContext>): TransportRequestCallback`
}
definition += `\n${indent()}${camelify(name)}<${responseGenerics}${requestGenerics}TContext = unknown>(params: ${requestDefinition}, callback: callbackFn<${responseDefinition}, TContext>): TransportRequestCallback`
definition += `\n${indent()}${camelify(name)}<${responseGenerics}${requestGenerics}TContext = unknown>(params: ${requestDefinition}, options: TransportRequestOptions, callback: callbackFn<${responseDefinition}, TContext>): TransportRequestCallback`
return definition
function indent (): string {
return isNested(endpoint.name) ? ' ' : ' '
}
function isParamsRequired (): boolean {
if (requestType == null) return false
assert(requestType.kind === 'request')
return Array.isArray(requestType.generics) ||
hasRequiredProps(requestType.path) ||
hasRequiredProps(requestType.query) ||
hasRequiredProps(requestType.body)
function hasRequiredProps (props?: M.Property[] | M.Body): boolean {
if (!Array.isArray(props)) return false
for (const prop of props) {
if (prop.required) return true
}
return false
}
}
function avoidCollisions (generic: string): string {
if (requestType === null || !Array.isArray(requestType.generics)) {
return generic
} else if (requestType.generics.map(unwrapGeneric).includes(generic)) {
return generic + 'R'
} else {
return generic
}
}
function unknownify (generic: string): string {
return `${generic} = unknown`
}
function unwrapGeneric (generic: M.TypeName | string): string {
if (typeof generic === 'string') return generic
return generic.name
}
}
function getType (name: M.TypeName): M.Request | M.Response | null {
for (const type of model.types) {
if (type.name.name === name.name && type.name.namespace === name.namespace) {
if (type.kind === 'request' && type.path.some(p => p.name.startsWith('stub'))) {
return null
}
if (type.kind === 'response' && type.body != null &&
type.body.kind === 'properties' &&
type.body.properties.some(p => p.name.startsWith('stub'))) {
return null
}
assert(type.kind !== 'enum')
assert(type.kind !== 'type_alias')
assert(type.kind !== 'interface')
return type
}
}
return null
}
function getNamespace (endpoint: M.Endpoint): string {
return isNested(endpoint.name)
? endpoint.name.split('.')[0]
: endpoint.name
}
function isNested (name: string): boolean {
return name.split('.').length > 1
}
function camelify (name: string): string {
return name.replace(/_([a-z])/g, k => k[1].toUpperCase())
}
function createName (type: M.TypeName): string {
if (type.namespace === '_builtins') return type.name
const namespace = strip(type.namespace).replace(/_([a-z])/g, k => k[1].toUpperCase())
return `${namespace.split('.').map(TitleCase).join('')}${type.name}`
function strip (namespace: string): string {
if (namespace.startsWith('_global')) {
return namespace.slice(8)
}
if (namespace.includes('_types')) {
return namespace.split('.').filter(n => n !== '_types').join('.')
}
return namespace
}
function TitleCase (str: string): string {
if (str.length === 0) return ''
return str[0].toUpperCase() + str.slice(1)
}
}
}