Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

mycache

Package Overview
Dependencies
Maintainers
1
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mycache - npm Package Compare versions

Comparing version 0.5.0 to 1.0.0

es/index.js

5

CHANGELOG.md

@@ -7,2 +7,7 @@ # Changelog

## [1.0.0] - 2018-12-22
### Changed
- Use new pattern to write logical
- Update package and use webpack
## [0.5.0] - 2018-06-25

@@ -9,0 +14,0 @@ ### Changed

80

package.json
{
"name": "mycache",
"version": "0.5.0",
"version": "1.0.0",
"description": "A Cache library",
"keywords": [
"cache",
"indexedDB",
"localstorage",
"localStorage",
"sessionStorage",
"memoryStore",
"javascript"

@@ -21,8 +22,10 @@ ],

"src",
"dist"
"umd",
"es",
"lib"
],
"main": "dist/cjs",
"module": "dist/esm/mycache.prod.min.js",
"browser": "dist/umd/mycache.prod.min.js",
"types": "src/index",
"main": "lib/index.js",
"module": "es/index.js",
"browser": "umd/mycache.js",
"types": "es/typings.d.ts",
"repository": {

@@ -33,32 +36,42 @@ "type": "git",

"scripts": {
"build": "cross-env rimraf lib build dist && tsc && rollup -c && node ./scripts/bundles",
"dev": "tsc --watch src",
"lint": "tslint src/*",
"prepublish": "npm run build",
"build": "npm run build:ts && npm run build:cjs && npm run build:umd",
"build:ts": "cross-env rimraf es && tsc",
"build:cjs": "cross-env rimraf lib && cross-env NODE_ENV=commonjs BABEL_ENV=cjs babel ./es -d lib",
"build:umd": "cross-env rimraf umd && cross-env BABEL_ENV=umd webpack --config webpack.config.js",
"clean": "cross-env rimraf lib build dist",
"lint": "tslint -c src/**/*",
"test": "npm run build && nyc ava",
"report": "nyc report --reporter=html"
},
"dependencies": {
"localforage": "^1.7.2"
},
"devDependencies": {
"@types/node": "^9.6.0",
"@babel/cli": "^7.1.0",
"@babel/core": "^7.0.0",
"@babel/plugin-proposal-class-properties": "^7.0.0",
"@babel/plugin-proposal-export-default-from": "^7.0.0",
"@babel/plugin-proposal-export-namespace-from": "^7.0.0",
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
"@babel/polyfill": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"@babel/register": "^7.0.0",
"@babel/runtime": "^7.0.0",
"@types/node": "^10.1.4",
"ava": "^0.25.0",
"babel-preset-es2015": "^6.24.1",
"babel-register": "^6.26.0",
"babel-loader": "^8.0.0",
"babel-plugin-lodash": "^3.3.0",
"coveralls": "^3.0.0",
"cross-env": "^5.1.4",
"husky": "^0.14.3",
"lint-staged": "^7.0.4",
"nyc": "^11.6.0",
"puppeteer": "^1.3.0",
"cross-env": "^5.2.0",
"husky": "^1.3.0",
"lint-staged": "^8.0.0",
"nyc": "^13.0.0",
"prettier": "^1.15.3",
"puppeteer": "^1.11.0",
"rimraf": "^2.6.2",
"rollup": "^0.57.1",
"rollup-plugin-commonjs": "^9.1.0",
"rollup-plugin-node-resolve": "^3.3.0",
"rollup-plugin-replace": "^2.0.0",
"rollup-plugin-uglify": "^3.0.0",
"sinon": "^4.5.0",
"tslint": "^5.9.1",
"typescript": "^2.8.1",
"uglify-es": "^3.3.10"
"tslint": "^5.10.0",
"typescript": "^3.1.0",
"webpack": "^4.20.0",
"webpack-bundle-analyzer": "^3.0.3",
"webpack-cli": "^3.1.0"
},

@@ -87,10 +100,5 @@ "husky": {

"require": [
"babel-register"
],
"babel": {
"presets": [
"es2015"
]
}
"@babel/register"
]
}
}

@@ -8,6 +8,4 @@ # Mycache

