🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@andrewshell/cacheism

Package Overview
Dependencies
Maintainers
1
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@andrewshell/cacheism - npm Package Compare versions

Comparing version
1.0.0
to
2.0.0
+36
.github/workflows/node.js.yml
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
name: Node.js CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x, 16.x, 18.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- name: Archive npm failure logs
uses: actions/upload-artifact@v3
if: failure()
with:
name: npm-logs
path: ~/.npm/_logs
- run: npm test
const expect = require('expect.js');
const mockdate = require('mockdate');
const Cacheism = require('../lib/cacheism');
function expectCacheHit(c, cached, data) {
expect(c).to.be.a(Cacheism.Hit);
expect(c).to.have.property('version', 3);
expect(c).to.have.property('cacheName', '-internal/cache');
expect(c).to.have.property('cached', cached);
expect(c).to.have.property('created');
expect(c.created).to.be.a(Date);
expect(c).to.have.property('data', data);
expect(c).to.have.property('etag');
}
function expectCacheMiss(c, cached, data) {
expect(c).to.be.a(Cacheism.Miss);
expect(c).to.have.property('version', 3);
expect(c).to.have.property('cacheName', '-internal/cache');
expect(c).to.have.property('cached', cached);
expect(c).to.have.property('created');
expect(c.created).to.be.a(Date);
expect(c).to.have.property('data', data);
expect(c).to.have.property('etag', null);
}
function expectCacheNoErrors(c) {
expect(c).to.have.property('error', null);
expect(c).to.have.property('errorTime', null);
expect(c).to.have.property('consecutiveErrors', 0);
}
function expectCacheErrors(c, error, errors) {
expect(c).to.have.property('error', error);
expect(c).to.have.property('errorTime');
expect(c.errorTime).to.be.a(Date);
expect(c).to.have.property('consecutiveErrors', errors);
}
function expectDataHit(d, data, etag) {
expect(d).to.be.a(Cacheism.Data);
expect(d).to.have.property('version', 3);
expect(d).to.have.property('type', Cacheism.Type.hit);
expect(d).to.have.property('created');
expect(d.created).to.be.a(Date);
expect(d).to.have.property('data', data);
expect(d).to.have.property('etag', etag);
}
function expectDataMiss(d, data, etag) {
expect(d).to.be.a(Cacheism.Data);
expect(d).to.have.property('version', 3);
expect(d).to.have.property('type', Cacheism.Type.miss);
expect(d).to.have.property('created');
expect(d.created).to.be.a(Date);
expect(d).to.have.property('data', data);
expect(d).to.have.property('etag', etag);
}
function expectDataNoErrors(d) {
expect(d).to.have.property('error', null);
expect(d).to.have.property('errorTime', null);
expect(d).to.have.property('consecutiveErrors', 0);
}
function expectDataErrors(d, error, errors) {
expect(d).to.have.property('error', error);
expect(d).to.have.property('errorTime');
expect(d.errorTime).to.be.a(Date);
expect(d).to.have.property('consecutiveErrors', errors);
}
module.exports = {
expectCacheHit,
expectCacheMiss,
expectCacheNoErrors,
expectCacheErrors,
expectDataHit,
expectDataMiss,
expectDataNoErrors,
expectDataErrors,
};
+21
-12

@@ -10,2 +10,3 @@ const common = require('./common');

this.status = common.Status;
this.type = common.Type;
}

@@ -16,12 +17,12 @@

