Demo for query storing
Change-Id: I947bcac841992c3f6cfd01ab337c265b0d01cb70
diff --git a/node_modules/cacheable-request/LICENSE b/node_modules/cacheable-request/LICENSE
new file mode 100644
index 0000000..f27ee9b
--- /dev/null
+++ b/node_modules/cacheable-request/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017 Luke Childs
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/node_modules/cacheable-request/README.md b/node_modules/cacheable-request/README.md
new file mode 100644
index 0000000..84a5568
--- /dev/null
+++ b/node_modules/cacheable-request/README.md
@@ -0,0 +1,190 @@
+# cacheable-request
+
+> Wrap native HTTP requests with RFC compliant cache support
+
+[](https://travis-ci.org/lukechilds/cacheable-request)
+[](https://coveralls.io/github/lukechilds/cacheable-request?branch=master)
+[](https://www.npmjs.com/package/cacheable-request)
+[](https://www.npmjs.com/package/cacheable-request)
+
+[RFC 7234](http://httpwg.org/specs/rfc7234.html) compliant HTTP caching for native Node.js HTTP/HTTPS requests. Caching works out of the box in memory or is easily pluggable with a wide range of storage adapters.
+
+**Note:** This is a low level wrapper around the core HTTP modules, it's not a high level request library.
+
+## Features
+
+- Only stores cacheable responses as defined by RFC 7234
+- Fresh cache entries are served directly from cache
+- Stale cache entries are revalidated with `If-None-Match`/`If-Modified-Since` headers
+- 304 responses from revalidation requests use cached body
+- Updates `Age` header on cached responses
+- Can completely bypass cache on a per request basis
+- In memory cache by default
+- Official support for Redis, MongoDB, SQLite, PostgreSQL and MySQL storage adapters
+- Easily plug in your own or third-party storage adapters
+- If DB connection fails, cache is automatically bypassed ([disabled by default](#optsautomaticfailover))
+- Adds cache support to any existing HTTP code with minimal changes
+- Uses [http-cache-semantics](https://github.com/pornel/http-cache-semantics) internally for HTTP RFC 7234 compliance
+
+## Install
+
+```shell
+npm install --save cacheable-request
+```
+
+## Usage
+
+```js
+const http = require('http');
+const CacheableRequest = require('cacheable-request');
+
+// Then instead of
+const req = http.request('http://example.com', cb);
+req.end();
+
+// You can do
+const cacheableRequest = new CacheableRequest(http.request);
+const cacheReq = cacheableRequest('http://example.com', cb);
+cacheReq.on('request', req => req.end());
+// Future requests to 'example.com' will be returned from cache if still valid
+
+// You pass in any other http.request API compatible method to be wrapped with cache support:
+const cacheableRequest = new CacheableRequest(https.request);
+const cacheableRequest = new CacheableRequest(electron.net);
+```
+
+## Storage Adapters
+
+`cacheable-request` uses [Keyv](https://github.com/lukechilds/keyv) to support a wide range of storage adapters.
+
+For example, to use Redis as a cache backend, you just need to install the official Redis Keyv storage adapter:
+
+```
+npm install --save @keyv/redis
+```
+
+And then you can pass `CacheableRequest` your connection string:
+
+```js
+const cacheableRequest = new CacheableRequest(http.request, 'redis://user:pass@localhost:6379');
+```
+
+[View all official Keyv storage adapters.](https://github.com/lukechilds/keyv#official-storage-adapters)
+
+Keyv also supports anything that follows the Map API so it's easy to write your own storage adapter or use a third-party solution.
+
+e.g The following are all valid storage adapters
+
+```js
+const storageAdapter = new Map();
+// or
+const storageAdapter = require('./my-storage-adapter');
+// or
+const QuickLRU = require('quick-lru');
+const storageAdapter = new QuickLRU({ maxSize: 1000 });
+
+const cacheableRequest = new CacheableRequest(http.request, storageAdapter);
+```
+
+View the [Keyv docs](https://github.com/lukechilds/keyv) for more information on how to use storage adapters.
+
+## API
+
+### new cacheableRequest(request, [storageAdapter])
+
+Returns the provided request function wrapped with cache support.
+
+#### request
+
+Type: `function`
+
+Request function to wrap with cache support. Should be [`http.request`](https://nodejs.org/api/http.html#http_http_request_options_callback) or a similar API compatible request function.
+
+#### storageAdapter
+
+Type: `Keyv storage adapter`<br>
+Default: `new Map()`
+
+A [Keyv](https://github.com/lukechilds/keyv) storage adapter instance, or connection string if using with an official Keyv storage adapter.
+
+### Instance
+
+#### cacheableRequest(opts, [cb])
+
+Returns an event emitter.
+
+##### opts
+
+Type: `object`, `string`
+
+Any of the default request functions options plus:
+
+###### opts.cache
+
+Type: `boolean`<br>
+Default: `true`
+
+If the cache should be used. Setting this to false will completely bypass the cache for the current request.
+
+###### opts.strictTtl
+
+Type: `boolean`<br>
+Default: `false`
+
+If set to `false`, after a cached resource's TTL expires it is kept in the cache and will be revalidated on the next request with `If-None-Match`/`If-Modified-Since` headers.
+
+If set to `true` once a cached resource has expired it is deleted and will have to be re-requested.
+
+###### opts.automaticFailover
+
+Type: `boolean`<br>
+Default: `false`
+
+When set to `true`, if the DB connection fails we will automatically fallback to a network request. DB errors will still be emitted to notify you of the problem even though the request callback may succeed.
+
+##### cb
+
+Type: `function`
+
+The callback function which will receive the response as an argument.
+
+The response can be either a [Node.js HTTP response stream](https://nodejs.org/api/http.html#http_class_http_incomingmessage) or a [responselike object](https://github.com/lukechilds/responselike). The response will also have a `fromCache` property set with a boolean value.
+
+##### .on('request', request)
+
+`request` event to get the request object of the request.
+
+**Note:** This event will only fire if an HTTP request is actually made, not when a response is retrieved from cache. However, you should always handle the `request` event to end the request and handle any potential request errors.
+
+##### .on('response', response)
+
+`response` event to get the response object from the HTTP request or cache.
+
+##### .on('error', error)
+
+`error` event emitted in case of an error with the cache.
+
+Errors emitted here will be an instance of `CacheableRequest.RequestError` or `CacheableRequest.CacheError`. You will only ever receive a `RequestError` if the request function throws (normally caused by invalid user input). Normal request errors should be handled inside the `request` event.
+
+To properly handle all error scenarios you should use the following pattern:
+
+```js
+cacheableRequest('example.com', cb)
+ .on('error', err => {
+ if (err instanceof CacheableRequest.CacheError) {
+ handleCacheError(err); // Cache error
+ } else if (err instanceof CacheableRequest.RequestError) {
+ handleRequestError(err); // Request function thrown
+ }
+ })
+ .on('request', req => {
+ req.on('error', handleRequestError); // Request error emitted
+ req.end();
+ });
+```
+
+**Note:** Database connection errors are emitted here, however `cacheable-request` will attempt to re-request the resource and bypass the cache on a connection error. Therefore a database connection error doesn't necessarily mean the request won't be fulfilled.
+
+## License
+
+MIT © Luke Childs
diff --git a/node_modules/cacheable-request/node_modules/lowercase-keys/index.js b/node_modules/cacheable-request/node_modules/lowercase-keys/index.js
new file mode 100644
index 0000000..b8d8898
--- /dev/null
+++ b/node_modules/cacheable-request/node_modules/lowercase-keys/index.js
@@ -0,0 +1,11 @@
+'use strict';
+module.exports = function (obj) {
+ var ret = {};
+ var keys = Object.keys(Object(obj));
+
+ for (var i = 0; i < keys.length; i++) {
+ ret[keys[i].toLowerCase()] = obj[keys[i]];
+ }
+
+ return ret;
+};
diff --git a/node_modules/cacheable-request/node_modules/lowercase-keys/package.json b/node_modules/cacheable-request/node_modules/lowercase-keys/package.json
new file mode 100644
index 0000000..3c2e463
--- /dev/null
+++ b/node_modules/cacheable-request/node_modules/lowercase-keys/package.json
@@ -0,0 +1,67 @@
+{
+ "_from": "lowercase-keys@1.0.0",
+ "_id": "lowercase-keys@1.0.0",
+ "_inBundle": false,
+ "_integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=",
+ "_location": "/cacheable-request/lowercase-keys",
+ "_phantomChildren": {},
+ "_requested": {
+ "type": "version",
+ "registry": true,
+ "raw": "lowercase-keys@1.0.0",
+ "name": "lowercase-keys",
+ "escapedName": "lowercase-keys",
+ "rawSpec": "1.0.0",
+ "saveSpec": null,
+ "fetchSpec": "1.0.0"
+ },
+ "_requiredBy": [
+ "/cacheable-request"
+ ],
+ "_resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz",
+ "_shasum": "4e3366b39e7f5457e35f1324bdf6f88d0bfc7306",
+ "_spec": "lowercase-keys@1.0.0",
+ "_where": "C:\\Users\\marcr\\Desktop\\KorAp\\Git\\Kalamar\\node_modules\\cacheable-request",
+ "author": {
+ "name": "Sindre Sorhus",
+ "email": "sindresorhus@gmail.com",
+ "url": "sindresorhus.com"
+ },
+ "bugs": {
+ "url": "https://github.com/sindresorhus/lowercase-keys/issues"
+ },
+ "bundleDependencies": false,
+ "deprecated": false,
+ "description": "Lowercase the keys of an object",
+ "devDependencies": {
+ "ava": "0.0.4"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "files": [
+ "index.js"
+ ],
+ "homepage": "https://github.com/sindresorhus/lowercase-keys#readme",
+ "keywords": [
+ "object",
+ "assign",
+ "extend",
+ "properties",
+ "lowercase",
+ "lower-case",
+ "case",
+ "keys",
+ "key"
+ ],
+ "license": "MIT",
+ "name": "lowercase-keys",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/sindresorhus/lowercase-keys.git"
+ },
+ "scripts": {
+ "test": "node test.js"
+ },
+ "version": "1.0.0"
+}
diff --git a/node_modules/cacheable-request/node_modules/lowercase-keys/readme.md b/node_modules/cacheable-request/node_modules/lowercase-keys/readme.md
new file mode 100644
index 0000000..dc65770
--- /dev/null
+++ b/node_modules/cacheable-request/node_modules/lowercase-keys/readme.md
@@ -0,0 +1,33 @@
+# lowercase-keys [](https://travis-ci.org/sindresorhus/lowercase-keys)
+
+> Lowercase the keys of an object
+
+
+## Install
+
+```
+$ npm install --save lowercase-keys
+```
+
+
+## Usage
+
+```js
+var lowercaseKeys = require('lowercase-keys');
+
+lowercaseKeys({FOO: true, bAr: false});
+//=> {foo: true, bar: false}
+```
+
+
+## API
+
+### lowercaseKeys(object)
+
+Lowercases the keys and returns a new object.
+
+
+
+## License
+
+MIT © [Sindre Sorhus](http://sindresorhus.com)
diff --git a/node_modules/cacheable-request/package.json b/node_modules/cacheable-request/package.json
new file mode 100644
index 0000000..7bc089b
--- /dev/null
+++ b/node_modules/cacheable-request/package.json
@@ -0,0 +1,86 @@
+{
+ "_from": "cacheable-request@^2.1.1",
+ "_id": "cacheable-request@2.1.4",
+ "_inBundle": false,
+ "_integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=",
+ "_location": "/cacheable-request",
+ "_phantomChildren": {},
+ "_requested": {
+ "type": "range",
+ "registry": true,
+ "raw": "cacheable-request@^2.1.1",
+ "name": "cacheable-request",
+ "escapedName": "cacheable-request",
+ "rawSpec": "^2.1.1",
+ "saveSpec": null,
+ "fetchSpec": "^2.1.1"
+ },
+ "_requiredBy": [
+ "/bin-wrapper/got"
+ ],
+ "_resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz",
+ "_shasum": "0d808801b6342ad33c91df9d0b44dc09b91e5c3d",
+ "_spec": "cacheable-request@^2.1.1",
+ "_where": "C:\\Users\\marcr\\Desktop\\KorAp\\Git\\Kalamar\\node_modules\\bin-wrapper\\node_modules\\got",
+ "author": {
+ "name": "Luke Childs",
+ "email": "lukechilds123@gmail.com",
+ "url": "http://lukechilds.co.uk"
+ },
+ "bugs": {
+ "url": "https://github.com/lukechilds/cacheable-request/issues"
+ },
+ "bundleDependencies": false,
+ "dependencies": {
+ "clone-response": "1.0.2",
+ "get-stream": "3.0.0",
+ "http-cache-semantics": "3.8.1",
+ "keyv": "3.0.0",
+ "lowercase-keys": "1.0.0",
+ "normalize-url": "2.0.1",
+ "responselike": "1.0.2"
+ },
+ "deprecated": false,
+ "description": "Wrap native HTTP requests with RFC compliant cache support",
+ "devDependencies": {
+ "@keyv/sqlite": "^1.2.6",
+ "ava": "^0.24.0",
+ "coveralls": "^3.0.0",
+ "create-test-server": "^2.0.0",
+ "delay": "^2.0.0",
+ "eslint-config-xo-lukechilds": "^1.0.0",
+ "nyc": "^11.0.2",
+ "pify": "^3.0.0",
+ "sqlite3": "^3.1.9",
+ "this": "^1.0.2",
+ "xo": "^0.19.0"
+ },
+ "homepage": "https://github.com/lukechilds/cacheable-request",
+ "keywords": [
+ "HTTP",
+ "HTTPS",
+ "cache",
+ "caching",
+ "layer",
+ "cacheable",
+ "RFC 7234",
+ "RFC",
+ "7234",
+ "compliant"
+ ],
+ "license": "MIT",
+ "main": "src/index.js",
+ "name": "cacheable-request",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/lukechilds/cacheable-request.git"
+ },
+ "scripts": {
+ "coverage": "nyc report --reporter=text-lcov | coveralls",
+ "test": "xo && nyc ava"
+ },
+ "version": "2.1.4",
+ "xo": {
+ "extends": "xo-lukechilds"
+ }
+}
diff --git a/node_modules/cacheable-request/src/index.js b/node_modules/cacheable-request/src/index.js
new file mode 100644
index 0000000..1935b2d
--- /dev/null
+++ b/node_modules/cacheable-request/src/index.js
@@ -0,0 +1,155 @@
+'use strict';
+
+const EventEmitter = require('events');
+const urlLib = require('url');
+const normalizeUrl = require('normalize-url');
+const getStream = require('get-stream');
+const CachePolicy = require('http-cache-semantics');
+const Response = require('responselike');
+const lowercaseKeys = require('lowercase-keys');
+const cloneResponse = require('clone-response');
+const Keyv = require('keyv');
+
+class CacheableRequest {
+ constructor(request, cacheAdapter) {
+ if (typeof request !== 'function') {
+ throw new TypeError('Parameter `request` must be a function');
+ }
+
+ this.cache = new Keyv({
+ uri: typeof cacheAdapter === 'string' && cacheAdapter,
+ store: typeof cacheAdapter !== 'string' && cacheAdapter,
+ namespace: 'cacheable-request'
+ });
+
+ return this.createCacheableRequest(request);
+ }
+
+ createCacheableRequest(request) {
+ return (opts, cb) => {
+ if (typeof opts === 'string') {
+ opts = urlLib.parse(opts);
+ }
+ opts = Object.assign({
+ headers: {},
+ method: 'GET',
+ cache: true,
+ strictTtl: false,
+ automaticFailover: false
+ }, opts);
+ opts.headers = lowercaseKeys(opts.headers);
+
+ const ee = new EventEmitter();
+ const url = normalizeUrl(urlLib.format(opts));
+ const key = `${opts.method}:${url}`;
+ let revalidate = false;
+ let madeRequest = false;
+
+ const makeRequest = opts => {
+ madeRequest = true;
+ const handler = response => {
+ if (revalidate) {
+ const revalidatedPolicy = CachePolicy.fromObject(revalidate.cachePolicy).revalidatedPolicy(opts, response);
+ if (!revalidatedPolicy.modified) {
+ const headers = revalidatedPolicy.policy.responseHeaders();
+ response = new Response(response.statusCode, headers, revalidate.body, revalidate.url);
+ response.cachePolicy = revalidatedPolicy.policy;
+ response.fromCache = true;
+ }
+ }
+
+ if (!response.fromCache) {
+ response.cachePolicy = new CachePolicy(opts, response);
+ response.fromCache = false;
+ }
+
+ let clonedResponse;
+ if (opts.cache && response.cachePolicy.storable()) {
+ clonedResponse = cloneResponse(response);
+ getStream.buffer(response)
+ .then(body => {
+ const value = {
+ cachePolicy: response.cachePolicy.toObject(),
+ url: response.url,
+ statusCode: response.fromCache ? revalidate.statusCode : response.statusCode,
+ body
+ };
+ const ttl = opts.strictTtl ? response.cachePolicy.timeToLive() : undefined;
+ return this.cache.set(key, value, ttl);
+ })
+ .catch(err => ee.emit('error', new CacheableRequest.CacheError(err)));
+ } else if (opts.cache && revalidate) {
+ this.cache.delete(key)
+ .catch(err => ee.emit('error', new CacheableRequest.CacheError(err)));
+ }
+
+ ee.emit('response', clonedResponse || response);
+ if (typeof cb === 'function') {
+ cb(clonedResponse || response);
+ }
+ };
+
+ try {
+ const req = request(opts, handler);
+ ee.emit('request', req);
+ } catch (err) {
+ ee.emit('error', new CacheableRequest.RequestError(err));
+ }
+ };
+
+ const get = opts => Promise.resolve()
+ .then(() => opts.cache ? this.cache.get(key) : undefined)
+ .then(cacheEntry => {
+ if (typeof cacheEntry === 'undefined') {
+ return makeRequest(opts);
+ }
+
+ const policy = CachePolicy.fromObject(cacheEntry.cachePolicy);
+ if (policy.satisfiesWithoutRevalidation(opts)) {
+ const headers = policy.responseHeaders();
+ const response = new Response(cacheEntry.statusCode, headers, cacheEntry.body, cacheEntry.url);
+ response.cachePolicy = policy;
+ response.fromCache = true;
+
+ ee.emit('response', response);
+ if (typeof cb === 'function') {
+ cb(response);
+ }
+ } else {
+ revalidate = cacheEntry;
+ opts.headers = policy.revalidationHeaders(opts);
+ makeRequest(opts);
+ }
+ });
+
+ this.cache.on('error', err => ee.emit('error', new CacheableRequest.CacheError(err)));
+
+ get(opts).catch(err => {
+ if (opts.automaticFailover && !madeRequest) {
+ makeRequest(opts);
+ }
+ ee.emit('error', new CacheableRequest.CacheError(err));
+ });
+
+ return ee;
+ };
+ }
+}
+
+CacheableRequest.RequestError = class extends Error {
+ constructor(err) {
+ super(err.message);
+ this.name = 'RequestError';
+ Object.assign(this, err);
+ }
+};
+
+CacheableRequest.CacheError = class extends Error {
+ constructor(err) {
+ super(err.message);
+ this.name = 'CacheError';
+ Object.assign(this, err);
+ }
+};
+
+module.exports = CacheableRequest;