key-file-storage
Advanced tools
Comparing version 2.2.6 to 2.2.7
@@ -0,0 +0,0 @@ import { KeyFileStorage } from './src/key-file-storage'; |
@@ -0,0 +0,0 @@ "use strict"; |
@@ -0,0 +0,0 @@ export interface KfsCache { |
@@ -0,0 +0,0 @@ "use strict"; |
@@ -0,0 +0,0 @@ export interface KeyFileBasic { |
@@ -191,3 +191,4 @@ "use strict"; | ||
return; | ||
fs_extra_1.readdir(folder, function (err, files) { | ||
var folderPath = path_1.join(kfsPath, folder); | ||
fs_extra_1.readdir(folderPath, function (err, files) { | ||
if (terminated) | ||
@@ -207,3 +208,3 @@ return; | ||
return; | ||
var filePath = path_1.join(folder, file); | ||
var filePath = path_1.join(folderPath, file); | ||
fs_extra_1.stat(filePath, function (err, status) { | ||
@@ -210,0 +211,0 @@ if (terminated) |
@@ -0,0 +0,0 @@ export interface KeyFileStorage { |
@@ -0,0 +0,0 @@ "use strict"; |
@@ -0,0 +0,0 @@ "use strict"; |
@@ -0,0 +0,0 @@ import createCache from './src/create-cache'; |
{ | ||
"name": "key-file-storage", | ||
"version": "2.2.6", | ||
"version": "2.2.7", | ||
"description": "Simple key-value storage directly on file system, maps each key to a separate file.", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -0,0 +0,0 @@ # key-file-storage |
@@ -1,205 +0,186 @@ | ||
'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) { | ||
var collectionCache = {}; | ||
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) { | ||
var collectionCache = {}; | ||
return new Proxy({ | ||
/*CACHE*/ | ||
}, | ||
{ | ||
set: function(target, property, value, receiver) { | ||
var propertyName = String(property); | ||
if (propertyName.endsWith('/')) { | ||
collectionCache[propertyName] = value; | ||
return true; | ||
} | ||
target[propertyName] = value; | ||
Object.keys(collectionCache) | ||
.filter(function(collection) { | ||
return keyInCollection(propertyName, collection); | ||
}) | ||
.forEach(function(collection) { | ||
return ( | ||
collectionCache[collection].includes(propertyName) || collectionCache[collection].push(propertyName) | ||
); | ||
}); | ||
return true; | ||
}, | ||
get: function(target, property, receiver) { | ||
var propertyName = String(property); | ||
if (propertyName.endsWith('/')) console.log('from cache'); | ||
if (propertyName.endsWith('/')) return collectionCache[propertyName]; | ||
return target[propertyName]; | ||
}, | ||
deleteProperty: function(target, property) { | ||
var propertyName = String(property); | ||
if (propertyName === '*') { | ||
collectionCache = {}; | ||
Object.keys(target).forEach(function(key) { | ||
return delete target[key]; | ||
}); | ||
return true; | ||
} | ||
if (propertyName.endsWith('/')) return delete collectionCache[propertyName]; | ||
Object.keys(collectionCache) | ||
.filter(function(collection) { | ||
return keyInCollection(propertyName, collection); | ||
}) | ||
.forEach(function(collection) { | ||
return ( | ||
collectionCache[collection].includes(propertyName) && | ||
collectionCache[collection].splice(collectionCache[collection].indexOf(propertyName), 1) | ||
); | ||
}); | ||
return delete target[propertyName]; | ||
}, | ||
has: function(target, property) { | ||
var propertyName = String(property); | ||
if (propertyName.endsWith('/')) return propertyName in collectionCache; | ||
return property in target; | ||
}, | ||
}, | ||
); | ||
} | ||
function createCache_NoCache(cacheConfig) { | ||
return new Proxy( | ||
{ | ||
}, { | ||
set: function (target, property, value, receiver) { | ||
var propertyName = String(property); | ||
if (propertyName.endsWith('/')) { | ||
collectionCache[propertyName] = value; | ||
return true; | ||
} | ||
target[propertyName] = value; | ||
Object.keys(collectionCache) | ||
.filter(function (collection) { return keyInCollection(propertyName, collection); }) | ||
.forEach(function (collection) { | ||
return collectionCache[collection].includes(propertyName) || collectionCache[collection].push(propertyName); | ||
}); | ||
return true; | ||
}, | ||
get: function (target, property, receiver) { | ||
var propertyName = String(property); | ||
if (propertyName.endsWith('/')) | ||
return collectionCache[propertyName]; | ||
return target[propertyName]; | ||
}, | ||
deleteProperty: function (target, property) { | ||
var propertyName = String(property); | ||
if (propertyName === '*') { | ||
collectionCache = {}; | ||
Object.keys(target).forEach(function (key) { return delete target[key]; }); | ||
return true; | ||
} | ||
if (propertyName.endsWith('/')) | ||
return delete collectionCache[propertyName]; | ||
Object.keys(collectionCache) | ||
.filter(function (collection) { return keyInCollection(propertyName, collection); }) | ||
.forEach(function (collection) { | ||
return collectionCache[collection].includes(propertyName) && | ||
collectionCache[collection].splice(collectionCache[collection].indexOf(propertyName), 1); | ||
}); | ||
return delete target[propertyName]; | ||
}, | ||
has: function (target, property) { | ||
var propertyName = String(property); | ||
if (propertyName.endsWith('/')) | ||
return propertyName in collectionCache; | ||
return property in target; | ||
} | ||
}); | ||
} | ||
function createCache_NoCache(cacheConfig) { | ||
return new Proxy({ | ||
/*CACHE*/ | ||
}, | ||
{ | ||
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 collectionCache = {}; | ||
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 collectionCache = {}; | ||
var keyNumber = Math.ceil(cacheConfig), keys = Array(keyNumber), nextKeyIndex = 0, keyIndex; | ||
return new Proxy({ | ||
/*CACHE*/ | ||
}, | ||
{ | ||
set: function(target, property, value, receiver) { | ||
var propertyName = String(property); | ||
if (propertyName.endsWith('/')) { | ||
collectionCache[propertyName] = value; | ||
return true; | ||
} | ||
updateKeys(target, propertyName, 'SET'); | ||
target[propertyName] = value; | ||
Object.keys(collectionCache) | ||
.filter(function(collection) { | ||
return keyInCollection(propertyName, collection); | ||
}) | ||
.forEach(function(collection) { | ||
return ( | ||
collectionCache[collection].includes(propertyName) || collectionCache[collection].push(propertyName) | ||
); | ||
}); | ||
return true; | ||
}, | ||
get: function(target, property, receiver) { | ||
var propertyName = String(property); | ||
if (propertyName.endsWith('/')) return collectionCache[propertyName]; | ||
updateKeys(target, propertyName, 'GET'); | ||
return target[propertyName]; | ||
}, | ||
deleteProperty: function(target, property) { | ||
var propertyName = String(property); | ||
if (propertyName === '*') { | ||
collectionCache = {}; | ||
keys = Array(keyNumber); | ||
nextKeyIndex = 0; | ||
return true; | ||
} | ||
if (propertyName.endsWith('/')) return delete collectionCache[propertyName]; | ||
Object.keys(collectionCache) | ||
.filter(function(collection) { | ||
return keyInCollection(propertyName, collection); | ||
}) | ||
.forEach(function(collection) { | ||
return ( | ||
collectionCache[collection].includes(propertyName) && | ||
collectionCache[collection].splice(collectionCache[collection].indexOf(propertyName), 1) | ||
); | ||
}); | ||
updateKeys(target, propertyName, 'DELETE'); | ||
return delete target[propertyName]; | ||
}, | ||
has: function(target, property) { | ||
var propertyName = String(property); | ||
if (propertyName.endsWith('/')) return propertyName in collectionCache; | ||
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) { | ||
var propertyName = String(property); | ||
if (propertyName.endsWith('/')) { | ||
collectionCache[propertyName] = value; | ||
return true; | ||
} | ||
updateKeys(target, propertyName, 'SET'); | ||
target[propertyName] = value; | ||
Object.keys(collectionCache) | ||
.filter(function (collection) { return keyInCollection(propertyName, collection); }) | ||
.forEach(function (collection) { | ||
return collectionCache[collection].includes(propertyName) || collectionCache[collection].push(propertyName); | ||
}); | ||
return true; | ||
}, | ||
get: function (target, property, receiver) { | ||
var propertyName = String(property); | ||
if (propertyName.endsWith('/')) | ||
return collectionCache[propertyName]; | ||
updateKeys(target, propertyName, 'GET'); | ||
return target[propertyName]; | ||
}, | ||
deleteProperty: function (target, property) { | ||
var propertyName = String(property); | ||
if (propertyName === '*') { | ||
collectionCache = {}; | ||
keys = Array(keyNumber); | ||
nextKeyIndex = 0; | ||
return true; | ||
} | ||
if (propertyName.endsWith('/')) | ||
return delete collectionCache[propertyName]; | ||
Object.keys(collectionCache) | ||
.filter(function (collection) { return keyInCollection(propertyName, collection); }) | ||
.forEach(function (collection) { | ||
return collectionCache[collection].includes(propertyName) && | ||
collectionCache[collection].splice(collectionCache[collection].indexOf(propertyName), 1); | ||
}); | ||
updateKeys(target, propertyName, 'DELETE'); | ||
return delete target[propertyName]; | ||
}, | ||
has: function (target, property) { | ||
var propertyName = String(property); | ||
if (propertyName.endsWith('/')) | ||
return propertyName in collectionCache; | ||
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); | ||
} | ||
} | ||
} | ||
function keyInCollection(key, collection) { | ||
collection = collection.startsWith('./') | ||
? collection.slice(1) | ||
: collection.startsWith('/') | ||
? collection | ||
: '/' + collection; | ||
key = key.startsWith('./') ? key.slice(1) : key.startsWith('/') ? key : '/' + key; | ||
return key.startsWith(collection); | ||
} | ||
function keyInCollection(key, collection) { | ||
collection = collection.startsWith('./') | ||
? collection.slice(1) | ||
: collection.startsWith('/') | ||
? collection | ||
: '/' + collection; | ||
key = key.startsWith('./') ? key.slice(1) : key.startsWith('/') ? key : '/' + key; | ||
return key.startsWith(collection); | ||
} | ||
} | ||
exports['default'] = createCache; | ||
exports["default"] = createCache; |
@@ -0,0 +0,0 @@ export interface KfsCache { |
@@ -1,214 +0,240 @@ | ||
'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); | ||
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]; | ||
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); | ||
kfsPath = kfsPath || __dirname; // Current working folder by default. | ||
kfsPath = String(kfsPath); | ||
if (!isValidPath(kfsPath)) { | ||
throw new Error('Invalid stroage path.'); | ||
} | ||
return (cache[key] = fs_extra_1.readJsonSync(file)); | ||
} | ||
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]; | ||
} | ||
function clearSync() { | ||
fs_extra_1.removeSync(kfsPath); | ||
return delete cache['*']; | ||
} | ||
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 { | ||
// 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); | ||
} | ||
return true; | ||
} | ||
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) return reject(err); | ||
resolve((cache[key] = value)); | ||
}); | ||
}); | ||
} | ||
function getAsync(key) { | ||
key = validizeKey(key); | ||
if (key in cache) return Promise.resolve(cache[key]); | ||
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()) return resolve((cache[key] = null)); | ||
fs_extra_1.readJson(file, function(err, value) { | ||
if (err) return reject(err); | ||
resolve((cache[key] = value)); | ||
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)); | ||
} | ||
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]; | ||
} | ||
function clearSync() { | ||
fs_extra_1.removeSync(kfsPath); | ||
return delete cache['*']; | ||
} | ||
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; | ||
} | ||
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) | ||
return reject(err); | ||
resolve((cache[key] = value)); | ||
}); | ||
}); | ||
}); | ||
}); | ||
} | ||
function deleteAsync(key) { | ||
key = validizeKey(key); | ||
if (key === '*') return clearAsync(); | ||
var file = path_1.join(kfsPath, key); | ||
return new Promise(function(resolve, reject) { | ||
fs_extra_1.remove(file, function(err) { | ||
if (err) return reject(err); | ||
resolve(delete cache[key]); | ||
}); | ||
}); | ||
} | ||
function clearAsync() { | ||
return new Promise(function(resolve, reject) { | ||
fs_extra_1.remove(kfsPath, function(err) { | ||
if (err) return reject(err); | ||
resolve(delete cache['*']); | ||
}); | ||
}); | ||
} | ||
function hasAsync(key) { | ||
key = validizeKey(key); | ||
if (key in cache) return Promise.resolve(true); | ||
var file = path_1.join(kfsPath, key); | ||
return new Promise(function(resolve, reject) { | ||
fs_extra_1.stat(file, function(err, status) { | ||
resolve(!!(!err && status && status.isFile())); | ||
}); | ||
}); | ||
} | ||
function querySync(collection) { | ||
collection = validizeKey(collection); | ||
if (collection in cache) return cache[collection]; | ||
try { | ||
var collectionPath = path_1.join(kfsPath, collection); | ||
var files = recurFs.readdir.sync(collectionPath, function(resource, status) { | ||
return status.isFile(); | ||
}); | ||
files = files.map(function(file) { | ||
return validizeKey(path_1.relative(kfsPath, file)); | ||
}); | ||
return (cache[collection] = files || []); | ||
} catch (err) { | ||
return []; | ||
} | ||
} | ||
function queryAsync(collection) { | ||
collection = 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; | ||
var collectionPath = path_1.join(kfsPath, collection); | ||
fs_extra_1.stat(collectionPath, function(err, status) { | ||
if (err) { | ||
if (err.code === 'ENOENT') resolve((cache[collection] = [])); | ||
else reject(err); | ||
} else { | ||
processFolder(collection); | ||
function getAsync(key) { | ||
key = validizeKey(key); | ||
if (key in cache) | ||
return Promise.resolve(cache[key]); | ||
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()) | ||
return resolve((cache[key] = null)); | ||
fs_extra_1.readJson(file, function (err, value) { | ||
if (err) | ||
return reject(err); | ||
resolve((cache[key] = value)); | ||
}); | ||
}); | ||
}); | ||
} | ||
function deleteAsync(key) { | ||
key = validizeKey(key); | ||
if (key === '*') | ||
return clearAsync(); | ||
var file = path_1.join(kfsPath, key); | ||
return new Promise(function (resolve, reject) { | ||
fs_extra_1.remove(file, function (err) { | ||
if (err) | ||
return reject(err); | ||
resolve(delete cache[key]); | ||
}); | ||
}); | ||
} | ||
function clearAsync() { | ||
return new Promise(function (resolve, reject) { | ||
fs_extra_1.remove(kfsPath, function (err) { | ||
if (err) | ||
return reject(err); | ||
resolve(delete cache['*']); | ||
}); | ||
}); | ||
} | ||
function hasAsync(key) { | ||
key = validizeKey(key); | ||
if (key in cache) | ||
return Promise.resolve(true); | ||
var file = path_1.join(kfsPath, key); | ||
return new Promise(function (resolve, reject) { | ||
fs_extra_1.stat(file, function (err, status) { | ||
resolve(!!(!err && status && status.isFile())); | ||
}); | ||
}); | ||
} | ||
function querySync(collection) { | ||
collection = validizeKey(collection); | ||
if (collection in cache) | ||
return cache[collection]; | ||
try { | ||
var collectionPath = path_1.join(kfsPath, collection); | ||
var files = recurFs.readdir.sync(collectionPath, function (resource, status) { | ||
return status.isFile(); | ||
}); | ||
files = files.map(function (file) { return validizeKey(path_1.relative(kfsPath, file)); }); | ||
return (cache[collection] = files || []); | ||
} | ||
}); | ||
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(validizeKey(path_1.relative(kfsPath, filePath))); | ||
} else if (status.isDirectory()) { | ||
jobNumber++; | ||
processFolder(filePath); | ||
} | ||
if (!jobNumber) { | ||
resolve((cache[collection] = fileList)); | ||
} | ||
catch (err) { | ||
return []; | ||
} | ||
} | ||
function queryAsync(collection) { | ||
collection = 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; | ||
var collectionPath = path_1.join(kfsPath, collection); | ||
fs_extra_1.stat(collectionPath, function (err, status) { | ||
if (err) { | ||
if (err.code === 'ENOENT') | ||
resolve((cache[collection] = [])); | ||
else | ||
reject(err); | ||
} | ||
else { | ||
processFolder(collection); | ||
} | ||
}); | ||
}); | ||
function processFolder(folder) { | ||
if (terminated) | ||
return; | ||
var folderPath = path_1.join(kfsPath, folder); | ||
fs_extra_1.readdir(folderPath, 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(folderPath, file); | ||
fs_extra_1.stat(filePath, function (err, status) { | ||
if (terminated) | ||
return; | ||
jobNumber--; | ||
if (err) { | ||
terminated = true; | ||
reject(err); | ||
} | ||
if (status.isFile()) { | ||
fileList.push(validizeKey(path_1.relative(kfsPath, filePath))); | ||
} | ||
else if (status.isDirectory()) { | ||
jobNumber++; | ||
processFolder(filePath); | ||
} | ||
if (!jobNumber) { | ||
resolve((cache[collection] = fileList)); | ||
} | ||
}); | ||
}); | ||
}); | ||
} | ||
}); | ||
} | ||
}); | ||
} | ||
/////////////////////////////////////////////////// | ||
function validizeKey(key) { | ||
key = String(key).replace(/\\/g, '/'); | ||
if (key.includes('/..') || key.includes('../') || key === '..') throw new Error('Invalid key name.'); | ||
return key; | ||
} | ||
} | ||
/////////////////////////////////////////////////// | ||
function validizeKey(key) { | ||
key = String(key).replace(/\\/g, '/'); | ||
if (key.includes('/..') || key.includes('../') || key === '..') | ||
throw new Error('Invalid key name.'); | ||
return key; | ||
} | ||
} | ||
exports['default'] = keyFileBasic; | ||
exports["default"] = keyFileBasic; |
@@ -215,3 +215,4 @@ import { | ||
if (terminated) return; | ||
readdir(folder, function(err, files) { | ||
const folderPath = join(kfsPath, folder); | ||
readdir(folderPath, function(err, files) { | ||
if (terminated) return; | ||
@@ -229,3 +230,3 @@ jobNumber--; | ||
if (terminated) return; | ||
var filePath = join(folder, file); | ||
var filePath = join(folderPath, file); | ||
stat(filePath, function(err, status) { | ||
@@ -232,0 +233,0 @@ if (terminated) return; |
@@ -1,135 +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(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 { | ||
hasAsyncPromise = promise; | ||
} | ||
} 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)); | ||
} else { | ||
/* sync get */ | ||
return kfb.getSync(String(property)); | ||
return false; // No synchronous answer. | ||
} | ||
}, | ||
/* 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)); | ||
}; | ||
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(String(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; |
@@ -0,0 +0,0 @@ import keyFileBasic from './key-file-basic'; |
"use strict"; | ||
exports.__esModule = true; | ||
var index_1 = require("./index"); | ||
var kfs = index_1["default"]('data'); | ||
var kfs = index_1["default"]('../../data'); | ||
delete kfs['*']; | ||
@@ -27,1 +27,7 @@ console.log("(kfs.a = 'a') >> ", (kfs.a = 'a')); | ||
console.log(kfs['a/b/c/']); | ||
console.log('..............................................'); | ||
Promise.resolve() | ||
.then(function (x) { return kfs('qq/qqq', { data: 123 }); }) | ||
.then(function (x) { return kfs('qq/www', { data: 456 }); }) | ||
.then(function (x) { return kfs('qq/'); }) | ||
.then(function (x) { return console.log(x); }); |
10
test.ts
import keyFileStorage from './index'; | ||
const kfs = keyFileStorage('data'); | ||
const kfs = keyFileStorage('../../data'); | ||
delete kfs['*']; | ||
@@ -29,1 +29,9 @@ | ||
console.log(kfs['a/b/c/']); | ||
console.log('..............................................'); | ||
Promise.resolve() | ||
.then(x => kfs('qq/qqq', { data: 123 })) | ||
.then(x => kfs('qq/www', { data: 456 })) | ||
.then(x => kfs('qq/')) | ||
.then(x => console.log(x)) |
@@ -0,0 +0,0 @@ { |
{ | ||
"extends": ["tslint:recommended", "tslint-config-prettier"] | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
78052
1873
25