This repository has been archived by the owner on Oct 24, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
JsonStorageEngine.js
127 lines (114 loc) · 3.46 KB
/
JsonStorageEngine.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
const fs = require('fs-extra');
const path = require('path');
const { StorageType, StorageEngine } = require('./StorageEngine');
const { StorageFunction, StorageFunctionType, StorageFunctionGroup } = require('./StorageFunction');
const { KeyFoundError, KeyNotFoundError } = require('./Errors');
// In-memory data manager, essentially
const STORAGE = {
FILENAME: 'data.json',
DATA: new Map()
};
/**
* Builds a safe path to the data file
* @returns {String} Path to the data file
*/
function getDataPath() {
return path.join(process.cwd(), STORAGE.FILENAME);
}
/**
* Converts the Data Map to a JSON Object
* @returns {Object} JSON Object representing resource data
*/
function toJson() {
const json = {};
STORAGE.DATA.forEach((resourceData, resourceId) => json[resourceId] = resourceData);
return json;
}
/**
* Attempts to save the data to a file
* @param {*} resolve Passed from a Promise. Runs on success
* @param {*} reject Passed from a Promise. Runs on failure
*/
function save(resolve, reject) {
fs.writeJson(getDataPath(), toJson(), { spaces: 4 })
.then(resolve)
.catch(reject);
}
/**
* Get a resource
* @param {String} resourceId Resource ID to get
* @returns {Promise}
*/
function JsonGetFunc(resourceId) {
return new Promise((resolve, reject) =>
(resourceId === undefined)
? resolve(Array.from(STORAGE.DATA.entries()))
: (STORAGE.DATA.has(resourceId))
? resolve(STORAGE.DATA.get(resourceId))
: reject(new KeyNotFoundError()));
}
/**
* Add a resource
* @param {String} resourceId Resource ID to add
* @param {Object} resourceData Data for the resource
* @returns {Promise}
*/
function JsonPutFunc(resourceId, resourceData) {
return new Promise((resolve, reject) =>
(!STORAGE.DATA.has(resourceId))
? (STORAGE.DATA.set(resourceId, resourceData), save(resolve, reject), null)
: reject(new KeyFoundError()));
}
/**
* Delete a resource
* @param {String} resourceId Resource to delete
* @returns {Promise}
*/
function JsonDelFunc(resourceId) {
return new Promise((resolve, reject) =>
(STORAGE.DATA.has(resourceId))
? (STORAGE.DATA.delete(resourceId), save(resolve, reject), null)
: reject(new KeyNotFoundError()));
}
/**
* Check a resource
* (Usually, this would also have a catch/reject, but Map's shouldn't throw on a .has)
* @param {String} resourceId Resource to Check
* @returns {Promise}
*/
function JsonHasFunc(resourceId) {
return new Promise((resolve) => resolve(STORAGE.DATA.has(resourceId)));
}
class JsonStorageEngine extends StorageEngine {
/**
* Create a new JsonStorageEngine
* @param {String} [filename=data.json] Filename for the JSON file. Defaults to 'data.json'
*/
constructor(filename = 'data.json') {
STORAGE.FILENAME = filename;
super('JSON', StorageType.FILE, new StorageFunctionGroup(
new StorageFunction(StorageFunctionType.GET, JsonGetFunc),
new StorageFunction(StorageFunctionType.PUT, JsonPutFunc),
new StorageFunction(StorageFunctionType.DEL, JsonDelFunc),
new StorageFunction(StorageFunctionType.HAS, JsonHasFunc)
));
// Load or create file
if (fs.existsSync(getDataPath()))
Object.entries(fs.readJsonSync(getDataPath()))
.forEach(([resourceId, resourceData]) => STORAGE.DATA.set(resourceId, resourceData))
else {
fs.ensureFileSync(getDataPath());
fs.writeJsonSync(getDataPath(), toJson());
}
}
/**
* Number of items this StorageEngine holds
*/
get size() {
return STORAGE.DATA.size;
}
toString() {
return STORAGE.DATA;
}
}
module.exports = JsonStorageEngine;