key-file-storage
Advanced tools
Comparing version 2.2.3 to 2.2.4
15
index.js
@@ -5,7 +5,16 @@ "use strict"; | ||
var key_file_storage_1 = require("./src/key-file-storage"); | ||
function keyFileStorage(kfsPath, cacheConfig) { | ||
var cache = create_cache_1["default"](cacheConfig); | ||
var kfs = key_file_storage_1["default"](kfsPath, cache); | ||
/** | ||
* Returns an instance of `key-file-storage` to access the file system. | ||
* @param path The root storage path on the file system: | ||
* * For example `'./the/path/to/data'` | ||
* @param caching The selected cache configuration: | ||
* * `true` *(By default)* for unlimited cache, | ||
* * `false` to disable caching, | ||
* * `n: number` to cache the latest **n** accessed keys. | ||
*/ | ||
function keyFileStorage(path, caching) { | ||
var cache = create_cache_1["default"](caching); | ||
var kfs = key_file_storage_1["default"](path, cache); | ||
return kfs; | ||
} | ||
exports["default"] = keyFileStorage; |
17
index.ts
import createCache from './src/create-cache'; | ||
import createKfs from './src/key-file-storage'; | ||
import createKfs, { KeyFileStorage } from './src/key-file-storage'; | ||
export default function keyFileStorage(kfsPath: string, cacheConfig?: number | boolean) { | ||
var cache = createCache(cacheConfig); | ||
var kfs = createKfs(kfsPath, cache); | ||
/** | ||
* Returns an instance of `key-file-storage` to access the file system. | ||
* @param path The root storage path on the file system: | ||
* * For example `'./the/path/to/data'` | ||
* @param caching The selected cache configuration: | ||
* * `true` *(By default)* for unlimited cache, | ||
* * `false` to disable caching, | ||
* * `n: number` to cache the latest **n** accessed keys. | ||
*/ | ||
export default function keyFileStorage(path: string, caching?: number | boolean): KeyFileStorage { | ||
var cache = createCache(caching); | ||
var kfs = createKfs(path, cache); | ||
return kfs; | ||
} |
{ | ||
"name": "key-file-storage", | ||
"version": "2.2.3", | ||
"version": "2.2.4", | ||
"description": "Simple key-value storage directly on file system, maps each key to a separate file.", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -1,126 +0,149 @@ | ||
'use strict'; | ||
"use strict"; | ||
exports.__esModule = true; | ||
function createCache(cacheConfig) { | ||
if (cacheConfig === true || typeof cacheConfig === 'undefined') { | ||
// Unlimited cache by default | ||
return createCache_Unlimited(cacheConfig); | ||
} else if (cacheConfig === false) { | ||
// No cache | ||
return createCache_NoCache(cacheConfig); | ||
} else if (typeof cacheConfig === 'number' && cacheConfig > 0) { | ||
// Limited cache by the number of keys | ||
return createCache_LimitedByKeyCount(cacheConfig); | ||
} else { | ||
throw new Error('Invalid cache config.'); | ||
} | ||
function createCache_Unlimited(cacheConfig) { | ||
return new Proxy( | ||
{ | ||
if (cacheConfig === true || typeof cacheConfig === 'undefined') { | ||
// Unlimited cache by default | ||
return createCache_Unlimited(cacheConfig); | ||
} | ||
else if (cacheConfig === false) { | ||
// No cache | ||
return createCache_NoCache(cacheConfig); | ||
} | ||
else if (typeof cacheConfig === 'number' && cacheConfig > 0) { | ||
// Limited cache by the number of keys | ||
return createCache_LimitedByKeyCount(cacheConfig); | ||
} | ||
else { | ||
throw new Error('Invalid cache config.'); | ||
} | ||
function createCache_Unlimited(cacheConfig) { | ||
return new Proxy({ | ||
/*CACHE*/ | ||
}, | ||
{ | ||
set: function(target, property, value, receiver) { | ||
return (target[property] = value); | ||
}, | ||
get: function(target, property, receiver) { | ||
return undefined; | ||
}, | ||
deleteProperty: function(target, property) { | ||
return true; | ||
}, | ||
has: function(target, property) { | ||
return false; | ||
}, | ||
}, | ||
); | ||
} | ||
function createCache_NoCache(cacheConfig) { | ||
return new Proxy( | ||
{ | ||
}, { | ||
set: function (target, property, value, receiver) { | ||
property in target || cleanUpCachedCollections(target, property); | ||
target[property] = value; | ||
return true; | ||
}, | ||
get: function (target, property, receiver) { | ||
return target[property]; | ||
}, | ||
deleteProperty: function (target, property) { | ||
if (property === '*') { | ||
Object.keys(target).forEach(function (key) { return delete target[key]; }); | ||
return true; | ||
} | ||
property in target && cleanUpCachedCollections(target, property); | ||
return delete target[property]; | ||
}, | ||
has: function (target, property) { | ||
return property in target; | ||
} | ||
}); | ||
function cleanUpCachedCollections(target, property) { | ||
var path = String(property); | ||
if (path.slice(-1) === '/') | ||
return; | ||
var parts = path.split('/'); | ||
var collections = parts.map(function (part, index) { return parts.slice(0, index).join('/') + '/'; }); | ||
collections.forEach(function (collection) { return delete target[collection]; }); | ||
} | ||
} | ||
function createCache_NoCache(cacheConfig) { | ||
return new Proxy({ | ||
/*CACHE*/ | ||
}, | ||
{ | ||
set: function(target, property, value, receiver) { | ||
return value; | ||
}, | ||
get: function(target, property, receiver) { | ||
return undefined; | ||
}, | ||
deleteProperty: function(target, property) { | ||
return true; | ||
}, | ||
has: function(target, property) { | ||
return false; | ||
}, | ||
}, | ||
); | ||
} | ||
function createCache_LimitedByKeyCount(cacheConfig) { | ||
var keyNumber = Math.ceil(cacheConfig), | ||
keys = Array(keyNumber), | ||
nextKeyIndex = 0, | ||
keyIndex; | ||
return new Proxy( | ||
{ | ||
}, { | ||
set: function (target, property, value, receiver) { | ||
return true; | ||
}, | ||
get: function (target, property, receiver) { | ||
return undefined; | ||
}, | ||
deleteProperty: function (target, property) { | ||
return true; | ||
}, | ||
has: function (target, property) { | ||
return false; | ||
} | ||
}); | ||
} | ||
function createCache_LimitedByKeyCount(cacheConfig) { | ||
var keyNumber = Math.ceil(cacheConfig), keys = Array(keyNumber), nextKeyIndex = 0, keyIndex; | ||
return new Proxy({ | ||
/*CACHE*/ | ||
}, | ||
{ | ||
set: function(target, property, value, receiver) { | ||
updateKeys(target, property, 'SET'); | ||
return (target[property] = value); | ||
}, | ||
get: function(target, property, receiver) { | ||
updateKeys(target, property, 'GET'); | ||
return target[property]; | ||
}, | ||
deleteProperty: function(target, property) { | ||
if (property === '*') { | ||
keys = Array(keyNumber); | ||
nextKeyIndex = 0; | ||
return true; | ||
} | ||
updateKeys(target, property, 'DELETE'); | ||
return delete target[property]; | ||
}, | ||
has: function(target, property) { | ||
return keys.indexOf(property) >= 0; | ||
}, | ||
}, | ||
); | ||
function realIndex(i) { | ||
return (i + keyNumber) % keyNumber; | ||
} | ||
function updateKeys(target, property, mode) { | ||
keyIndex = keys.indexOf(property); | ||
if (keyIndex < 0) { | ||
// Does not exist | ||
mode === 'SET' && addKey(); | ||
} else if (keyIndex === realIndex(nextKeyIndex - 1)) { | ||
// The latest key | ||
mode === 'DELETE' && removeKey(); | ||
} else { | ||
// Otherwise | ||
removeKey(); | ||
mode === 'DELETE' || addKey(); | ||
} | ||
function removeKey() { | ||
while (keyIndex !== nextKeyIndex && keys[keyIndex]) { | ||
keys[keyIndex] = keys[realIndex(keyIndex - 1)]; | ||
keyIndex = realIndex(keyIndex - 1); | ||
}, { | ||
set: function (target, property, value, receiver) { | ||
if (!keys.includes(property)) { | ||
keys | ||
.filter(function (key) { return key === '/' || (key.slice(-1) === '/' && String(property).indexOf(key) === 0); }) | ||
.forEach(function (key) { | ||
updateKeys(target, key, 'DELETE'); | ||
delete target[key]; | ||
}); | ||
} | ||
updateKeys(target, property, 'SET'); | ||
target[property] = value; | ||
return true; | ||
}, | ||
get: function (target, property, receiver) { | ||
updateKeys(target, property, 'GET'); | ||
return target[property]; | ||
}, | ||
deleteProperty: function (target, property) { | ||
if (property === '*') { | ||
keys = Array(keyNumber); | ||
nextKeyIndex = 0; | ||
return true; | ||
} | ||
if (keys.includes(property)) { | ||
keys | ||
.filter(function (key) { return key === '/' || (key.slice(-1) === '/' && String(property).indexOf(key) === 0); }) | ||
.forEach(function (key) { | ||
updateKeys(target, key, 'DELETE'); | ||
delete target[key]; | ||
}); | ||
} | ||
updateKeys(target, property, 'DELETE'); | ||
return delete target[property]; | ||
}, | ||
has: function (target, property) { | ||
return keys.indexOf(property) >= 0; | ||
} | ||
}); | ||
function realIndex(i) { | ||
return (i + keyNumber) % keyNumber; | ||
} | ||
keys[nextKeyIndex] = undefined; | ||
} | ||
function addKey() { | ||
if (keys[nextKeyIndex] !== property) { | ||
if (keys[nextKeyIndex] !== undefined) delete target[keys[nextKeyIndex]]; | ||
keys[nextKeyIndex] = property; | ||
function updateKeys(target, property, mode) { | ||
keyIndex = keys.indexOf(property); | ||
if (keyIndex < 0) { | ||
// Does not exist | ||
mode === 'SET' && addKey(); | ||
} | ||
else if (keyIndex === realIndex(nextKeyIndex - 1)) { | ||
// The latest key | ||
mode === 'DELETE' && removeKey(); | ||
} | ||
else { | ||
// Otherwise | ||
removeKey(); | ||
mode === 'DELETE' || addKey(); | ||
} | ||
function removeKey() { | ||
while (keyIndex !== nextKeyIndex && keys[keyIndex]) { | ||
keys[keyIndex] = keys[realIndex(keyIndex - 1)]; | ||
keyIndex = realIndex(keyIndex - 1); | ||
} | ||
keys[nextKeyIndex] = undefined; | ||
} | ||
function addKey() { | ||
if (keys[nextKeyIndex] !== property) { | ||
if (keys[nextKeyIndex] !== undefined) | ||
delete target[keys[nextKeyIndex]]; | ||
keys[nextKeyIndex] = property; | ||
} | ||
nextKeyIndex = realIndex(nextKeyIndex + 1); | ||
} | ||
} | ||
nextKeyIndex = realIndex(nextKeyIndex + 1); | ||
} | ||
} | ||
} | ||
} | ||
exports['default'] = createCache; | ||
exports["default"] = createCache; |
@@ -1,2 +0,6 @@ | ||
export default function createCache(cacheConfig?: number | boolean) { | ||
export interface KfsCache { | ||
[key: string]: any; | ||
} | ||
export default function createCache(cacheConfig?: number | boolean): KfsCache { | ||
if (cacheConfig === true || typeof cacheConfig === 'undefined') { | ||
@@ -23,3 +27,4 @@ // Unlimited cache by default | ||
property in target || cleanUpCachedCollections(target, property); | ||
return ((target as any)[property] = value); | ||
(target as any)[property] = value; | ||
return true; | ||
}, | ||
@@ -62,3 +67,3 @@ | ||
set: function(target, property, value, receiver) { | ||
return value; | ||
return true; | ||
}, | ||
@@ -102,3 +107,4 @@ | ||
updateKeys(target, property, 'SET'); | ||
return ((target as any)[property] = value); | ||
(target as any)[property] = value; | ||
return true; | ||
}, | ||
@@ -105,0 +111,0 @@ |
@@ -1,269 +0,288 @@ | ||
'use strict'; | ||
"use strict"; | ||
exports.__esModule = true; | ||
var fs_extra_1 = require('fs-extra'); | ||
var path_1 = require('path'); | ||
var fs_extra_1 = require("fs-extra"); | ||
var path_1 = require("path"); | ||
var isValidPath = require('is-valid-path'); | ||
var recurFs = require('recur-fs'); | ||
function keyFileBasic(kfsPath, cache) { | ||
kfsPath = kfsPath || __dirname; // Current working folder by default. | ||
kfsPath = String(kfsPath); | ||
if (!isValidPath(kfsPath)) { | ||
throw new Error('Invalid stroage path.'); | ||
} | ||
return { | ||
// Synchronous | ||
setSync: setSync, | ||
getSync: getSync, | ||
deleteSync: deleteSync, | ||
clearSync: clearSync, | ||
hasSync: hasSync, | ||
// Asynchronous | ||
setAsync: setAsync, | ||
getAsync: getAsync, | ||
deleteAsync: deleteAsync, | ||
clearAsync: clearAsync, | ||
hasAsync: hasAsync, | ||
// Iterate | ||
querySync: querySync, | ||
queryAsync: queryAsync, | ||
}; | ||
function setSync(key, value) { | ||
if (value === undefined) { | ||
return deleteSync(key); | ||
kfsPath = kfsPath || __dirname; // Current working folder by default. | ||
kfsPath = String(kfsPath); | ||
if (!isValidPath(kfsPath)) { | ||
throw new Error('Invalid stroage path.'); | ||
} | ||
key = validizeKey(key); | ||
var file = path_1.join(kfsPath, key); | ||
fs_extra_1.outputJsonSync(file, value); | ||
return (cache[key] = value); | ||
} | ||
function getSync(key) { | ||
key = validizeKey(key); | ||
if (key in cache) { | ||
return cache[key]; | ||
return { | ||
// Synchronous | ||
setSync: setSync, | ||
getSync: getSync, | ||
deleteSync: deleteSync, | ||
clearSync: clearSync, | ||
hasSync: hasSync, | ||
// Asynchronous | ||
setAsync: setAsync, | ||
getAsync: getAsync, | ||
deleteAsync: deleteAsync, | ||
clearAsync: clearAsync, | ||
hasAsync: hasAsync, | ||
// Iterate | ||
querySync: querySync, | ||
queryAsync: queryAsync | ||
}; | ||
function setSync(key, value) { | ||
if (value === undefined) { | ||
return deleteSync(key); | ||
} | ||
key = validizeKey(key); | ||
var file = path_1.join(kfsPath, key); | ||
fs_extra_1.outputJsonSync(file, value); | ||
return (cache[key] = value); | ||
} | ||
var file = path_1.join(kfsPath, key); | ||
try { | ||
var status = fs_extra_1.statSync(file); | ||
if (!status || !status.isFile()) { | ||
return (cache[key] = null); | ||
} | ||
} catch (err) { | ||
return (cache[key] = null); | ||
function getSync(key) { | ||
key = validizeKey(key); | ||
if (key in cache) { | ||
return cache[key]; | ||
} | ||
var file = path_1.join(kfsPath, key); | ||
try { | ||
var status = fs_extra_1.statSync(file); | ||
if (!status || !status.isFile()) { | ||
return (cache[key] = null); | ||
} | ||
} | ||
catch (err) { | ||
return (cache[key] = null); | ||
} | ||
return (cache[key] = fs_extra_1.readJsonSync(file)); | ||
} | ||
return (cache[key] = fs_extra_1.readJsonSync(file)); | ||
} | ||
function deleteSync(key) { | ||
key = validizeKey(key); | ||
if (key === '*') { | ||
return clearSync(); | ||
function deleteSync(key) { | ||
key = validizeKey(key); | ||
if (key === '*') { | ||
return clearSync(); | ||
} | ||
var file = path_1.join(kfsPath, key); | ||
fs_extra_1.removeSync(file); | ||
return delete cache[key]; | ||
} | ||
var file = path_1.join(kfsPath, key); | ||
fs_extra_1.removeSync(file); | ||
return delete cache[key]; | ||
} | ||
function clearSync() { | ||
fs_extra_1.removeSync(kfsPath); | ||
if (cache.constructor === Object) { | ||
cache = { | ||
/*NEW-EMPTY-CACHE*/ | ||
}; | ||
return true; | ||
} else { | ||
return delete cache['*']; | ||
function clearSync() { | ||
fs_extra_1.removeSync(kfsPath); | ||
if (cache.constructor === Object) { | ||
cache = { | ||
/*NEW-EMPTY-CACHE*/ | ||
}; | ||
return true; | ||
} | ||
else { | ||
return delete cache['*']; | ||
} | ||
} | ||
} | ||
function hasSync(key) { | ||
key = validizeKey(key); | ||
if (key in cache) { | ||
return true; | ||
function hasSync(key) { | ||
key = validizeKey(key); | ||
if (key in cache) { | ||
return true; | ||
} | ||
var file = path_1.join(kfsPath, key); | ||
try { | ||
var status = fs_extra_1.statSync(file); | ||
if (!status || !status.isFile()) { | ||
return false; | ||
} | ||
} | ||
catch (err) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
var file = path_1.join(kfsPath, key); | ||
try { | ||
var status = fs_extra_1.statSync(file); | ||
if (!status || !status.isFile()) { | ||
return false; | ||
} | ||
} catch (err) { | ||
return false; | ||
function setAsync(key, value) { | ||
if (value === undefined) { | ||
return deleteAsync(key); | ||
} | ||
key = validizeKey(key); | ||
var file = path_1.join(kfsPath, key); | ||
return new Promise(function (resolve, reject) { | ||
fs_extra_1.outputJson(file, value, function (err) { | ||
if (err) { | ||
reject(err); | ||
} | ||
else { | ||
resolve((cache[key] = value)); | ||
} | ||
}); | ||
}); | ||
} | ||
return true; | ||
} | ||
function setAsync(key, value) { | ||
if (value === undefined) { | ||
return deleteAsync(key); | ||
function getAsync(key) { | ||
key = validizeKey(key); | ||
if (key in cache) { | ||
return Promise.resolve(cache[key]); | ||
} | ||
else { | ||
var file = path_1.join(kfsPath, key); | ||
return new Promise(function (resolve, reject) { | ||
fs_extra_1.stat(file, function (err, status) { | ||
if (err || !status || !status.isFile()) { | ||
resolve((cache[key] = null)); | ||
} | ||
else { | ||
fs_extra_1.readJson(file, function (err, value) { | ||
if (err) { | ||
reject(err); | ||
} | ||
else { | ||
resolve((cache[key] = value)); | ||
} | ||
}); | ||
} | ||
}); | ||
}); | ||
} | ||
} | ||
key = validizeKey(key); | ||
var file = path_1.join(kfsPath, key); | ||
return new Promise(function(resolve, reject) { | ||
fs_extra_1.outputJson(file, value, function(err) { | ||
if (err) { | ||
reject(err); | ||
} else { | ||
resolve((cache[key] = value)); | ||
function deleteAsync(key) { | ||
key = validizeKey(key); | ||
if (key === '*') { | ||
return clearAsync(); | ||
} | ||
}); | ||
}); | ||
} | ||
function getAsync(key) { | ||
key = validizeKey(key); | ||
if (key in cache) { | ||
return Promise.resolve(cache[key]); | ||
} else { | ||
var file = path_1.join(kfsPath, key); | ||
return new Promise(function(resolve, reject) { | ||
fs_extra_1.stat(file, function(err, status) { | ||
if (err || !status || !status.isFile()) { | ||
resolve((cache[key] = null)); | ||
} else { | ||
fs_extra_1.readJson(file, function(err, value) { | ||
if (err) { | ||
reject(err); | ||
} else { | ||
resolve((cache[key] = value)); | ||
} | ||
var file = path_1.join(kfsPath, key); | ||
return new Promise(function (resolve, reject) { | ||
fs_extra_1.remove(file, function (err) { | ||
if (err) { | ||
reject(err); | ||
} | ||
else { | ||
resolve(delete cache[key]); | ||
} | ||
}); | ||
} | ||
}); | ||
}); | ||
} | ||
} | ||
function deleteAsync(key) { | ||
key = validizeKey(key); | ||
if (key === '*') { | ||
return clearAsync(); | ||
function clearAsync() { | ||
return new Promise(function (resolve, reject) { | ||
fs_extra_1.remove(kfsPath, function (err) { | ||
if (err) { | ||
reject(err); | ||
} | ||
else { | ||
if (cache.constructor === Object) { | ||
cache = { | ||
/*NEW-EMPTY-CACHE*/ | ||
}; | ||
resolve(true); | ||
} | ||
else { | ||
resolve(delete cache['*']); | ||
} | ||
} | ||
}); | ||
}); | ||
} | ||
var file = path_1.join(kfsPath, key); | ||
return new Promise(function(resolve, reject) { | ||
fs_extra_1.remove(file, function(err) { | ||
if (err) { | ||
reject(err); | ||
} else { | ||
resolve(delete cache[key]); | ||
function hasAsync(key) { | ||
key = validizeKey(key); | ||
if (key in cache) { | ||
return Promise.resolve(true); | ||
} | ||
}); | ||
}); | ||
} | ||
function clearAsync() { | ||
return new Promise(function(resolve, reject) { | ||
fs_extra_1.remove(kfsPath, function(err) { | ||
if (err) { | ||
reject(err); | ||
} else { | ||
if (cache.constructor === Object) { | ||
cache = { | ||
/*NEW-EMPTY-CACHE*/ | ||
}; | ||
resolve(true); | ||
} else { | ||
resolve(delete cache['*']); | ||
} | ||
else { | ||
var file = path_1.join(kfsPath, key); | ||
return new Promise(function (resolve, reject) { | ||
fs_extra_1.stat(file, function (err, status) { | ||
if (err || !status || !status.isFile()) { | ||
resolve(false); | ||
} | ||
else { | ||
resolve(true); | ||
} | ||
}); | ||
}); | ||
} | ||
}); | ||
}); | ||
} | ||
function hasAsync(key) { | ||
key = validizeKey(key); | ||
if (key in cache) { | ||
return Promise.resolve(true); | ||
} else { | ||
var file = path_1.join(kfsPath, key); | ||
return new Promise(function(resolve, reject) { | ||
fs_extra_1.stat(file, function(err, status) { | ||
if (err || !status || !status.isFile()) { | ||
resolve(false); | ||
} else { | ||
resolve(true); | ||
} | ||
}); | ||
}); | ||
} | ||
} | ||
function querySync(collection) { | ||
collection = path_1.join(kfsPath, validizeKey(collection)); | ||
if (collection in cache) return cache[collection]; | ||
try { | ||
var files = recurFs.readdir.sync(collection, function(resource, status) { | ||
return status.isFile(); | ||
}); | ||
files = files.map(function(file) { | ||
return path_1.relative(kfsPath, file); | ||
}); | ||
return (cache[collection] = files || []); | ||
} catch (err) { | ||
return []; | ||
function querySync(collection) { | ||
collection = path_1.join(kfsPath, validizeKey(collection)); | ||
if (collection in cache) | ||
return cache[collection]; | ||
try { | ||
var files = recurFs.readdir.sync(collection, function (resource, status) { | ||
return status.isFile(); | ||
}); | ||
files = files.map(function (file) { return path_1.relative(kfsPath, file); }); | ||
return (cache[collection] = files || []); | ||
} | ||
catch (err) { | ||
return []; | ||
} | ||
} | ||
} | ||
function queryAsync(collection) { | ||
collection = path_1.join(kfsPath, validizeKey(collection)); | ||
if (collection in cache) return Promise.resolve(cache[collection]); | ||
return new Promise(function(resolve, reject) { | ||
//// This implementation does not work with empty folders: | ||
// recurFs.readdir(collection, function(resource, status, next) { | ||
// next(status.isFile()); | ||
// }, function(err, resources) { | ||
// if (err) { | ||
// reject(err); | ||
// } | ||
// else { | ||
// resolve(resources.map(file => path.relative(kfsPath, file))); | ||
// } | ||
// }); | ||
var fileList = [], | ||
jobNumber = 1, | ||
terminated = false; | ||
fs_extra_1.stat(collection, function(err, status) { | ||
if (err) { | ||
if (err.code === 'ENOENT') resolve((cache[collection] = [])); | ||
else reject(err); | ||
} else { | ||
processFolder(collection); | ||
} | ||
}); | ||
function processFolder(folder) { | ||
if (terminated) return; | ||
fs_extra_1.readdir(folder, function(err, files) { | ||
if (terminated) return; | ||
jobNumber--; | ||
if (err) { | ||
terminated = true; | ||
reject(err); | ||
} | ||
jobNumber += files.length; | ||
if (!jobNumber) { | ||
resolve((cache[collection] = fileList)); | ||
} | ||
files.forEach(function(file) { | ||
if (terminated) return; | ||
var filePath = path_1.join(folder, file); | ||
fs_extra_1.stat(filePath, function(err, status) { | ||
if (terminated) return; | ||
jobNumber--; | ||
if (err) { | ||
terminated = true; | ||
reject(err); | ||
} | ||
if (status.isFile()) { | ||
fileList.push(path_1.relative(kfsPath, filePath)); | ||
} else if (status.isDirectory()) { | ||
jobNumber++; | ||
processFolder(filePath); | ||
} | ||
if (!jobNumber) { | ||
resolve((cache[collection] = fileList)); | ||
} | ||
function queryAsync(collection) { | ||
collection = path_1.join(kfsPath, validizeKey(collection)); | ||
if (collection in cache) | ||
return Promise.resolve(cache[collection]); | ||
return new Promise(function (resolve, reject) { | ||
//// This implementation does not work with empty folders: | ||
// recurFs.readdir(collection, function(resource, status, next) { | ||
// next(status.isFile()); | ||
// }, function(err, resources) { | ||
// if (err) { | ||
// reject(err); | ||
// } | ||
// else { | ||
// resolve(resources.map(file => path.relative(kfsPath, file))); | ||
// } | ||
// }); | ||
var fileList = [], jobNumber = 1, terminated = false; | ||
fs_extra_1.stat(collection, function (err, status) { | ||
if (err) { | ||
if (err.code === 'ENOENT') | ||
resolve((cache[collection] = [])); | ||
else | ||
reject(err); | ||
} | ||
else { | ||
processFolder(collection); | ||
} | ||
}); | ||
}); | ||
function processFolder(folder) { | ||
if (terminated) | ||
return; | ||
fs_extra_1.readdir(folder, function (err, files) { | ||
if (terminated) | ||
return; | ||
jobNumber--; | ||
if (err) { | ||
terminated = true; | ||
reject(err); | ||
} | ||
jobNumber += files.length; | ||
if (!jobNumber) { | ||
resolve((cache[collection] = fileList)); | ||
} | ||
files.forEach(function (file) { | ||
if (terminated) | ||
return; | ||
var filePath = path_1.join(folder, file); | ||
fs_extra_1.stat(filePath, function (err, status) { | ||
if (terminated) | ||
return; | ||
jobNumber--; | ||
if (err) { | ||
terminated = true; | ||
reject(err); | ||
} | ||
if (status.isFile()) { | ||
fileList.push(path_1.relative(kfsPath, filePath)); | ||
} | ||
else if (status.isDirectory()) { | ||
jobNumber++; | ||
processFolder(filePath); | ||
} | ||
if (!jobNumber) { | ||
resolve((cache[collection] = fileList)); | ||
} | ||
}); | ||
}); | ||
}); | ||
} | ||
}); | ||
} | ||
}); | ||
} | ||
/////////////////////////////////////////////////// | ||
function validizeKey(key) { | ||
key = String(key); | ||
if (key.indexOf('/..') >= 0 || key.indexOf('../') >= 0 || key === '..') { | ||
throw new Error('Invalid key name.'); | ||
} | ||
return key; | ||
} | ||
/////////////////////////////////////////////////// | ||
function validizeKey(key) { | ||
key = String(key); | ||
if (key.indexOf('/..') >= 0 || key.indexOf('../') >= 0 || key === '..') { | ||
throw new Error('Invalid key name.'); | ||
} | ||
return key; | ||
} | ||
} | ||
exports['default'] = keyFileBasic; | ||
exports["default"] = keyFileBasic; |
@@ -17,3 +17,20 @@ import { | ||
export default function keyFileBasic(kfsPath: string, cache: { [x: string]: any }) { | ||
export interface KeyFileBasic { | ||
setSync(key: string, value: any): any; | ||
getSync(key: string): any; | ||
deleteSync(key: string): boolean; | ||
clearSync(): boolean; | ||
hasSync(key: string): boolean; | ||
setAsync(key: string, value: any): Promise<any>; | ||
getAsync(key: string): Promise<any>; | ||
deleteAsync(key: string): Promise<boolean>; | ||
clearAsync(): Promise<boolean>; | ||
hasAsync(key: string): Promise<boolean>; | ||
querySync(collection: string): string[]; | ||
queryAsync(collection: string): Promise<string[]>; | ||
} | ||
export default function keyFileBasic(kfsPath: string, cache: { [x: string]: any }): KeyFileBasic { | ||
kfsPath = kfsPath || __dirname; // Current working folder by default. | ||
@@ -152,3 +169,3 @@ kfsPath = String(kfsPath); | ||
function deleteAsync(key: string) { | ||
function deleteAsync(key: string): Promise<boolean> { | ||
key = validizeKey(key); | ||
@@ -170,3 +187,3 @@ if (key === '*') { | ||
function clearAsync() { | ||
function clearAsync(): Promise<boolean> { | ||
return new Promise(function(resolve, reject) { | ||
@@ -190,3 +207,3 @@ remove(kfsPath, function(err) { | ||
function hasAsync(key: string) { | ||
function hasAsync(key: string): Promise<boolean> { | ||
key = validizeKey(key); | ||
@@ -223,3 +240,3 @@ if (key in cache) { | ||
function queryAsync(collection: string) { | ||
function queryAsync(collection: string): Promise<string[]> { | ||
collection = join(kfsPath, validizeKey(collection)); | ||
@@ -226,0 +243,0 @@ if (collection in cache) return Promise.resolve(cache[collection]); |
@@ -1,134 +0,138 @@ | ||
'use strict'; | ||
"use strict"; | ||
exports.__esModule = true; | ||
var key_file_basic_1 = require('./key-file-basic'); | ||
var key_file_basic_1 = require("./key-file-basic"); | ||
function createKfs(kfsPath, cache) { | ||
var kfb = key_file_basic_1['default'](kfsPath, cache); | ||
// The produced promise and callback function related to the latest async 'in' operator | ||
var hasAsyncHandler = null, | ||
hasAsyncPromise = null; | ||
/* async has */ | ||
var hasAsyncWrap = { | ||
has: function(target, property) { | ||
var promise = kfb.hasAsync(property); | ||
if (hasAsyncHandler) { | ||
callbackizePromise(promise, hasAsyncHandler); | ||
hasAsyncHandler = null; | ||
} else { | ||
hasAsyncPromise = promise; | ||
} | ||
return false; // No synchronous answer. | ||
}, | ||
}; | ||
var kfs = new Proxy( | ||
function() { | ||
var a1 = arguments[0], | ||
a2 = arguments[1], | ||
a3 = arguments[2]; | ||
switch (arguments.length) { | ||
case 0: | ||
if (hasAsyncPromise) { | ||
a3 = hasAsyncPromise; | ||
hasAsyncPromise = null; | ||
return a3; | ||
} else { | ||
return new Proxy({}, hasAsyncWrap); | ||
} | ||
// break; | ||
case 1: | ||
if (typeof a1 === 'function') { | ||
if (hasAsyncPromise) { | ||
a3 = hasAsyncPromise; | ||
hasAsyncPromise = null; | ||
return callbackizePromise(a3, a1); | ||
} else { | ||
hasAsyncHandler = a1; | ||
return new Proxy({}, hasAsyncWrap); | ||
var kfb = key_file_basic_1["default"](kfsPath, cache); | ||
// The produced promise and callback function related to the latest async 'in' operator | ||
var hasAsyncHandler = null, hasAsyncPromise = null; | ||
/* async has */ | ||
var hasAsyncWrap = { | ||
has: function (target, property) { | ||
var promise = kfb.hasAsync(property); | ||
if (hasAsyncHandler) { | ||
callbackizePromise(promise, hasAsyncHandler); | ||
hasAsyncHandler = null; | ||
} | ||
} else if (String(a1).slice(-1) === '/') { | ||
/* async query pr */ | ||
return kfb.queryAsync(a1); | ||
} else { | ||
/* async get pr */ | ||
return kfb.getAsync(a1); | ||
} | ||
// break; | ||
case 2: | ||
if (typeof a2 === 'function') { | ||
if (String(a1).slice(-1) === '/') { | ||
/* async query cb */ | ||
return callbackizePromise(kfb.queryAsync(a1), a2); | ||
} else { | ||
/* async get cb */ | ||
return callbackizePromise(kfb.getAsync(a1), a2); | ||
else { | ||
hasAsyncPromise = promise; | ||
} | ||
} else { | ||
/* async set pr */ | ||
return kfb.setAsync(a1, a2); | ||
} | ||
// break; | ||
case 3: | ||
if (typeof a3 === 'function') { | ||
/* async set cb */ | ||
return callbackizePromise(kfb.setAsync(a1, a2), a3); | ||
} | ||
// break; | ||
} | ||
throw new Error('Invalid input argument(s).'); | ||
}, | ||
{ | ||
/* sync set */ | ||
set: function(target, property, value, receiver) { | ||
return kfb.setSync(property, value); | ||
}, | ||
get: function(target, property, receiver) { | ||
if (String(property).slice(-1) === '/') { | ||
/* sync query */ | ||
return kfb.querySync(property); | ||
} else { | ||
/* sync get */ | ||
return kfb.getSync(property); | ||
return false; // No synchronous answer. | ||
} | ||
}, | ||
/* sync delete */ | ||
deleteProperty: function(target, property) { | ||
return kfb.deleteSync(property); | ||
}, | ||
/* sync has */ | ||
has: function(target, property) { | ||
return kfb.hasSync(property); | ||
}, | ||
/* async delete */ | ||
construct: function(target, argumentsList, newTarget) { | ||
var a1 = argumentsList[0], | ||
a2 = argumentsList[1]; | ||
switch (argumentsList.length) { | ||
case 0: | ||
return kfb.clearAsync(); | ||
// break; | ||
case 1: | ||
if (typeof a1 === 'function') { | ||
return callbackizePromise(kfb.clearAsync(), a1); | ||
} else { | ||
return kfb.deleteAsync(a1); | ||
}; | ||
var kfs = new Proxy(function () { | ||
var a1 = arguments[0], a2 = arguments[1], a3 = arguments[2]; | ||
switch (arguments.length) { | ||
case 0: | ||
if (hasAsyncPromise) { | ||
a3 = hasAsyncPromise; | ||
hasAsyncPromise = null; | ||
return a3; | ||
} | ||
else { | ||
return new Proxy({}, hasAsyncWrap); | ||
} | ||
// break; | ||
case 1: | ||
if (typeof a1 === 'function') { | ||
if (hasAsyncPromise) { | ||
a3 = hasAsyncPromise; | ||
hasAsyncPromise = null; | ||
return callbackizePromise(a3, a1); | ||
} | ||
else { | ||
hasAsyncHandler = a1; | ||
return new Proxy({}, hasAsyncWrap); | ||
} | ||
} | ||
else if (String(a1).slice(-1) === '/') { | ||
/* async query pr */ | ||
return kfb.queryAsync(String(a1)); | ||
} | ||
else { | ||
/* async get pr */ | ||
return kfb.getAsync(String(a1)); | ||
} | ||
// break; | ||
case 2: | ||
if (typeof a2 === 'function') { | ||
if (String(a1).slice(-1) === '/') { | ||
/* async query cb */ | ||
return callbackizePromise(kfb.queryAsync(String(a1)), a2); | ||
} | ||
else { | ||
/* async get cb */ | ||
return callbackizePromise(kfb.getAsync(String(a1)), a2); | ||
} | ||
} | ||
else { | ||
/* async set pr */ | ||
return kfb.setAsync(String(a1), a2); | ||
} | ||
// break; | ||
case 3: | ||
if (typeof a3 === 'function') { | ||
/* async set cb */ | ||
return callbackizePromise(kfb.setAsync(String(a1), a2), a3); | ||
} | ||
// break; | ||
} | ||
throw new Error('Invalid input argument(s).'); | ||
}, { | ||
/* sync set */ | ||
set: function (target, property, value, receiver) { | ||
kfb.setSync(String(property), value); | ||
return true; | ||
}, | ||
get: function (target, property, receiver) { | ||
if (String(property).slice(-1) === '/') { | ||
/* sync query */ | ||
return kfb.querySync(String(property)); | ||
} | ||
// break; | ||
case 2: | ||
return callbackizePromise(kfb.deleteAsync(a1), a2); | ||
// break; | ||
else { | ||
/* sync get */ | ||
return kfb.getSync(String(property)); | ||
} | ||
}, | ||
/* sync delete */ | ||
deleteProperty: function (target, property) { | ||
return kfb.deleteSync(String(property)); | ||
}, | ||
/* sync has */ | ||
has: function (target, property) { | ||
return kfb.hasSync(String(property)); | ||
}, | ||
/* async delete */ | ||
construct: function (target, argumentsList, newTarget) { | ||
var a1 = argumentsList[0], a2 = argumentsList[1]; | ||
switch (argumentsList.length) { | ||
case 0: | ||
return kfb.clearAsync(); | ||
// break; | ||
case 1: | ||
if (typeof a1 === 'function') { | ||
return callbackizePromise(kfb.clearAsync(), a1); | ||
} | ||
else { | ||
return kfb.deleteAsync(String(a1)); | ||
} | ||
// break; | ||
case 2: | ||
return callbackizePromise(kfb.deleteAsync(String(a1)), a2); | ||
// break; | ||
} | ||
throw new Error('Invalid input argument(s).'); | ||
} | ||
throw new Error('Invalid input argument(s).'); | ||
}, | ||
}, | ||
); | ||
return kfs; | ||
function callbackizePromise(promise, callback) { | ||
if (typeof callback === 'function') { | ||
return promise.then(function(data) { | ||
return callback(undefined, data); | ||
}, callback); | ||
} else { | ||
return promise; | ||
}); | ||
return kfs; | ||
function callbackizePromise(promise, callback) { | ||
if (typeof callback === 'function') { | ||
return promise.then(function (data) { | ||
return callback(undefined, data); | ||
}, callback); | ||
} | ||
else { | ||
return promise; | ||
} | ||
} | ||
} | ||
} | ||
exports['default'] = createKfs; | ||
exports["default"] = createKfs; |
import keyFileBasic from './key-file-basic'; | ||
export default function createKfs(kfsPath: string, cache: { [x: string]: any }) { | ||
export interface KeyFileStorage { | ||
[key: string]: any; | ||
[index: number]: any; | ||
<T, U = T>(key: string | number, value: T, callback?: (error: any) => U): Promise<U>; | ||
<T = any, U = T>(key: string | number, callback?: (error: any, value?: T) => U): Promise<U>; | ||
new <U = boolean>(key: string | number, callback?: (error: any) => U): Promise<U>; | ||
new <U = boolean>(callback?: (error: any) => U): Promise<U>; | ||
<U = boolean>(callback?: (error: any) => U): Promise<U>; | ||
} | ||
export default function createKfs(kfsPath: string, cache: { [x: string]: any }): KeyFileStorage { | ||
var kfb = keyFileBasic(kfsPath, cache); | ||
@@ -53,6 +64,6 @@ | ||
/* async query pr */ | ||
return kfb.queryAsync(a1); | ||
return kfb.queryAsync(String(a1)); | ||
} else { | ||
/* async get pr */ | ||
return kfb.getAsync(a1); | ||
return kfb.getAsync(String(a1)); | ||
} | ||
@@ -65,10 +76,10 @@ // break; | ||
/* async query cb */ | ||
return callbackizePromise(kfb.queryAsync(a1), a2); | ||
return callbackizePromise(kfb.queryAsync(String(a1)), a2); | ||
} else { | ||
/* async get cb */ | ||
return callbackizePromise(kfb.getAsync(a1), a2); | ||
return callbackizePromise(kfb.getAsync(String(a1)), a2); | ||
} | ||
} else { | ||
/* async set pr */ | ||
return kfb.setAsync(a1, a2); | ||
return kfb.setAsync(String(a1), a2); | ||
} | ||
@@ -80,3 +91,3 @@ // break; | ||
/* async set cb */ | ||
return callbackizePromise(kfb.setAsync(a1, a2), a3); | ||
return callbackizePromise(kfb.setAsync(String(a1), a2), a3); | ||
} | ||
@@ -90,13 +101,14 @@ // break; | ||
/* sync set */ | ||
set: function(target, property: string, value, receiver) { | ||
return kfb.setSync(property, value); | ||
set: function(target, property, value, receiver) { | ||
kfb.setSync(String(property), value); | ||
return true; | ||
}, | ||
get: function(target, property: string, receiver) { | ||
get: function(target, property, receiver) { | ||
if (String(property).slice(-1) === '/') { | ||
/* sync query */ | ||
return kfb.querySync(property); | ||
return kfb.querySync(String(property)); | ||
} else { | ||
/* sync get */ | ||
return kfb.getSync(property); | ||
return kfb.getSync(String(property)); | ||
} | ||
@@ -106,9 +118,9 @@ }, | ||
/* sync delete */ | ||
deleteProperty: function(target, property: string) { | ||
return kfb.deleteSync(property); | ||
deleteProperty: function(target, property) { | ||
return kfb.deleteSync(String(property)); | ||
}, | ||
/* sync has */ | ||
has: function(target, property: string) { | ||
return kfb.hasSync(property); | ||
has: function(target, property) { | ||
return kfb.hasSync(String(property)); | ||
}, | ||
@@ -130,3 +142,3 @@ | ||
} else { | ||
return kfb.deleteAsync(a1); | ||
return kfb.deleteAsync(String(a1)); | ||
} | ||
@@ -136,3 +148,3 @@ // break; | ||
case 2: | ||
return callbackizePromise(kfb.deleteAsync(a1), a2); | ||
return callbackizePromise(kfb.deleteAsync(String(a1)), a2); | ||
// break; | ||
@@ -139,0 +151,0 @@ } |
"use strict"; | ||
exports.__esModule = true; | ||
var _1 = require("."); | ||
var kfs = _1["default"]('data'); | ||
kfs.a = 'a'; | ||
var index_1 = require("./index"); | ||
var kfs = index_1["default"]('data'); | ||
console.log((kfs.a = 'a')); | ||
console.log(kfs.a, kfs.b); |
@@ -1,5 +0,5 @@ | ||
import keyFileStorage from '.'; | ||
import keyFileStorage from './index'; | ||
const kfs = keyFileStorage('data'); | ||
kfs.a = 'a'; | ||
console.log((kfs.a = 'a')); | ||
console.log(kfs.a, kfs.b); |
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
70740
1824