metro-cache
Advanced tools
Comparing version 0.30.2 to 0.31.0
{ | ||
"version": "0.30.2", | ||
"version": "0.31.0", | ||
"name": "metro-cache", | ||
@@ -16,4 +16,5 @@ "description": "🚇 Cache layers for Metro", | ||
"jest-serializer": "^22.4.0", | ||
"metro-core": "0.31.0", | ||
"mkdirp": "^0.5.1" | ||
} | ||
} |
@@ -14,14 +14,34 @@ /** | ||
const Cache = require('../Cache'); | ||
describe('Cache', () => { | ||
let Cache; | ||
let Logger; | ||
let log; | ||
describe('Cache', () => { | ||
function createStore(i) { | ||
return { | ||
function createStore(name = '') { | ||
// eslint-disable-next-line no-eval | ||
const TempClass = eval(`(class ${name} {})`); | ||
return Object.assign(new TempClass(), { | ||
get: jest.fn().mockImplementation(() => null), | ||
set: jest.fn(), | ||
}; | ||
}); | ||
} | ||
beforeEach(() => { | ||
Logger = require('metro-core').Logger; | ||
Cache = require('../Cache'); | ||
Logger.on('log', item => { | ||
log.push({ | ||
a: item.action_name, | ||
l: item.log_entry_label, | ||
p: item.action_phase, | ||
}); | ||
}); | ||
log = []; | ||
}); | ||
afterEach(() => { | ||
jest.restoreAllMocks(); | ||
jest.resetModules().restoreAllMocks(); | ||
}); | ||
@@ -43,5 +63,5 @@ | ||
it('sequentially searches up until it finds a valid result', async () => { | ||
const store1 = createStore(1); | ||
const store2 = createStore(2); | ||
const store3 = createStore(3); | ||
const store1 = createStore(); | ||
const store2 = createStore(); | ||
const store3 = createStore(); | ||
const cache = new Cache([store1, store2, store3]); | ||
@@ -142,2 +162,59 @@ | ||
}); | ||
it('logs the right messages when getting without errors', async () => { | ||
const store1 = createStore('Local'); | ||
const store2 = createStore('Network'); | ||
const cache = new Cache([store1, store2]); | ||
store1.get.mockImplementation(() => null); | ||
store2.get.mockImplementation(() => 'le potato'); | ||
await cache.get(Buffer.from('foo')); | ||
expect(log).toEqual([ | ||
{a: 'Cache get', l: 'Cache get', p: 'start'}, | ||
{a: 'Cache get', l: 'Cache get', p: 'end'}, | ||
{a: 'Cache miss', l: 'Local::666f6f', p: undefined}, | ||
{a: 'Cache get', l: 'Cache get', p: 'start'}, | ||
{a: 'Cache get', l: 'Cache get', p: 'end'}, | ||
{a: 'Cache hit', l: 'Network::666f6f', p: undefined}, | ||
]); | ||
}); | ||
it('logs the right messages when getting with errors', async () => { | ||
const store1 = createStore('Local'); | ||
const store2 = createStore('Network'); | ||
const cache = new Cache([store1, store2]); | ||
store1.get.mockImplementation(() => null); | ||
store2.get.mockImplementation(() => Promise.reject(new TypeError('bar'))); | ||
try { | ||
await cache.get(Buffer.from('foo')); | ||
} catch (err) { | ||
// Do nothing, we care about the logs. | ||
} | ||
expect(log).toEqual([ | ||
{a: 'Cache get', l: 'Cache get', p: 'start'}, | ||
{a: 'Cache get', l: 'Cache get', p: 'end'}, | ||
{a: 'Cache miss', l: 'Local::666f6f', p: undefined}, | ||
{a: 'Cache get', l: 'Cache get', p: 'start'}, | ||
{a: 'Cache get', l: 'Cache get', p: 'end'}, | ||
{a: 'Cache miss', l: 'Network::666f6f', p: undefined}, | ||
]); | ||
}); | ||
it('logs the right messages when setting', async () => { | ||
const store1 = createStore('Local'); | ||
const store2 = createStore('Network'); | ||
const cache = new Cache([store1, store2]); | ||
await cache.set(Buffer.from('foo')); | ||
expect(log).toEqual([ | ||
{a: 'Cache set', l: 'Local::666f6f', p: undefined}, | ||
{a: 'Cache set', l: 'Network::666f6f', p: undefined}, | ||
]); | ||
}); | ||
}); |
@@ -13,4 +13,13 @@ /** | ||
const {Logger} = require('metro-core'); | ||
import type {CacheStore} from 'metro-cache'; | ||
/** | ||
* Main cache class. Receives an array of cache instances, and sequentially | ||
* traverses them to return a previously stored value. It also ensures setting | ||
* the value in all instances. | ||
* | ||
* All get/set operations are logged via Metro's logger. | ||
*/ | ||
class Cache<T> { | ||
@@ -31,12 +40,36 @@ _stores: $ReadOnlyArray<CacheStore<T>>; | ||
for (let i = 0; i < length; i++) { | ||
let value = stores[i].get(key); | ||
const store = stores[i]; | ||
const name = store.constructor.name + '::' + key.toString('hex'); | ||
let value = null; | ||
if (value instanceof Promise) { | ||
value = await value; | ||
} | ||
const logStart = Logger.log( | ||
Logger.createActionStartEntry({ | ||
action_name: 'Cache get', | ||
log_entry_label: name, | ||
}), | ||
); | ||
if (value != null) { | ||
this._hits.set(key, stores[i]); | ||
try { | ||
const valueOrPromise = store.get(key); | ||
return value; | ||
if (valueOrPromise && typeof valueOrPromise.then === 'function') { | ||
value = await valueOrPromise; | ||
} else { | ||
value = valueOrPromise; | ||
} | ||
} finally { | ||
Logger.log(Logger.createActionEndEntry(logStart)); | ||
Logger.log( | ||
Logger.createEntry({ | ||
action_name: 'Cache ' + (value == null ? 'miss' : 'hit'), | ||
log_entry_label: name, | ||
}), | ||
); | ||
if (value != null) { | ||
this._hits.set(key, store); | ||
return value; | ||
} | ||
} | ||
@@ -55,2 +88,12 @@ } | ||
for (let i = 0; i < length && stores[i] !== stop; i++) { | ||
const store = stores[i]; | ||
const name = store.constructor.name + '::' + key.toString('hex'); | ||
Logger.log( | ||
Logger.createEntry({ | ||
action_name: 'Cache set', | ||
log_entry_label: name, | ||
}), | ||
); | ||
promises.push(stores[i].set(key, value)); | ||
@@ -57,0 +100,0 @@ } |
@@ -11,6 +11,15 @@ /** | ||
'use strict';function _asyncToGenerator(fn) {return function () {var gen = fn.apply(this, arguments);return new Promise(function (resolve, reject) {function step(key, arg) {try {var info = gen[key](arg);var value = info.value;} catch (error) {reject(error);return;}if (info.done) {resolve(value);} else {return Promise.resolve(value).then(function (value) {step("next", value);}, function (err) {step("throw", err);});}}return step("next");});};} | ||
'use strict';function _asyncToGenerator(fn) {return function () {var gen = fn.apply(this, arguments);return new Promise(function (resolve, reject) {function step(key, arg) {try {var info = gen[key](arg);var value = info.value;} catch (error) {reject(error);return;}if (info.done) {resolve(value);} else {return Promise.resolve(value).then(function (value) {step("next", value);}, function (err) {step("throw", err);});}}return step("next");});};}var _require = | ||
require('metro-core');const Logger = _require.Logger; | ||
/** | ||
* Main cache class. Receives an array of cache instances, and sequentially | ||
* traverses them to return a previously stored value. It also ensures setting | ||
* the value in all instances. | ||
* | ||
* All get/set operations are logged via Metro's logger. | ||
*/ | ||
class Cache { | ||
@@ -31,12 +40,36 @@ | ||
for (let i = 0; i < length; i++) { | ||
let value = stores[i].get(key); | ||
const store = stores[i]; | ||
const name = store.constructor.name + '::' + key.toString('hex'); | ||
let value = null; | ||
if (value instanceof Promise) { | ||
value = yield value; | ||
} | ||
const logStart = Logger.log( | ||
Logger.createActionStartEntry({ | ||
action_name: 'Cache get', | ||
log_entry_label: name })); | ||
if (value != null) { | ||
_this._hits.set(key, stores[i]); | ||
return value; | ||
try { | ||
const valueOrPromise = store.get(key); | ||
if (valueOrPromise && typeof valueOrPromise.then === 'function') { | ||
value = yield valueOrPromise; | ||
} else { | ||
value = valueOrPromise; | ||
} | ||
} finally { | ||
Logger.log(Logger.createActionEndEntry(logStart)); | ||
Logger.log( | ||
Logger.createEntry({ | ||
action_name: 'Cache ' + (value == null ? 'miss' : 'hit'), | ||
log_entry_label: name })); | ||
if (value != null) { | ||
_this._hits.set(key, store); | ||
return value; | ||
} | ||
} | ||
@@ -55,2 +88,12 @@ } | ||
for (let i = 0; i < length && stores[i] !== stop; i++) { | ||
const store = stores[i]; | ||
const name = store.constructor.name + '::' + key.toString('hex'); | ||
Logger.log( | ||
Logger.createEntry({ | ||
action_name: 'Cache set', | ||
log_entry_label: name })); | ||
promises.push(stores[i].set(key, value)); | ||
@@ -57,0 +100,0 @@ } |
Sorry, the diff of this file is not supported yet
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
32798
796
3
1
+ Addedmetro-core@0.31.0
+ Addedlodash.throttle@4.1.1(transitive)
+ Addedmetro-core@0.31.0(transitive)
+ Addedwordwrap@1.0.0(transitive)