try {
let existing = new common.Miss(name, new Error('Missing cache'), 0);
let hasCache = await this.store.isset(name);
let existing = new common.Miss(name, new Error('Missing cache'));
let hasCache = await this.store.isset(name);
if (hasCache) {
existing = (await this.store.get(name)).response();
}
if (hasCache) {
existing = await this.store.get(name);
}
try {
if (status >= this.status.preferCache && hasCache) {
if (status >= this.status.preferCache && hasCache && existing.isHit) {
response = existing;

@@ -35,3 +36,2 @@ } else if (status === this.status.onlyCache) {

}
await this.store.set(response);
}

@@ -41,7 +41,13 @@

if (status >= this.status.cacheOnFail && await this.store.isset(name)) {
response = await this.store.get(name);
response.error = err;
if (status >= this.status.cacheOnFail && hasCache) {
response = existing;
response.error = err.toString();
response.errorTime = new Date();
response.consecutiveErrors++;
} else {
response = new common.Miss(name, err);
response = new common.Miss(
name,
err.toString(),
existing.consecutiveErrors + 1
);
}

@@ -51,2 +57,4 @@

await this.store.set(common.Data.fromResponse(response));
Object.freeze(response);

@@ -76,2 +84,3 @@ return response;

Cacheism.Status = common.Status;
Cacheism.Type = common.Type;

@@ -78,0 +87,0 @@ Cacheism.store = {

@@ -10,2 +10,7 @@ const generateEtag = require('etag');

class Type {}
Type.hit = 'Hit';
Type.miss = 'Miss';
Object.freeze(Status);

@@ -15,3 +20,3 @@

constructor(name, data, etag) {
this.version = 2;
this.version = 3;
this.cacheName = name;

@@ -22,2 +27,4 @@ this.cached = false;

this.error = null;
this.errorTime = null;
this.consecutiveErrors = 0;
this.etag = null == etag ? generateEtag(JSON.stringify(data)) : etag;

@@ -30,4 +37,4 @@ this.isHit = true;

class Miss {
constructor(name, error) {
this.version = 2;
constructor(name, error, consecutiveErrors) {
this.version = 3;
this.cacheName = name;

@@ -38,2 +45,4 @@ this.cached = false;

this.error = error;
this.errorTime = new Date(this.created);
this.consecutiveErrors = consecutiveErrors;
this.etag = null;

@@ -46,20 +55,34 @@ this.isHit = false;

class Data {
constructor(version, name, created, data, etag) {
constructor(version, type, name, created, data, error, errorTime, consecutiveErrors, etag) {
this.version = version;
this.type = type;
this.cacheName = name;
this.created = created;
this.data = data;
this.error = error;
this.errorTime = errorTime;
this.consecutiveErrors = consecutiveErrors;
this.etag = etag;
}
hit() {
if (2 !== this.version) {
response() {
if (3 !== this.version) {
throw new Error(`Unknown cache version number: ${this.version}`);
}
const hit = new Hit(this.cacheName, this.data, this.etag);
hit.cached = true;
hit.created = this.created;
let response;
return hit;
if (this.type === Type.hit) {
response = new Hit(this.cacheName, this.data, this.etag);
response.cached = true;
response.created = this.created;
response.consecutiveErrors = this.consecutiveErrors;
} else {
response = new Miss(this.cacheName, this.error, this.consecutiveErrors);
response.cached = false;
response.created = this.created;
response.errorTime = this.errorTime;
}
return response;
}

@@ -70,5 +93,9 @@

version: this.version,
type: this.type,
cacheName: this.cacheName,
created: this.created,
data: this.data,
error: this.error,
errorTime: this.errorTime,
consecutiveErrors: this.consecutiveErrors,
etag: this.etag,

@@ -78,4 +105,14 @@ }, null, 2);

static fromHit(hit) {
return new Data(hit.version, hit.cacheName, hit.created, hit.data, hit.etag);
static fromResponse(response) {
return new Data(
response.version,
response.isHit ? Type.hit : Type.miss,
response.cacheName,
response.created,
response.data,
response.error,
response.errorTime,
response.consecutiveErrors,
response.etag
);
}

@@ -85,6 +122,55 @@

const parsed = JSON.parse(value);
return new Data(parsed.version, parsed.cacheName, new Date(parsed.created), parsed.data, parsed.etag);
if (2 === parsed.version) {
return new Data(
3,
Type.hit,
parsed.cacheName,
new Date(parsed.created),
parsed.data,
null,
null,
0,
parsed.etag
);
}
if (3 === parsed.version) {
return new Data(
3,
parsed.type,
parsed.cacheName,
new Date(parsed.created),
parsed.data,
parsed.error,
null === parsed.errorTime ? null : new Date(parsed.errorTime),
parsed.consecutiveErrors,
parsed.etag
);
}
throw new Error(`Unknown cache version number: ${parsed.version}`);
}
}
module.exports = { Hit, Miss, Data, Status };
module.exports = { Hit, Miss, Data, Status, Type };
/**
* String.prototype.replaceAll() polyfill
* https://gomakethings.com/how-to-replace-a-section-of-a-string-with-another-one-with-vanilla-js/
* @author Chris Ferdinandi
* @license MIT
*/
if (!String.prototype.replaceAll) {
String.prototype.replaceAll = function(str, newStr){
// If a regex pattern
if (Object.prototype.toString.call(str).toLowerCase() === '[object regexp]') {
return this.replace(str, newStr);
}
// If a string
return this.replace(new RegExp(str, 'g'), newStr);
};
}

@@ -19,9 +19,9 @@ const common = require('./common');

const data = await fsPromises.readFile(filename, 'utf8');
return common.Data.parse(data).hit();
return common.Data.parse(data);
}
storeFilesystem.set = async (hit) => {
const filename = path.resolve(config.datadir, `${hit.cacheName}.json`);
storeFilesystem.set = async (data) => {
const filename = path.resolve(config.datadir, `${data.cacheName}.json`);
_mkdir(path.dirname(filename));
await fsPromises.writeFile(filename, common.Data.fromHit(hit).stringify(), 'utf8');
await fsPromises.writeFile(filename, data.stringify(), 'utf8');
}

@@ -28,0 +28,0 @@

@@ -7,7 +7,7 @@ const common = require('./common');

storeMemory.get = async (cacheName) => {
return common.Data.parse(storeMemory.data[cacheName]).hit();
return common.Data.parse(storeMemory.data[cacheName]);
}
storeMemory.set = async (hit) => {
storeMemory.data[hit.cacheName] = common.Data.fromHit(hit).stringify();
storeMemory.set = async (data) => {
storeMemory.data[data.cacheName] = data.stringify();
}

@@ -14,0 +14,0 @@

{
"name": "@andrewshell/cacheism",
"version": "1.0.0",
"version": "2.0.0",
"description": "Simple caching library",

@@ -25,3 +25,4 @@ "main": "lib/cacheism.js",

"expect.js": "^0.3.1",
"mocha": "^9.2.2"
"mocha": "^10.2.0",
"mockdate": "^3.0.5"
},

@@ -28,0 +29,0 @@ "dependencies": {

# cacheism
Simple caching library
[![Node.js CI](https://github.com/andrewshell/cacheism/actions/workflows/node.js.yml/badge.svg)](https://github.com/andrewshell/cacheism/actions/workflows/node.js.yml)
## Overview

@@ -72,11 +74,13 @@

Hit {
version: 2,
version: 3,
cacheName: '-internal/hoopla',
cached: true,
created: 2022-04-22T21:05:14.094Z,
created: 2023-04-02T22:00:49.320Z,
data: { message: 'Hoopla!' },
error: Error: Death
at /Users/andrewshell/code/personal/test-cacheism/index.js:8:15
at Cacheism.go (/Users/andrewshell/code/personal/cacheism/lib/cacheism.js:29:30)
at async run (/Users/andrewshell/code/personal/test-cacheism/index.js:7:13),
at /Users/andrewshell/code/test-cacheism/index.js:9:19
at Cacheism.go (/Users/andrewshell/code/cacheism/lib/cacheism.js:30:30)
at async run (/Users/andrewshell/code/test-cacheism/index.js:7:18),
errorTime: 2023-04-02T22:00:49.928Z,
consecutiveErrors: 1,
etag: '"15-QcHvuZdyxCmLJ4zoYIPsP6pkNoM"',

@@ -99,10 +103,12 @@ isHit: true,

Miss {
version: 2,
version: 3,
cacheName: '-internal/hoopla',
cached: false,
created: 2022-04-22T21:30:56.275Z,
created: 2023-04-02T22:02:30.294Z,
data: null,
error: Error: Missing cache
at Cacheism.go (/Users/andrewshell/code/personal/cacheism/lib/cacheism.js:27:19)
at async run (/Users/andrewshell/code/personal/test-cacheism/index.js:7:18),
at Cacheism.go (/Users/andrewshell/code/cacheism/lib/cacheism.js:28:19)
at async run (/Users/andrewshell/code/test-cacheism/index.js:7:18),
errorTime: 2023-04-02T22:02:30.294Z,
consecutiveErrors: 1,
etag: null,

@@ -109,0 +115,0 @@ isHit: false,

const expect = require('expect.js');
const mockdate = require('mockdate');
const fs = require('fs');

@@ -9,2 +11,4 @@ const path = require('path');

const helpers = require('./helpers');
describe('filesystem', function() {

@@ -32,47 +36,88 @@

it('should return a Hit with the live value', async function () {
const c = await cache.go('-internal', 'nocache', Cacheism.Status.onlyFresh, async () => {
return 'live';
describe('and no existing cache', async function () {
it('should return a Hit (live value) on success', async function () {
const c = await cache.go('-internal', 'cache', Cacheism.Status.onlyFresh, async () => {
return 'live';
});
helpers.expectCacheHit(c, false, 'live');
helpers.expectCacheNoErrors(c);
expect(await cache.store.isset('-internal/cache')).to.be(true);
const d = await cache.store.get('-internal/cache');
helpers.expectDataHit(d, 'live', c.etag);
helpers.expectDataNoErrors(d);
});
expect(c).to.be.a(Cacheism.Hit);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/nocache');
expect(c).to.have.property('cached', false);
expect(c).to.have.property('created');
expect(c.created).to.be.a(Date);
expect(c).to.have.property('data', 'live');
expect(c).to.have.property('error', null);
expect(c).to.have.property('etag');
});
it('should return a Miss on error', async function () {
const c = await cache.go('-internal', 'cache', Cacheism.Status.onlyFresh, async () => {
throw Error('cache error');
});
it('should return a Miss on error', async function () {
const c = await cache.go('-internal', 'nocache', Cacheism.Status.onlyFresh, async () => {
throw Error('cache error');
helpers.expectCacheMiss(c, false, null);
helpers.expectCacheErrors(c, 'cache error', 1);
expect(c.created).to.eql(c.errorTime);
expect(await cache.store.isset('-internal/cache')).to.be(true);
const d = await cache.store.get('-internal/cache');
helpers.expectDataMiss(d, null);
helpers.expectDataErrors(d, 'Error: cache error', 1);
expect(d.created).to.eql(d.errorTime);
});
expect(c).to.be.a(Cacheism.Miss);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/nocache');
expect(c).to.have.property('error');
expect(c.error).to.be.an(Error);
expect(c.error).to.have.property('message', 'cache error');
});
it('should update cache with successful live value', async function () {
const c = await cache.go('-internal', 'true', Cacheism.Status.onlyFresh, async () => {
return 'live';
describe('and having existing cache', async function () {
it('should return a Hit (live value) on success', async function () {
mockdate.set('2000-11-22');
await cache.store.set(Cacheism.Data.fromResponse(
new Cacheism.Hit('-internal/cache', 'cached')
));
mockdate.reset();
const c = await cache.go('-internal', 'cache', Cacheism.Status.onlyFresh, async () => {
return 'live';
});
helpers.expectCacheHit(c, false, 'live');
helpers.expectCacheNoErrors(c);
expect(await cache.store.isset('-internal/cache')).to.be(true);
const d = await cache.store.get('-internal/cache');
helpers.expectDataHit(d, 'live', c.etag);
helpers.expectDataNoErrors(d);
});
expect(c).to.be.a(Cacheism.Hit);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/true');
expect(c).to.have.property('cached', false);
expect(c).to.have.property('created');
expect(c.created).to.be.a(Date);
expect(c).to.have.property('data', 'live');
expect(c).to.have.property('error', null);
expect(c).to.have.property('etag');
it('should return a Miss on error', async function () {
mockdate.set('2000-11-22');
expect(await cache.store.isset('-internal/true')).to.be(true);
await cache.store.set(Cacheism.Data.fromResponse(
new Cacheism.Hit('-internal/cache', 'cached')
));
mockdate.reset();
const c = await cache.go('-internal', 'cache', Cacheism.Status.onlyFresh, async () => {
throw Error('cache error');
});
helpers.expectCacheMiss(c, false, null);
helpers.expectCacheErrors(c, 'cache error', 1);
expect(c.created).to.eql(c.errorTime);
expect(await cache.store.isset('-internal/cache')).to.be(true);
const d = await cache.store.get('-internal/cache');
helpers.expectDataMiss(d, null);
helpers.expectDataErrors(d, 'Error: cache error', 1);
expect(d.created).to.eql(d.errorTime);
});
});

@@ -84,69 +129,88 @@

it('should return a Miss on error with no cache', async function () {
const c = await cache.go('-internal', 'nocache', Cacheism.Status.cacheOnFail, async () => {
throw Error('cache error');
describe('and no existing cache', async function () {
it('should return a Hit (live value) on success', async function () {
const c = await cache.go('-internal', 'cache', Cacheism.Status.cacheOnFail, async () => {
return 'live';
});
helpers.expectCacheHit(c, false, 'live');
helpers.expectCacheNoErrors(c);
expect(await cache.store.isset('-internal/cache')).to.be(true);
const d = await cache.store.get('-internal/cache');
helpers.expectDataHit(d, 'live', c.etag);
helpers.expectDataNoErrors(d);
});
expect(c).to.be.a(Cacheism.Miss);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/nocache');
expect(c).to.have.property('error');
expect(c.error).to.be.an(Error);
expect(c.error).to.have.property('message', 'cache error');
});
it('should return a Miss on error', async function () {
const c = await cache.go('-internal', 'cache', Cacheism.Status.cacheOnFail, async () => {
throw Error('cache error');
});
it('should return a Hit on error with cache', async function () {
await cache.store.set(new Cacheism.Hit('-internal/true', 'cached'));
helpers.expectCacheMiss(c, false, null);
helpers.expectCacheErrors(c, 'cache error', 1);
expect(c.created).to.eql(c.errorTime);
const c = await cache.go('-internal', 'true', Cacheism.Status.cacheOnFail, async () => {
throw Error('cache error');
expect(await cache.store.isset('-internal/cache')).to.be(true);
const d = await cache.store.get('-internal/cache');
helpers.expectDataMiss(d, null, c.etag);
helpers.expectDataErrors(d, 'Error: cache error', 1);
expect(d.created).to.eql(d.errorTime);
});
expect(c).to.be.a(Cacheism.Hit);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/true');
expect(c).to.have.property('cached', true);
expect(c).to.have.property('created');
expect(c.created).to.be.a(Date);
expect(c).to.have.property('data', 'cached');
expect(c).to.have.property('error');
expect(c.error).to.be.an(Error);
expect(c.error).to.have.property('message', 'cache error');
expect(c).to.have.property('etag');
});
it('should return a Hit with the live value with cache', async function () {
await cache.store.set(new Cacheism.Hit('-internal/true', 'cached'));
describe('and having existing cache', async function () {
const c = await cache.go('-internal', 'true', Cacheism.Status.cacheOnFail, async () => {
return 'live';
it('should return a Hit (live value) on success', async function () {
mockdate.set('2000-11-22');
await cache.store.set(Cacheism.Data.fromResponse(
new Cacheism.Hit('-internal/cache', 'cached')
));
mockdate.reset();
const c = await cache.go('-internal', 'cache', Cacheism.Status.cacheOnFail, async () => {
return 'live';
});
helpers.expectCacheHit(c, false, 'live');
helpers.expectCacheNoErrors(c);
expect(await cache.store.isset('-internal/cache')).to.be(true);
const d = await cache.store.get('-internal/cache');
helpers.expectDataHit(d, 'live', c.etag);
helpers.expectDataNoErrors(d);
});
expect(c).to.be.a(Cacheism.Hit);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/true');
expect(c).to.have.property('cached', false);
expect(c).to.have.property('created');
expect(c.created).to.be.a(Date);
expect(c).to.have.property('data', 'live');
expect(c).to.have.property('error', null);
expect(c).to.have.property('etag');
});
it('should return a Hit (cached value) on error', async function () {
mockdate.set('2000-11-22');
it('should update cache with successful live value', async function () {
await cache.store.set(new Cacheism.Hit('-internal/true', 'cached'));
await cache.store.set(Cacheism.Data.fromResponse(
new Cacheism.Hit('-internal/cache', 'cached')
));
const c = await cache.go('-internal', 'true', Cacheism.Status.cacheOnFail, async () => {
return 'live';
mockdate.reset();
const c = await cache.go('-internal', 'cache', Cacheism.Status.cacheOnFail, async () => {
throw Error('cache error');
});
helpers.expectCacheHit(c, true, 'cached');
helpers.expectCacheErrors(c, 'cache error', 1);
expect(c.created).not.to.eql(c.errorTime);
expect(await cache.store.isset('-internal/cache')).to.be(true);
const d = await cache.store.get('-internal/cache');
helpers.expectDataHit(d, 'cached', c.etag);
helpers.expectDataErrors(d, 'Error: cache error', 1);
expect(d.created).not.to.eql(d.errorTime);
});
expect(c).to.be.a(Cacheism.Hit);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/true');
expect(c).to.have.property('cached', false);
expect(c).to.have.property('created');
expect(c.created).to.be.a(Date);
expect(c).to.have.property('data', 'live');
expect(c).to.have.property('error', null);
expect(c).to.have.property('etag');
});

@@ -158,47 +222,86 @@

it('should return a Miss on error with no cache', async function () {
const c = await cache.go('-internal', 'nocache', Cacheism.Status.preferCache, async () => {
throw Error('cache error');
describe('and no existing cache', async function () {
it('should return a Hit (live value) on success', async function () {
const c = await cache.go('-internal', 'cache', Cacheism.Status.preferCache, async () => {
return 'live';
});
helpers.expectCacheHit(c, false, 'live');
helpers.expectCacheNoErrors(c);
expect(await cache.store.isset('-internal/cache')).to.be(true);
const d = await cache.store.get('-internal/cache');
helpers.expectDataHit(d, 'live', c.etag);
helpers.expectDataNoErrors(d);
});
expect(c).to.be.a(Cacheism.Miss);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/nocache');
expect(c).to.have.property('error');
expect(c.error).to.be.an(Error);
expect(c.error).to.have.property('message', 'cache error');
});
it('should return a Miss on error', async function () {
const c = await cache.go('-internal', 'cache', Cacheism.Status.preferCache, async () => {
throw Error('cache error');
});
it('should return a Hit with the cached value with cache', async function () {
await cache.store.set(new Cacheism.Hit('-internal/true', 'cached'));
helpers.expectCacheMiss(c, false, null);
helpers.expectCacheErrors(c, 'cache error', 1);
expect(c.created).to.eql(c.errorTime);
const c = await cache.go('-internal', 'true', Cacheism.Status.preferCache, async () => {
return 'live';
expect(await cache.store.isset('-internal/cache')).to.be(true);
const d = await cache.store.get('-internal/cache');
helpers.expectDataMiss(d, null, c.etag);
helpers.expectDataErrors(d, 'Error: cache error', 1);
expect(d.created).to.eql(d.errorTime);
});
expect(c).to.be.a(Cacheism.Hit);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/true');
expect(c).to.have.property('cached', true);
expect(c).to.have.property('created');
expect(c.created).to.be.a(Date);
expect(c).to.have.property('data', 'cached');
expect(c).to.have.property('error', null);
expect(c).to.have.property('etag');
});
it('should return a Hit with the live value with no cache', async function () {
const c = await cache.go('-internal', 'true', Cacheism.Status.preferCache, async () => {
return 'live';
describe('and having existing cache', async function () {
it('should return a Hit (cached value) on success', async function () {
mockdate.set('2000-11-22');
await cache.store.set(Cacheism.Data.fromResponse(
new Cacheism.Hit('-internal/cache', 'cached')
));
mockdate.reset();
const c = await cache.go('-internal', 'cache', Cacheism.Status.preferCache, async () => {
return 'live';
});
helpers.expectCacheHit(c, true, 'cached');
helpers.expectCacheNoErrors(c);
expect(await cache.store.isset('-internal/cache')).to.be(true);
const d = await cache.store.get('-internal/cache');
helpers.expectDataHit(d, 'cached', c.etag);
helpers.expectDataNoErrors(d);
});
expect(c).to.be.a(Cacheism.Hit);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/true');
expect(c).to.have.property('cached', false);
expect(c).to.have.property('created');
expect(c.created).to.be.a(Date);
expect(c).to.have.property('data', 'live');
expect(c).to.have.property('error', null);
expect(c).to.have.property('etag');
it('should return a Hit (cached value) on error', async function () {
mockdate.set('2000-11-22');
await cache.store.set(Cacheism.Data.fromResponse(
new Cacheism.Hit('-internal/cache', 'cached')
));
mockdate.reset();
const c = await cache.go('-internal', 'cache', Cacheism.Status.preferCache, async () => {
throw Error('cache error');
});
helpers.expectCacheHit(c, true, 'cached');
helpers.expectCacheNoErrors(c);
expect(await cache.store.isset('-internal/cache')).to.be(true);
const d = await cache.store.get('-internal/cache');
helpers.expectDataHit(d, 'cached', c.etag);
helpers.expectDataNoErrors(d);
});
});

@@ -209,44 +312,89 @@

describe('when status=onlyCache', function () {
it('should return a Miss on error with no cache', async function () {
const c = await cache.go('-internal', 'nocache', Cacheism.Status.onlyCache, async () => {
throw Error('cache error');
describe('and no existing cache', async function () {
it('should return a Miss on success', async function () {
const c = await cache.go('-internal', 'cache', Cacheism.Status.onlyCache, async () => {
return 'live';
});
helpers.expectCacheMiss(c, false, null);
helpers.expectCacheErrors(c, 'Missing cache', 1);
expect(c.created).to.eql(c.errorTime);
expect(await cache.store.isset('-internal/cache')).to.be(true);
const d = await cache.store.get('-internal/cache');
helpers.expectDataMiss(d, null, null);
helpers.expectDataErrors(d, 'Error: Missing cache', 1);
expect(d.created).to.eql(d.errorTime);
});
expect(c).to.be.a(Cacheism.Miss);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/nocache');
expect(c).to.have.property('error');
expect(c.error).to.be.an(Error);
expect(c.error).to.have.property('message', 'Missing cache');
});
it('should return a Miss on error', async function () {
const c = await cache.go('-internal', 'cache', Cacheism.Status.onlyCache, async () => {
throw Error('cache error');
});
it('should return a Hit with the cached value with cache', async function () {
await cache.store.set(new Cacheism.Hit('-internal/true', 'cached'));
helpers.expectCacheMiss(c, false, null);
helpers.expectCacheErrors(c, 'Missing cache', 1);
expect(c.created).to.eql(c.errorTime);
const c = await cache.go('-internal', 'true', Cacheism.Status.onlyCache, async () => {
return 'live';
expect(await cache.store.isset('-internal/cache')).to.be(true);
const d = await cache.store.get('-internal/cache');
helpers.expectDataMiss(d, null, null);
helpers.expectDataErrors(d, 'Error: Missing cache', 1);
expect(d.created).to.eql(d.errorTime);
});
expect(c).to.be.a(Cacheism.Hit);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/true');
expect(c).to.have.property('cached', true);
expect(c).to.have.property('created');
expect(c.created).to.be.a(Date);
expect(c).to.have.property('data', 'cached');
expect(c).to.have.property('error', null);
expect(c).to.have.property('etag');
});
it('should return a Miss with no cache', async function () {
const c = await cache.go('-internal', 'nocache', Cacheism.Status.onlyCache, async () => {
return 'live';
describe('and having existing cache', async function () {
it('should return a Hit (cached value) on success', async function () {
mockdate.set('2000-11-22');
await cache.store.set(Cacheism.Data.fromResponse(
new Cacheism.Hit('-internal/cache', 'cached')
));
mockdate.reset();
const c = await cache.go('-internal', 'cache', Cacheism.Status.onlyCache, async () => {
return 'live';
});
helpers.expectCacheHit(c, true, 'cached');
helpers.expectCacheNoErrors(c);
expect(await cache.store.isset('-internal/cache')).to.be(true);
const d = await cache.store.get('-internal/cache');
helpers.expectDataHit(d, 'cached', c.etag);
helpers.expectDataNoErrors(d);
});
expect(c).to.be.a(Cacheism.Miss);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/nocache');
expect(c).to.have.property('error');
expect(c.error).to.be.an(Error);
expect(c.error).to.have.property('message', 'Missing cache');
it('should return a Hit (cached value) on error', async function () {
mockdate.set('2000-11-22');
await cache.store.set(Cacheism.Data.fromResponse(
new Cacheism.Hit('-internal/cache', 'cached')
));
mockdate.reset();
const c = await cache.go('-internal', 'cache', Cacheism.Status.onlyCache, async () => {
return 'live';
});
helpers.expectCacheHit(c, true, 'cached');
helpers.expectCacheNoErrors(c);
expect(await cache.store.isset('-internal/cache')).to.be(true);
const d = await cache.store.get('-internal/cache');
helpers.expectDataHit(d, 'cached', c.etag);
helpers.expectDataNoErrors(d);
});
});

@@ -253,0 +401,0 @@

const expect = require('expect.js');
const mockdate = require('mockdate');

@@ -6,4 +7,6 @@ const Cacheism = require('../lib/cacheism');

describe('memory', function() {
const helpers = require('./helpers');
describe.only('memory', function() {
beforeEach(function() {

@@ -20,52 +23,90 @@ // runs before each test in this block

it('should return a Hit with the live value', async function () {
const c = await cache.go('-internal', 'nocache', Cacheism.Status.onlyFresh, async () => {
return 'live';
describe('and no existing cache', async function () {
it('should return a Hit (live value) on success', async function () {
const c = await cache.go('-internal', 'cache', Cacheism.Status.onlyFresh, async () => {
return 'live';
});
helpers.expectCacheHit(c, false, 'live');
helpers.expectCacheNoErrors(c);
expect(await cache.store.isset('-internal/cache')).to.be(true);
const d = await cache.store.get('-internal/cache');
helpers.expectDataHit(d, 'live', c.etag);
helpers.expectDataNoErrors(d);
});
expect(c).to.be.a(Cacheism.Hit);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/nocache');
expect(c).to.have.property('cached', false);
expect(c).to.have.property('created');
expect(c.created).to.be.a(Date);
expect(c).to.have.property('data', 'live');
expect(c).to.have.property('error', null);
expect(c).to.have.property('etag');
});
it('should return a Miss on error', async function () {
let c, d, e;
for (e = 1; e < 3; e++) {
c = await cache.go('-internal', 'cache', Cacheism.Status.onlyFresh, async () => {
throw Error('cache error');
});
it('should return a Miss on error', async function () {
const c = await cache.go('-internal', 'nocache', Cacheism.Status.onlyFresh, async () => {
throw Error('cache error');
helpers.expectCacheMiss(c, false, null);
helpers.expectCacheErrors(c, 'Error: cache error', e);
expect(await cache.store.isset('-internal/cache')).to.be(true);
d = await cache.store.get('-internal/cache');
helpers.expectDataMiss(d, null);
helpers.expectDataErrors(d, 'Error: cache error', e);
}
});
expect(c).to.be.a(Cacheism.Miss);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/nocache');
expect(c).to.have.property('error');
expect(c.error).to.be.an(Error);
expect(c.error).to.have.property('message', 'cache error');
});
it('should update cache with successful live value', async function () {
const c = await cache.go('-internal', 'true', Cacheism.Status.onlyFresh, async () => {
return 'live';
describe('and having existing cache', async function () {
it('should return a Hit (live value) on success', async function () {
mockdate.set('2000-11-22');
await cache.store.set(Cacheism.Data.fromResponse(
new Cacheism.Hit('-internal/cache', 'cached')
));
mockdate.reset();
const c = await cache.go('-internal', 'cache', Cacheism.Status.onlyFresh, async () => {
return 'live';
});
helpers.expectCacheHit(c, false, 'live');
helpers.expectCacheNoErrors(c);
expect(await cache.store.isset('-internal/cache')).to.be(true);
const d = await cache.store.get('-internal/cache');
helpers.expectDataHit(d, 'live', c.etag);
helpers.expectDataNoErrors(d);
});
expect(c).to.be.a(Cacheism.Hit);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/true');
expect(c).to.have.property('cached', false);
expect(c).to.have.property('created');
expect(c.created).to.be.a(Date);
expect(c).to.have.property('data', 'live');
expect(c).to.have.property('error', null);
expect(c).to.have.property('etag');
it('should return a Miss on error', async function () {
mockdate.set('2000-11-22');
expect(cache.store.data).to.have.property('-internal/true');
await cache.store.set(Cacheism.Data.fromResponse(
new Cacheism.Hit('-internal/cache', 'cached')
));
const d = Cacheism.Data.parse(cache.store.data['-internal/true']);
expect(d).to.be.a(Cacheism.Data);
expect(d).to.have.property('data', 'live');
expect(d).to.have.property('etag', c.etag);
mockdate.reset();
let c, d, e;
for (e = 1; e < 3; e++) {
c = await cache.go('-internal', 'cache', Cacheism.Status.onlyFresh, async () => {
throw Error('cache error');
});
helpers.expectCacheMiss(c, false, null);
helpers.expectCacheErrors(c, 'Error: cache error', e);
expect(await cache.store.isset('-internal/cache')).to.be(true);
d = await cache.store.get('-internal/cache');
helpers.expectDataMiss(d, null);
helpers.expectDataErrors(d, 'Error: cache error', e);
}
});
});

@@ -77,82 +118,90 @@

it('should return a Miss on error with no cache', async function () {
const c = await cache.go('-internal', 'nocache', Cacheism.Status.cacheOnFail, async () => {
throw Error('cache error');
});
describe('and no existing cache', async function () {
expect(c).to.be.a(Cacheism.Miss);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/nocache');
expect(c).to.have.property('error');
expect(c.error).to.be.an(Error);
expect(c.error).to.have.property('message', 'cache error');
});
it('should return a Hit (live value) on success', async function () {
const c = await cache.go('-internal', 'cache', Cacheism.Status.cacheOnFail, async () => {
return 'live';
});
it('should return a Hit on error with cache', async function () {
cache.store.data['-internal/true'] = Cacheism.Data.fromHit(
new Cacheism.Hit('-internal/true', 'cached')
).stringify();
helpers.expectCacheHit(c, false, 'live');
helpers.expectCacheNoErrors(c);
const c = await cache.go('-internal', 'true', Cacheism.Status.cacheOnFail, async () => {
throw Error('cache error');
expect(await cache.store.isset('-internal/cache')).to.be(true);
const d = await cache.store.get('-internal/cache');
helpers.expectDataHit(d, 'live', c.etag);
helpers.expectDataNoErrors(d);
});
expect(c).to.be.a(Cacheism.Hit);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/true');
expect(c).to.have.property('cached', true);
expect(c).to.have.property('created');
expect(c.created).to.be.a(Date);
expect(c).to.have.property('data', 'cached');
expect(c).to.have.property('error');
expect(c.error).to.be.an(Error);
expect(c.error).to.have.property('message', 'cache error');
expect(c).to.have.property('etag');
});
it('should return a Miss on error', async function () {
let c, d, e;
for (e = 1; e < 3; e++) {
c = await cache.go('-internal', 'cache', Cacheism.Status.cacheOnFail, async () => {
throw Error('cache error');
});
it('should return a Hit with the live value with cache', async function () {
cache.store.data['-internal/true'] = Cacheism.Data.fromHit(
new Cacheism.Hit('-internal/true', 'cached')
).stringify();
helpers.expectCacheMiss(c, false, null);
helpers.expectCacheErrors(c, 'Error: cache error', e);
const c = await cache.go('-internal', 'true', Cacheism.Status.cacheOnFail, async () => {
return 'live';
expect(await cache.store.isset('-internal/cache')).to.be(true);
d = await cache.store.get('-internal/cache');
helpers.expectDataMiss(d, null, c.etag);
helpers.expectDataErrors(d, 'Error: cache error', e);
}
});
expect(c).to.be.a(Cacheism.Hit);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/true');
expect(c).to.have.property('cached', false);
expect(c).to.have.property('created');
expect(c.created).to.be.a(Date);
expect(c).to.have.property('data', 'live');
expect(c).to.have.property('error', null);
expect(c).to.have.property('etag');
});
it('should update cache with successful live value', async function () {
cache.store.data['-internal/true'] = Cacheism.Data.fromHit(
new Cacheism.Hit('-internal/true', 'cached')
).stringify();
describe('and having existing cache', async function () {
const c = await cache.go('-internal', 'true', Cacheism.Status.cacheOnFail, async () => {
return 'live';
it('should return a Hit (live value) on success', async function () {
mockdate.set('2000-11-22');
await cache.store.set(Cacheism.Data.fromResponse(
new Cacheism.Hit('-internal/cache', 'cached')
));
mockdate.reset();
const c = await cache.go('-internal', 'cache', Cacheism.Status.cacheOnFail, async () => {
return 'live';
});
helpers.expectCacheHit(c, false, 'live');
helpers.expectCacheNoErrors(c);
expect(await cache.store.isset('-internal/cache')).to.be(true);
const d = await cache.store.get('-internal/cache');
helpers.expectDataHit(d, 'live', c.etag);
helpers.expectDataNoErrors(d);
});
expect(c).to.be.a(Cacheism.Hit);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/true');
expect(c).to.have.property('cached', false);
expect(c).to.have.property('created');
expect(c.created).to.be.a(Date);
expect(c).to.have.property('data', 'live');
expect(c).to.have.property('error', null);
expect(c).to.have.property('etag');
it('should return a Hit (cached value) on error', async function () {
mockdate.set('2000-11-22');
expect(cache.store.data).to.have.property('-internal/true');
await cache.store.set(Cacheism.Data.fromResponse(
new Cacheism.Hit('-internal/cache', 'cached')
));
const d = Cacheism.Data.parse(cache.store.data['-internal/true']);
expect(d).to.be.a(Cacheism.Data);
expect(d).to.have.property('data', 'live');
expect(d).to.have.property('etag', c.etag);
mockdate.reset();
let c, d, e;
for (e = 1; e < 3; e++) {
c = await cache.go('-internal', 'cache', Cacheism.Status.cacheOnFail, async () => {
throw Error('cache error');
});
helpers.expectCacheHit(c, true, 'cached');
helpers.expectCacheErrors(c, 'Error: cache error', e);
expect(await cache.store.isset('-internal/cache')).to.be(true);
d = await cache.store.get('-internal/cache');
helpers.expectDataHit(d, 'cached', c.etag);
helpers.expectDataErrors(d, 'Error: cache error', e);
}
});
});

@@ -164,49 +213,90 @@

it('should return a Miss on error with no cache', async function () {
const c = await cache.go('-internal', 'nocache', Cacheism.Status.preferCache, async () => {
throw Error('cache error');
describe('and no existing cache', async function () {
it('should return a Hit (live value) on success', async function () {
const c = await cache.go('-internal', 'cache', Cacheism.Status.preferCache, async () => {
return 'live';
});
helpers.expectCacheHit(c, false, 'live');
helpers.expectCacheNoErrors(c);
expect(await cache.store.isset('-internal/cache')).to.be(true);
const d = await cache.store.get('-internal/cache');
helpers.expectDataHit(d, 'live', c.etag);
helpers.expectDataNoErrors(d);
});
expect(c).to.be.a(Cacheism.Miss);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/nocache');
expect(c).to.have.property('error');
expect(c.error).to.be.an(Error);
expect(c.error).to.have.property('message', 'cache error');
});
it('should return a Miss on error', async function () {
let c, d, e;
for (e = 1; e < 3; e++) {
c = await cache.go('-internal', 'cache', Cacheism.Status.preferCache, async () => {
throw Error('cache error');
});
it('should return a Hit with the cached value with cache', async function () {
cache.store.data['-internal/true'] = Cacheism.Data.fromHit(
new Cacheism.Hit('-internal/true', 'cached')
).stringify();
helpers.expectCacheMiss(c, false, null);
helpers.expectCacheErrors(c, 'Error: cache error', e);
const c = await cache.go('-internal', 'true', Cacheism.Status.preferCache, async () => {
return 'live';
expect(await cache.store.isset('-internal/cache')).to.be(true);
d = await cache.store.get('-internal/cache');
helpers.expectDataMiss(d, null, c.etag);
helpers.expectDataErrors(d, 'Error: cache error', e);
}
});
expect(c).to.be.a(Cacheism.Hit);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/true');
expect(c).to.have.property('cached', true);
expect(c).to.have.property('created');
expect(c.created).to.be.a(Date);
expect(c).to.have.property('data', 'cached');
expect(c).to.have.property('error', null);
expect(c).to.have.property('etag');
});
it('should return a Hit with the live value with no cache', async function () {
const c = await cache.go('-internal', 'true', Cacheism.Status.preferCache, async () => {
return 'live';
describe('and having existing cache', async function () {
it('should return a Hit (cached value) on success', async function () {
mockdate.set('2000-11-22');
await cache.store.set(Cacheism.Data.fromResponse(
new Cacheism.Hit('-internal/cache', 'cached')
));
mockdate.reset();
const c = await cache.go('-internal', 'cache', Cacheism.Status.preferCache, async () => {
return 'live';
});
helpers.expectCacheHit(c, true, 'cached');
helpers.expectCacheNoErrors(c);
expect(await cache.store.isset('-internal/cache')).to.be(true);
const d = await cache.store.get('-internal/cache');
helpers.expectDataHit(d, 'cached', c.etag);
helpers.expectDataNoErrors(d);
});
expect(c).to.be.a(Cacheism.Hit);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/true');
expect(c).to.have.property('cached', false);
expect(c).to.have.property('created');
expect(c.created).to.be.a(Date);
expect(c).to.have.property('data', 'live');
expect(c).to.have.property('error', null);
expect(c).to.have.property('etag');
it('should return a Hit (cached value) on error', async function () {
mockdate.set('2000-11-22');
await cache.store.set(Cacheism.Data.fromResponse(
new Cacheism.Hit('-internal/cache', 'cached')
));
mockdate.reset();
let c, d, e;
for (e = 1; e < 3; e++) {
c = await cache.go('-internal', 'cache', Cacheism.Status.preferCache, async () => {
throw Error('cache error');
});
helpers.expectCacheHit(c, true, 'cached');
helpers.expectCacheNoErrors(c);
expect(await cache.store.isset('-internal/cache')).to.be(true);
d = await cache.store.get('-internal/cache');
helpers.expectDataHit(d, 'cached', c.etag);
helpers.expectDataNoErrors(d);
}
});
});

@@ -217,46 +307,88 @@

describe('when status=onlyCache', function () {
it('should return a Miss on error with no cache', async function () {
const c = await cache.go('-internal', 'nocache', Cacheism.Status.onlyCache, async () => {
throw Error('cache error');
describe('and no existing cache', async function () {
it('should return a Miss on success', async function () {
const c = await cache.go('-internal', 'cache', Cacheism.Status.onlyCache, async () => {
return 'live';
});
helpers.expectCacheMiss(c, false, null);
helpers.expectCacheErrors(c, 'Error: Missing cache', 1);
expect(await cache.store.isset('-internal/cache')).to.be(true);
const d = await cache.store.get('-internal/cache');
helpers.expectDataMiss(d, null, null);
helpers.expectDataErrors(d, 'Error: Missing cache', 1);
});
expect(c).to.be.a(Cacheism.Miss);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/nocache');
expect(c).to.have.property('error');
expect(c.error).to.be.an(Error);
expect(c.error).to.have.property('message', 'Missing cache');
});
it('should return a Miss on error', async function () {
let c, d, e;
for (e = 1; e < 3; e++) {
c = await cache.go('-internal', 'cache', Cacheism.Status.onlyCache, async () => {
throw Error('cache error');
});
it('should return a Hit with the cached value with cache', async function () {
cache.store.data['-internal/true'] = Cacheism.Data.fromHit(
new Cacheism.Hit('-internal/true', 'cached')
).stringify();
helpers.expectCacheMiss(c, false, null);
helpers.expectCacheErrors(c, 'Error: Missing cache', e);
const c = await cache.go('-internal', 'true', Cacheism.Status.onlyCache, async () => {
return 'live';
expect(await cache.store.isset('-internal/cache')).to.be(true);
d = await cache.store.get('-internal/cache');
helpers.expectDataMiss(d, null, null);
helpers.expectDataErrors(d, 'Error: Missing cache', e);
}
});
expect(c).to.be.a(Cacheism.Hit);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/true');
expect(c).to.have.property('cached', true);
expect(c).to.have.property('created');
expect(c.created).to.be.a(Date);
expect(c).to.have.property('data', 'cached');
expect(c).to.have.property('error', null);
expect(c).to.have.property('etag');
});
it('should return a Miss with no cache', async function () {
const c = await cache.go('-internal', 'nocache', Cacheism.Status.onlyCache, async () => {
return 'live';
describe('and having existing cache', async function () {
it('should return a Hit (cached value) on success', async function () {
mockdate.set('2000-11-22');
await cache.store.set(Cacheism.Data.fromResponse(
new Cacheism.Hit('-internal/cache', 'cached')
));
mockdate.reset();
const c = await cache.go('-internal', 'cache', Cacheism.Status.onlyCache, async () => {
return 'live';
});
helpers.expectCacheHit(c, true, 'cached');
helpers.expectCacheNoErrors(c);
expect(await cache.store.isset('-internal/cache')).to.be(true);
const d = await cache.store.get('-internal/cache');
helpers.expectDataHit(d, 'cached', c.etag);
helpers.expectDataNoErrors(d);
});
expect(c).to.be.a(Cacheism.Miss);
expect(c).to.have.property('version', 2);
expect(c).to.have.property('cacheName', '-internal/nocache');
expect(c).to.have.property('error');
expect(c.error).to.be.an(Error);
expect(c.error).to.have.property('message', 'Missing cache');
it('should return a Hit (cached value) on error', async function () {
mockdate.set('2000-11-22');
await cache.store.set(Cacheism.Data.fromResponse(
new Cacheism.Hit('-internal/cache', 'cached')
));
mockdate.reset();
const c = await cache.go('-internal', 'cache', Cacheism.Status.onlyCache, async () => {
return 'live';
});
helpers.expectCacheHit(c, true, 'cached');
helpers.expectCacheNoErrors(c);
expect(await cache.store.isset('-internal/cache')).to.be(true);
const d = await cache.store.get('-internal/cache');
helpers.expectDataHit(d, 'cached', c.etag);
helpers.expectDataNoErrors(d);
});
});

@@ -263,0 +395,0 @@