Mycache is a cache library enhanced front end local cache, and provides two kinds of cache: persist cache and memory cache.
Mycache is a cache library enhanced front end local cache. It can provide 4 stores, includes indexedDB, localStorage, sessionStorage and memorayStore.
The persist cache use two park to store, localStorage is responsible for store the meta info, and indexeddb is responsible for store value.
## Installation

@@ -25,5 +23,5 @@ NPM is the easiest and fastest way to get started using Mycache.

```js
import { Persist } from 'mycache';
import Mycache from 'mycache';
const persist = new Persist();
const mycache = new Mycache();
```

@@ -34,10 +32,8 @@

```js
import { Persist } from 'mycache';
import Mycache from 'mycache';
const persist = new Persist();
const mycache = new Mycache();
async function persist() {
await persist.set('key', 'value');
return await persist.get('key');
}
await mycache.set('key', 'value');
const val = await mycache.get('key');
```

@@ -47,49 +43,7 @@

MemCache Config:
```js
import { MemCache } from 'mycache';
import Mycache from 'mycache';
const cache = new MemCache({
const mycache = new Mycache({
name: 'mycache', // name prefix of key
});
```
MemCache API:
```ts
// get value of key
function get(key: string): Promise<any> {}
// get all value of keys
function gets() : Promise<any> {}
// set key value and expire time
function set<T>(key: string, value: T, expire: number | Date = -1): Promise<T> {}
// append key value and expire time
function append<T>(key: string, value: T, expire: number | Date = -1): Promise<T> {}
// if the key has in local
function has(key: string): Promise<boolean> {}
// remove key
function remove(key: string): Promise<void> {}
// get all keys
function keys(): Promise<string[]> {}
// clear all keys
function clear(): Promise<void> {}
// the length of all keys
function length(): Promise<number> {}
// each all keys by callback
function each(iterator: (value: any, key: string, iterationNumber: number) => void): Promise<boolean> {}
// if the key is expired
function isExpired(key: string): Promise<boolean> {}
```
Persist Config:
```js
import { Persist } from 'mycache';
const persist = new Persist({
name: 'mycache', // name prefix of key
storeName: 'persist', // The name of the datastore
isCompress: false, // if enable string compress
valueMaxLength: 20 * 1000, // max length of value
oldItemsCount: 0.2, // this count of old items

@@ -99,3 +53,3 @@ });

Persist API:
Mycache API:

@@ -127,4 +81,2 @@ ```ts

function getExpiredKeys(): Promise<string[]> {}
// if the key is overlength
function isOverLength(key: string): Promise<boolean> {}
// get all overlength keys

@@ -135,3 +87,3 @@ function getOverLengthKeys(): Promise<string[]> {}

