Socket
Socket
Sign inDemoInstall

@elastic/elasticsearch

Package Overview
Dependencies
Maintainers
39
Versions
107
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@elastic/elasticsearch - npm Package Compare versions

Comparing version 0.1.0-alpha.2 to 0.1.0-alpha.3

index.d.ts

38

index.js

@@ -8,13 +8,7 @@ 'use strict'

const Serializer = require('./lib/Serializer')
const symbols = require('./lib/symbols')
const { ConfigurationError } = require('./lib/errors')
const errors = require('./lib/errors')
const { ConfigurationError } = errors
const buildApi = require('./api')
const {
kTransport,
kConnectionPool,
kSerializer
} = symbols
class Client extends EventEmitter {

@@ -33,8 +27,2 @@ constructor (opts = {}) {

// The logging is exposed via events, which the user can
// listen to and log the message its preferred way
// we add a fake listener to the error event to avoid
// the "unhandled error event" error.
this.on('error', () => {})
const options = Object.assign({}, {

@@ -62,4 +50,4 @@ Connection,

this[kSerializer] = new options.Serializer()
this[kConnectionPool] = new options.ConnectionPool({
this.serializer = new options.Serializer()
this.connectionPool = new options.ConnectionPool({
pingTimeout: options.pingTimeout,

@@ -77,8 +65,8 @@ resurrectStrategy: options.resurrectStrategy,

// Add the connections before initialize the Transport
this[kConnectionPool].addConnection(options.node || options.nodes)
this.connectionPool.addConnection(options.node || options.nodes)
this[kTransport] = new options.Transport({
this.transport = new options.Transport({
emit: this.emit.bind(this),
connectionPool: this[kConnectionPool],
serializer: this[kSerializer],
connectionPool: this.connectionPool,
serializer: this.serializer,
maxRetries: options.maxRetries,

@@ -93,6 +81,4 @@ requestTimeout: options.requestTimeout,

this.request = this[kTransport].request.bind(this[kTransport])
const apis = buildApi({
makeRequest: this[kTransport].request.bind(this[kTransport]),
makeRequest: this.transport.request.bind(this.transport),
result: { body: null, statusCode: null, headers: null, warnings: null },

@@ -111,3 +97,3 @@ ConfigurationError

REQUEST: 'request',
ERROR: 'error'
SNIFF: 'sniff'
}

@@ -121,4 +107,4 @@

Serializer,
symbols,
events
events,
errors
}

@@ -80,2 +80,11 @@ 'use strict'

// updates the ended state
request.on('abort', () => {
debug('Request aborted', params)
if (ended === false) {
ended = true
this._openRequests--
}
})
// Disables the Nagle algorithm

@@ -82,0 +91,0 @@ request.setNoDelay(true)

@@ -277,2 +277,3 @@ 'use strict'

* Transforms the nodes objects to a host object.
* TODO: handle ssl and agent options
*

@@ -334,5 +335,5 @@ * @param {object} nodes

// avoid master only nodes
if (!!node.master === true &&
!!node.data === false &&
!!node.ingest === false) {
if (!!node.roles.master === true &&
!!node.roles.data === false &&
!!node.roles.ingest === false) {
return false

@@ -339,0 +340,0 @@ }

@@ -47,2 +47,3 @@ 'use strict'

if (object == null) return ''
if (typeof object === 'string') return object
// arrays should be serialized as comma separated list

@@ -49,0 +50,0 @@ const keys = Object.keys(object)

@@ -14,3 +14,2 @@ 'use strict'

const noop = () => {}
const kRemainingAttempts = Symbol('elasticsearch-remaining-attempts')

@@ -34,3 +33,3 @@ class Transport {

if (opts.sniffOnStart === true) {
this.sniff()
this.sniff(Transport.sniffReasons.SNIFF_ON_START)
}

@@ -41,67 +40,88 @@ }

callback = once(callback)
const result = { body: null, statusCode: null, headers: null, warnings: null }
const attempts = params[kRemainingAttempts] || params.maxRetries || this.maxRetries
const connection = this.getConnection()
if (connection === null) {
return callback(new NoLivingConnectionsError('There are not living connections'), result)
const meta = {
connection: null,
request: null,
response: null,
attempts: 0,
aborted: false
}
const result = {
body: null,
statusCode: null,
headers: null,
warnings: null
}
const maxRetries = params.maxRetries || this.maxRetries
var request = { abort: noop }
params.headers = params.headers || {}
// handle json body
if (params.body != null) {
if (shouldSerialize(params.body) === true) {
try {
params.body = this.serializer.serialize(params.body)
} catch (err) {
return callback(err, result)
}
const makeRequest = () => {
if (meta.aborted === true) return
meta.connection = this.getConnection()
if (meta.connection === null) {
return callback(new NoLivingConnectionsError('There are not living connections'), result)
}
params.headers['Content-Type'] = 'application/json'
if (isStream(params.body) === false) {
params.headers['Content-Length'] = '' + Buffer.byteLength(params.body)
}
// handle ndjson body
} else if (params.bulkBody != null) {
if (shouldSerialize(params.bulkBody) === true) {
try {
params.body = this.serializer.ndserialize(params.bulkBody)
} catch (err) {
return callback(err, result)
params.headers = params.headers || {}
// handle json body
if (params.body != null) {
if (shouldSerialize(params.body) === true) {
try {
params.body = this.serializer.serialize(params.body)
} catch (err) {
return callback(err, result)
}
}
} else {
params.body = params.bulkBody
params.headers['Content-Type'] = 'application/json'
if (isStream(params.body) === false) {
params.headers['Content-Length'] = '' + Buffer.byteLength(params.body)
}
// handle ndjson body
} else if (params.bulkBody != null) {
if (shouldSerialize(params.bulkBody) === true) {
try {
params.body = this.serializer.ndserialize(params.bulkBody)
} catch (err) {
return callback(err, result)
}
} else {
params.body = params.bulkBody
}
params.headers['Content-Type'] = 'application/x-ndjson'
if (isStream(params.body) === false) {
params.headers['Content-Length'] = '' + Buffer.byteLength(params.body)
}
}
params.headers['Content-Type'] = 'application/x-ndjson'
if (isStream(params.body) === false) {
params.headers['Content-Length'] = '' + Buffer.byteLength(params.body)
if (this.suggestCompression === true) {
params.headers['Accept-Encoding'] = 'gzip,deflate'
}
}
if (this.suggestCompression === true) {
params.headers['Accept-Encoding'] = 'gzip,deflate'
}
// serializes the querystring
params.querystring = this.serializer.qserialize(params.querystring)
// handles request timeout
params.timeout = toMs(params.requestTimeout || this.requestTimeout)
// serializes the querystring
params.querystring = this.serializer.qserialize(params.querystring)
// handles request timeout
params.timeout = toMs(params.requestTimeout || this.requestTimeout)
meta.request = params
this.emit('request', null, meta)
this.emit('request', connection, params)
// perform the actual http request
return meta.connection.request(params, onResponse)
}
// perform the actual http request
const request = connection.request(params, (err, response) => {
if (err != null) {
const onResponse = (err, response) => {
if (err !== null) {
// if there is an error in the connection
// let's mark the connection as dead
this.connectionPool.markDead(connection)
this.connectionPool.markDead(meta.connection)
if (this.sniffOnConnectionFault === true) {
this.sniff()
this.sniff(Transport.sniffReasons.SNIFF_ON_CONNECTION_FAULT)
}
// retry logic
if (attempts > 0) {
debug(`Retrying request, there are still ${attempts} attempts`, params)
params[kRemainingAttempts] = attempts - 1
return this.request(params, callback)
if (meta.attempts < maxRetries) {
meta.attempts++
debug(`Retrying request, there are still ${maxRetries - meta.attempts} attempts`, params)
request = makeRequest(params, callback)
return
}

@@ -113,3 +133,3 @@

this.emit('error', error, connection, params)
this.emit('response', error, meta)
return callback(error, result)

@@ -128,3 +148,4 @@ }

result.body = response
this.emit('response', connection, params, result)
meta.response = result
this.emit('response', null, meta)
callback(null, result)

@@ -138,3 +159,7 @@ return

response.on('data', chunk => { payload += chunk })
response.on('error', err => callback(new ConnectionError(err.message, params), result))
response.on('error', err => {
const error = new ConnectionError(err.message, params)
this.emit('response', error, meta)
callback(error, result)
})
response.on('end', () => {

@@ -154,3 +179,3 @@ const isHead = params.method === 'HEAD'

} catch (err) {
this.emit('error', err, connection, params)
this.emit('response', err, meta)
return callback(err, result)

@@ -172,7 +197,9 @@ }

// and mark the connection as dead
this.connectionPool.markDead(connection)
if (attempts > 0) {
debug(`Retrying request, there are still ${attempts} attempts`, params)
params[kRemainingAttempts] = attempts - 1
return this.request(params, callback)
this.connectionPool.markDead(meta.connection)
// retry logic
if (meta.attempts < maxRetries) {
meta.attempts++
debug(`Retrying request, there are still ${maxRetries - meta.attempts} attempts`, params)
request = makeRequest(params, callback)
return
}

@@ -182,8 +209,10 @@ } else {

// the connection as alive (or confirm it)
this.connectionPool.markAlive(connection)
this.connectionPool.markAlive(meta.connection)
}
this.emit('response', connection, params, result)
meta.response = result
if (ignoreStatusCode === false && statusCode >= 400) {
callback(new ResponseError(result), result)
const error = new ResponseError(result)
this.emit('response', error, meta)
callback(error, result)
} else {

@@ -194,11 +223,15 @@ // cast to boolean if the request method was HEAD

}
this.emit('response', null, meta)
callback(null, result)
}
})
})
}
request = makeRequest()
return {
abort: () => {
meta.aborted = true
request.abort()
debug('Request aborted', params)
debug('Aborting request', params)
}

@@ -211,3 +244,3 @@ }

if (this._sniffEnabled === true && now > this._nextSniff) {
this.sniff()
this.sniff(Transport.sniffReasons.SNIFF_INTERVAL)
}

@@ -218,3 +251,3 @@ this.connectionPool.resurrect(now)

sniff (callback = noop) {
sniff (reason = Transport.sniffReasons.DEFAULT, callback = noop) {
if (this._isSniffing === true) return

@@ -224,2 +257,7 @@ this._isSniffing = true

if (typeof reason === 'function') {
callback = reason
reason = Transport.sniffReasons.DEFAULT
}
const request = {

@@ -237,4 +275,4 @@ method: 'GET',

if (err != null) {
this.emit('error', err, null, request)
debug('Sniffing errored', err)
this.emit('sniff', err, { hosts: [], reason })
return callback(err)

@@ -247,2 +285,3 @@ }

this.emit('sniff', null, { hosts, reason })
callback(null, hosts)

@@ -253,2 +292,10 @@ })

Transport.sniffReasons = {
SNIFF_ON_START: 'sniff-on-start',
SNIFF_INTERVAL: 'sniff-interval',
SNIFF_ON_CONNECTION_FAULT: 'sniff-on-connection-fault',
// TODO: find a better name
DEFAULT: 'default'
}
function toMs (time) {

@@ -255,0 +302,0 @@ if (typeof time === 'string') {

@@ -6,3 +6,3 @@ {

"homepage": "http://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/index.html",
"version": "0.1.0-alpha.2",
"version": "0.1.0-alpha.3",
"keywords": [

@@ -19,5 +19,7 @@ "elasticsearch",

"scripts": {
"test": "npm run lint && npm run test:unit",
"test:unit": "tap test/unit/*.test.js -J -T",
"test": "npm run lint && npm run test:unit && npm run test:behavior && npm run test:types",
"test:unit": "tap test/unit/*.test.js -J -t 300",
"test:behavior": "tap test/behavior/*.test.js -J -t 300",
"test:integration": "tap test/integration/index.js -T --harmony",
"test:types": "tsc --project ./test/types/tsconfig.json",
"lint": "standard",

@@ -38,2 +40,3 @@ "lint:fix": "standard --fix",

"devDependencies": {
"@types/node": "^10.12.10",
"dedent": "^0.7.0",

@@ -51,2 +54,3 @@ "deepmerge": "^2.2.1",

"tap": "^12.0.1",
"typescript": "^3.1.6",
"workq": "^2.1.0"

@@ -53,0 +57,0 @@ },

@@ -25,2 +25,3 @@ 'use strict'

const mainOutputFile = join(packageFolder, 'index.js')
const typesOutputFile = join(packageFolder, 'generated.d.ts')

@@ -39,7 +40,13 @@ log.text = 'Cleaning API folder...'

const { fn: factory, types } = genFactory(apiOutputFolder)
writeFileSync(
mainOutputFile,
genFactory(apiOutputFolder),
factory,
{ encoding: 'utf8' }
)
writeFileSync(
typesOutputFile,
types,
{ encoding: 'utf8' }
)
lintFiles(log)

@@ -74,4 +81,5 @@ })

log.succeed('Done!')
console.log('Remember to copy the generated types into the index.d.ts file')
})
}
}

@@ -10,2 +10,24 @@ 'use strict'

const apiFiles = readdirSync(folder)
const types = apiFiles
.map(file => {
return file
.slice(0, -3) // remove `.js` extension
.split('.')
.reverse()
.reduce((acc, val) => {
const obj = {
[val]: acc === null
? 'apiMethod'
: acc
}
if (isSnakeCased(val)) {
obj[camelify(val)] = acc === null
? 'apiMethod'
: acc
}
return obj
}, null)
})
.reduce((acc, val) => deepmerge(acc, val), {})
const apis = apiFiles

@@ -42,2 +64,10 @@ .map(file => {

// serialize the type object
const typesStr = Object.keys(types)
.map(key => `${key}: ${JSON.stringify(types[key], null, 2)}`)
.join('\n')
// remove useless quotes and commas
.replace(/"/g, '')
.replace(/,/g, '')
const fn = dedent`

@@ -80,3 +110,3 @@ 'use strict'

// new line at the end of file
return fn + '\n'
return { fn: fn + '\n', types: typesStr }
}

@@ -83,0 +113,0 @@

@@ -5,4 +5,3 @@ 'use strict'

const { URL } = require('url')
const { Client, symbols } = require('../../index')
const { kConnectionPool } = symbols
const { Client } = require('../../index')

@@ -14,3 +13,3 @@ test('Configure host', t => {

})
const pool = client[kConnectionPool]
const pool = client.connectionPool
t.match(pool.connections.get('http://localhost:9200/'), {

@@ -37,3 +36,3 @@ url: new URL('http://localhost:9200'),

})
const pool = client[kConnectionPool]
const pool = client.connectionPool
t.match(pool.connections.get('http://localhost:9200/'), {

@@ -83,3 +82,3 @@ url: new URL('http://localhost:9200'),

})
const pool = client[kConnectionPool]
const pool = client.connectionPool
t.match(pool.connections.get('node'), {

@@ -119,3 +118,3 @@ url: new URL('http://localhost:9200'),

})
const pool = client[kConnectionPool]
const pool = client.connectionPool
t.match(pool.connections.get('node1'), {

@@ -154,3 +153,3 @@ url: new URL('http://localhost:9200'),

})
const pool = client[kConnectionPool]
const pool = client.connectionPool
t.match(pool.connections.get('node'), {

@@ -157,0 +156,0 @@ url: new URL('http://localhost:9200'),

@@ -16,11 +16,17 @@ 'use strict'

client.on(events.REQUEST, (connection, request) => {
t.match(connection, {
id: 'http://localhost:9200'
client.on(events.REQUEST, (err, meta) => {
t.error(err)
t.match(meta, {
connection: {
id: 'http://localhost:9200'
},
request: {
method: 'GET',
path: '/test/doc/_search',
querystring: 'q=foo%3Abar'
},
response: null,
attempts: 0,
aborted: false
})
t.match(request, {
method: 'GET',
path: '/test/doc/_search',
querystring: 'q=foo%3Abar'
})
})

@@ -38,3 +44,3 @@

test('Should emit a response event in case of a successful response', t => {
t.plan(4)
t.plan(3)

@@ -46,19 +52,24 @@ const client = new Client({

client.on(events.RESPONSE, (connection, request, response) => {
t.match(connection, {
id: 'http://localhost:9200'
})
t.match(request, {
method: 'GET',
path: '/test/doc/_search',
querystring: 'q=foo%3Abar'
})
t.match(response, {
body: { hello: 'world' },
statusCode: 200,
headers: {
'content-type': 'application/json;utf=8',
'connection': 'keep-alive'
client.on(events.RESPONSE, (err, meta) => {
t.error(err)
t.match(meta, {
connection: {
id: 'http://localhost:9200'
},
warnings: null
request: {
method: 'GET',
path: '/test/doc/_search',
querystring: 'q=foo%3Abar'
},
response: {
body: { hello: 'world' },
statusCode: 200,
headers: {
'content-type': 'application/json;utf=8',
'connection': 'keep-alive'
},
warnings: null
},
attempts: 0,
aborted: false
})

@@ -76,4 +87,4 @@ })

test('Should emit an error event in case of a failing response', t => {
t.plan(4)
test('Should emit a response event with the error set', t => {
t.plan(3)

@@ -86,16 +97,17 @@ const client = new Client({

client.on(events.RESPONSE, (connection, request, response) => {
t.fail('This should not be called')
})
client.on(events.ERROR, (error, connection, request) => {
t.ok(error instanceof TimeoutError)
t.match(connection, {
id: 'http://localhost:9200'
client.on(events.RESPONSE, (err, meta) => {
t.ok(err instanceof TimeoutError)
t.match(meta, {
connection: {
id: 'http://localhost:9200'
},
request: {
method: 'GET',
path: '/test/doc/_search',
querystring: 'q=foo%3Abar'
},
response: null,
attempts: 0,
aborted: false
})
t.match(request, {
method: 'GET',
path: '/test/doc/_search',
querystring: 'q=foo%3Abar'
})
})

@@ -102,0 +114,0 @@

@@ -77,2 +77,16 @@ 'use strict'

test('qserialize (string)', t => {
t.plan(1)
const s = new Serializer()
const obj = {
hello: 'world',
you_know: 'for search'
}
t.strictEqual(
s.qserialize(stringify(obj)),
stringify(obj)
)
})
test('SerializationError', t => {

@@ -79,0 +93,0 @@ t.plan(1)

@@ -471,2 +471,53 @@ 'use strict'

test('Custom retry mechanism', t => {
t.plan(2)
var count = 0
function handler (req, res) {
res.setHeader('Content-Type', 'application/json;utf=8')
if (count > 0) {
res.end(JSON.stringify({ hello: 'world' }))
} else {
setTimeout(() => {
res.end(JSON.stringify({ hello: 'world' }))
}, 1000)
}
count++
}
buildServer(handler, ({ port }, server) => {
const pool = new ConnectionPool({ Connection })
pool.addConnection([{
url: new URL(`http://localhost:${port}`),
id: 'node1'
}, {
url: new URL(`http://localhost:${port}`),
id: 'node2'
}, {
url: new URL(`http://localhost:${port}`),
id: 'node3'
}])
const transport = new Transport({
emit: () => {},
connectionPool: pool,
serializer: new Serializer(),
maxRetries: 0,
requestTimeout: 250,
sniffInterval: false,
sniffOnStart: false
})
transport.request({
method: 'GET',
path: '/hello',
maxRetries: 1
}, (err, { body }) => {
t.error(err)
t.deepEqual(body, { hello: 'world' })
server.stop()
})
})
})
test('Should call markAlive with a successful response', t => {

@@ -571,2 +622,51 @@ t.plan(3)

test('Retry mechanism and abort', t => {
t.plan(1)
function handler (req, res) {
setTimeout(() => {
res.setHeader('Content-Type', 'application/json;utf=8')
res.end(JSON.stringify({ hello: 'world' }))
}, 1000)
}
buildServer(handler, ({ port }, server) => {
const pool = new ConnectionPool({ Connection })
pool.addConnection([{
url: new URL(`http://localhost:${port}`),
id: 'node1'
}, {
url: new URL(`http://localhost:${port}`),
id: 'node2'
}, {
url: new URL(`http://localhost:${port}`),
id: 'node3'
}])
var count = 0
const transport = new Transport({
emit: event => {
if (event === 'request' && count++ > 0) {
request.abort()
server.stop()
t.pass('ok')
}
},
connectionPool: pool,
serializer: new Serializer(),
maxRetries: 2,
requestTimeout: 100,
sniffInterval: false,
sniffOnStart: false
})
const request = transport.request({
method: 'GET',
path: '/hello'
}, (e, { body }) => {
t.fail('Should not be called')
})
})
})
test('ResponseError', t => {

@@ -573,0 +673,0 @@ t.plan(3)

'use strict'
const debug = require('debug')('elasticsearch-test')
const stoppable = require('stoppable')

@@ -18,3 +19,6 @@

var id = 0
function buildServer (handler, opts, cb) {
const serverId = id++
debug(`Booting server '${serverId}'`)
if (cb == null) {

@@ -30,4 +34,9 @@ cb = opts

server.on('request', handler)
server.on('error', err => {
console.log('http server error', err)
process.exit(1)
})
server.listen(0, () => {
const port = server.address().port
debug(`Server '${serverId}' booted on port ${port}`)
cb(Object.assign({}, secureOpts, { port }), server)

@@ -34,0 +43,0 @@ })

'use strict'
const buildServer = require('./buildServer')
const buildCluster = require('./buildCluster')
const connection = require('./MockConnection')

@@ -8,3 +9,4 @@

buildServer,
buildCluster,
connection
}

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc