All good open source repositories have an excellent README guide or a website which explains how to use it. But most of them don't have any kind of guide for the source itself. Although this is less likely to be useful for the average user, it can be quite useful for anyone who is looking to contribute or perhaps wants to debug a weird behavior.
You absolutely don't need to read this. But you could. If you wanted to.
All the source files written in ES6 are present in the src
folder.
This gets transpiled using babel to the lib
folder.
npm script:
cross-env BABEL_ENV=production babel src --out-dir lib
This is not tracked in git but is present in the npm package which the end user gets.
// package.json snippet
{
// ...
// Files to be picked up by npm
"files": [
"browser/",
"lib/",
"src/",
"repl.js",
"index.d.ts"
],
// ...
}
These transpiled files are then webpack
ed into a minified umd
module
for use in the browser and kept in the browser
folder.
This is also used by the demo hosted on https://elastic-builder.js.org
The code in src
folder doesn't use es6 imports. So it can be directly used without the transpiled code.
Earlier, the transpiled code used to jumble the documentation so there was an advantage to using
from elastic-builder/src
. But now I have added the type definition so that advantage no longer applies.
Starting from the base folder src
, index.js
simply pulls in all the concrete classes and re-exports
them under the same object so that you can access all queries and aggregations. It also adds
helper methods so that the class, for example MatchQuery
can be instantiated with bob.matchQuery()
thereby avoiding the new
keyword. This means there are 2 ways of doing the same thing. While this is not ideal,
the reason for doing so because the documentation, type definitions declare classes and
it might be confusing to access them using only functions. I am open to rethinking this approach.
recipes.js
has a few helper methods for augmenting the base queries and aggregations.
For example, although elasticsearch no longer supports the missing
query, there is a helper recipe for that.
I am also considering adding a bodybuilder
style bool query builder to the recipes.
The library uses inheritance and es6 class syntax quite heavily. The base classes for
request body search, queries, aggregations and other misc classes are present in core
.
The queries, aggregations are organised to mirror the elasticsearch reference guide.
Whereever there is common behavior for multiple classes, the methods are moved to a base class.
Strictly speaking, all the base classes are instantiable.
But this is less likely to be useful and hence are not exported.
You could very easily override or extend any behavior for these classes.
Some classes have a relatively long inheritance chain.
Query -> FullTextQueryBase -> MonoFieldQueryBase -> MatchPhraseQueryBase -> MatchPhraseQuery
This can get a little confusing but I am hoping that the type definition solves most of the woes.
Tests are written using ava
and each file is independent. I am using macros heavily.
Probably harder to understand. But very good for reusing test code.
To be able to test with different node versions,
we need to use babel
again. However, the lib
files do not have source maps(not useful in prod) so cannot be used
to measure coverage. Earlier, I setup ava
to use babel-register
but with the sheer number of files,
this performed very poorly. So as suggested in a ava
recipe, I setup pre-compilation step to transpile
tests to _build
folder(not tracked in git).
You can pretty much ignore the assets
folder.
I am using release-it
for making releases. One of the key factors for doing this is to
auto generate release notes. I also looked into conventional changelog and am trying to follow that
for commits. On starting the release, it runs tests, builds lib
, generates documentation(docs
folder)
and creates the github release. I manually wait for all tests in travis to pass before running npm publish
.
There are other options like semantic release which can take care of the entire workflow but
provide less flexibility. I am not yet completely comfortable with git branches and am using the master
branch itself for pushing commits. So I don't always want to release when I push to master.
For the project prod dependencies, I am using the modularised lodash
libraries
along with babel-runtime
. The reason for doing this, although quite unlikely,
is because if someone does use it, they shouldn't have to load 100 kb worth of lodash
.
There are plugins available for only exporting what you use but the end user may not be aware of that.