// get items by sorted
function getSortedItems(): Promise<typed.IPersistMetaDataMap[]> {}
function getSortedItems(): Promise<typed.IMycacheMetaDataMap[]> {}
```

@@ -138,0 +90,0 @@

@@ -1,9 +0,360 @@

import MemCache from './MemCache/MemCache';
import Persist from './Persist/Persist';
import * as typed from './typed';
// import * as localForage from 'localforage';
import { StorageStore } from './StorageStore';
import * as typed from './typings';
import * as utils from './Utils/utils';
export {
typed,
Persist,
MemCache,
const DEFAULT_CONFIG: typed.IMycacheConfig = {
oldItemsCount: 0.2,
};
interface ITempCache {
count: number;
items: typed.IMycacheMetaDataMap;
}
class Mycache {
private cacheConfig: typed.IMycacheConfig;
private cacheInstance: StorageStore;
constructor(config: typed.IMycacheConfig = {}) {
this.cacheConfig = utils.extend(DEFAULT_CONFIG, config);
const stores = ['indexedDB', 'localStorage'];
this.cacheInstance = new StorageStore(stores, {
prefix: this.cacheConfig.name,
});
}
public async getOldKeys(): Promise<string[]> {
try {
const length = await this.length();
const oldItemsCount = this.cacheConfig.oldItemsCount;
const oldCount =
oldItemsCount < 1
? Math.floor(length * oldItemsCount)
: Math.floor(oldItemsCount);
const getkeys: string[] = [];
const cacheSorted = await this.getSortedItems();
const sortedCache = cacheSorted.reverse();
for (let i = 0; i < sortedCache.length; i++) {
const value = sortedCache[i];
if (i < oldCount) {
getkeys.push(value.key);
}
}
return Promise.resolve(getkeys);
} catch (err) {
return Promise.reject(err);
}
}
public async getExpiredKeys(): Promise<string[]> {
try {
const getkeys: string[] = [];
const keys = await this.keys();
for (const key of keys) {
const isExpired = await this.isExpired(key);
if (isExpired) {
getkeys.push(key);
}
}
return Promise.resolve(getkeys);
} catch (err) {
return Promise.reject(err);
}
}
public async isExpired(
key: string,
currentTime: number = new Date().getTime()
): Promise<boolean> {
try {
const res = await this.get(key);
if (res && res.expire) {
return Promise.resolve(this.expiredVaule(res.expire, currentTime));
} else {
return Promise.resolve(false);
}
} catch (err) {
return Promise.reject(err);
}
}
public async get(
key: string,
currentTime: number = new Date().getTime()
): Promise<any> {
try {
const res: typed.IMycacheDataMapValue = await this.cacheInstance.get(key);
if (!res) {
return Promise.resolve(null);
}
if (
res.expire !== undefined &&
res.now !== undefined &&
res.count !== undefined
) {
const isExpired = this.expiredVaule(res.expire, currentTime);
if (isExpired) {
await this.remove(key);
return Promise.resolve(null);
}
return Promise.resolve(res.value);
}
// If don't mycache init, return value directly
return Promise.resolve(res);
} catch (err) {
return Promise.reject(err);
}
}
public async gets(keys: string[]): Promise<any> {
try {
const res = [];
for (const key of keys) {
res.push(await this.get(key));
}
return Promise.resolve(res);
} catch (err) {
return Promise.reject(err);
}
}
public async set<T>(
key: string,
value: T,
expire: number | Date = -1
): Promise<T> {
try {
const res = await this.get(key);
// If don't use mycache init, return value directly
if (res && !res.expire && !res.count && !res.now) {
return this.cacheInstance.set(key, value);
}
const now = new Date().getTime();
let expireTime;
if (utils.isDate(expire)) {
expireTime = (expire as Date).getTime();
} else if (utils.isNumber(expire) && expire > 0) {
// expire number is second
expireTime = now + (expire as number) * 1000;
} else {
expireTime = -1;
}
let count = 0;
if (res && res.count !== undefined) {
count = res.count + 1;
}
let realValue;
if (value) {
realValue = {
value,
now,
count,
expire: expireTime,
};
} else {
realValue = {
...res,
now,
count,
};
}
return this.cacheInstance.set(key, realValue);
} catch (err) {
if (err.name.toUpperCase().indexOf('QUOTA') >= 0) {
await this.clearKeys();
return Promise.resolve(null);
}
return Promise.reject(err);
}
}
public async append<T>(
key: string,
value: T,
expire: number | Date = -1
): Promise<T> {
try {
const res = await this.get(key);
if (!res) {
return this.set(key, value, expire);
}
expire = expire ? expire : res.expire;
if (utils.isArray(value) && utils.isArray(res)) {
value = (res as any).concat(value);
} else if (utils.isPlainObject(value) && utils.isPlainObject(res)) {
value = utils.extend(res, value);
}
return this.set(key, value, expire);
} catch (err) {
if (err.name.toUpperCase().indexOf('QUOTA') >= 0) {
await this.clearKeys();
return Promise.resolve(null);
}
return Promise.reject(err);
}
}
public async has(key: string): Promise<boolean> {
try {
const res = await this.get(key);
if (res) {
return Promise.resolve(true);
} else {
return Promise.resolve(false);
}
} catch (err) {
return Promise.reject(err);
}
}
public async remove(key: string): Promise<void> {
try {
await this.cacheInstance.remove(key);
return Promise.resolve();
} catch (err) {
return Promise.reject(err);
}
}
public async clear(): Promise<void> {
try {
await this.cacheInstance.clear();
return Promise.resolve();
} catch (err) {
return Promise.reject(err);
}
}
public keys(): Promise<string[]> {
return this.cacheInstance.keys();
}
public length(): Promise<number> {
return this.cacheInstance.length();
}
public async each(
iterator: (value: any, key: string, num: number) => void
): Promise<boolean> {
try {
const cache = await this.keys();
for (let i = 0; i < cache.length; i++) {
const key = cache[i];
const value = await this.get(key);
if (iterator) {
await iterator(value, key, i);
}
}
return Promise.resolve(true);
} catch (err) {
return Promise.reject(err);
}
}
public async getSortedItems(): Promise<typed.IMycacheMetaDataMap[]> {
try {
const keys = await this.keys();
const cache: typed.IMycacheMetaDataMap[] = [];
for (const key of keys) {
const value = await this.get(key);
cache.push({ ...value, key });
}
const countGroup: any = {};
for (const item of cache) {
if (!countGroup[item.count]) {
countGroup[item.count] = [];
}
countGroup[item.count].push(item);
}
let sortCountSet: ITempCache[] = [];
for (const i in countGroup) {
if (countGroup.hasOwnProperty(i)) {
// sort by now desc
sortCountSet.push({
count: parseInt(i, 10),
items: countGroup[i].sort(
(a: typed.IMycacheMetaDataMap, b: typed.IMycacheMetaDataMap) =>
b.now - a.now
),
});
}
}
// sort by count desc
sortCountSet = sortCountSet.sort(
(a: ITempCache, b: ITempCache) => b.count - a.count
);
let finalCache: typed.IMycacheMetaDataMap[] = [];
for (const res of sortCountSet) {
finalCache = finalCache.concat(res.items);
}
return Promise.resolve(finalCache);
} catch (err) {
return Promise.reject(err);
}
}
private expiredVaule(expire: number, currentTime: number): boolean {
return expire && expire > 0 && expire < currentTime;
}
private async clearKeys(): Promise<boolean> {
try {
let keys = await this.getExpiredKeys();
keys.concat(await this.getOldKeys());
keys = keys.sort().filter((item, index, array) => {
return !index || item !== array[index - 1];
});
for (const key of keys) {
await this.remove(key);
}
return Promise.resolve(true);
} catch (err) {
return Promise.reject(err);
}
}
}
module.exports = Mycache;

@@ -18,16 +18,24 @@ const toString = Object.prototype.toString;

function isObjectObject(o: any) {
return isObject(o) === true
&& Object.prototype.toString.call(o) === '[object Object]';
return (
isObject(o) === true &&
Object.prototype.toString.call(o) === '[object Object]'
);
}
function isPlainObject(o: any) {
if (isObjectObject(o) === false) { return false; }
if (isObjectObject(o) === false) {
return false;
}
// If has modified constructor
const ctor = o.constructor;
if (typeof ctor !== 'function') { return false; }
if (typeof ctor !== 'function') {
return false;
}
// If has modified prototype
const prot = ctor.prototype;
if (isObjectObject(prot) === false) { return false; }
if (isObjectObject(prot) === false) {
return false;
}

@@ -44,3 +52,5 @@ // If constructor does not have an Object-specific method

function extend(target: any, source: any) {
if (source === null || typeof source !== 'object') { return target; }
if (source === null || typeof source !== 'object') {
return target;
}

@@ -57,5 +67,9 @@ const keys = Object.keys(source);

function omit(obj: any, props: any) {
if (!isObject(obj)) { return {}; }
if (!isObject(obj)) {
return {};
}
if (typeof props === 'string') { props = [props]; }
if (typeof props === 'string') {
props = [props];
}

@@ -66,3 +80,3 @@ const keys = Object.keys(obj);

for (const key of keys) {
if (!props || (props.indexOf(key) === -1)) {
if (!props || props.indexOf(key) === -1) {
res[key] = obj[key];

@@ -75,19 +89,2 @@ }

// http://www.alloyteam.com/2013/12/js-calculate-the-number-of-bytes-occupied-by-a-string/
function utf16ByteLength(str: string): number {
let total = 0;
let charCode;
for (let i = 0; i < str.length; i++) {
charCode = str.charCodeAt(i);
if (charCode <= 0xffff) {
total += 2;
} else {
total += 4;
}
}
return total;
}
export { isDate, isNumber, isArray, isPlainObject, extend, omit, utf16ByteLength };
export { isDate, isNumber, isArray, isPlainObject, extend, omit };
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