mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-13 07:04:53 +09:00
Add id based database load and save functions
Add functions to save and load a Map of objects indexed by the id property in the objects.
This commit is contained in:
1 parent
fcae3ef0c1
commit
65f75d86e6
6 files changed
+163
-4
No files matched your search
+76
-3
@@ -31,9 +31,10 @@ function mapToObject(map) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Load JSON file as a Map
|
||||
* Load JSON object file as a Map
|
||||
*
|
||||
* Loads the JSON file specified by path an converts it into a JavaScript Map.
|
||||
* Loads the JSON file specified by path containing an object with
|
||||
* properties as key value pairs and converts it into a JavaScript Map.
|
||||
* Returns an empty Map if the file does not exist.
|
||||
*
|
||||
* @param {string} filePath - The path to the JSON file to load.
|
||||
@@ -71,7 +72,7 @@ async function loadJsonAsMap(filePath) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a Map as a JSON file
|
||||
* Save a Map as a JSON object file
|
||||
*
|
||||
* Save the content of a key-value Map with only string keys as a JSON file.
|
||||
* If the directory the file is to be saved into doesn't exist it will be
|
||||
@@ -87,6 +88,76 @@ async function saveMapAsJson(filePath, map) {
|
||||
await fs.outputFile(filePath, JSON.stringify(obj, null, 4));
|
||||
}
|
||||
|
||||
/**
|
||||
* Load JSON array file as a Map
|
||||
*
|
||||
* Loads the JSON file specified by path containing an array of objects that
|
||||
* each have an id property into a Map from the id to the object.
|
||||
*
|
||||
* @param {string} filePath - The path to the JSON file to load.
|
||||
* @throws {Error} If JSON file did not contain an array.
|
||||
* @throws {Error} If there are objects in the array without an id property.
|
||||
* @throws {Error} If an error occured reading the file.
|
||||
*/
|
||||
async function loadJsonArrayAsMap(filePath) {
|
||||
try {
|
||||
let content = await fs.readFile(filePath);
|
||||
let parsed = JSON.parse(content);
|
||||
|
||||
if (parsed === null) {
|
||||
throw new Error(`Expected array but got null`);
|
||||
}
|
||||
|
||||
if (typeof parsed !== "object") {
|
||||
throw new Error(`Expected array but got ${typeof parsed}`);
|
||||
}
|
||||
|
||||
if (!(parsed instanceof Array)) {
|
||||
throw new Error(`Expected array but got object`);
|
||||
}
|
||||
|
||||
let map = new Map();
|
||||
for (let element of parsed) {
|
||||
if (element === null || element instanceof Array || typeof element !== "object") {
|
||||
throw new Error(`Expected all elements to be objects`);
|
||||
}
|
||||
|
||||
if (element.id === undefined) {
|
||||
throw new Error(`Expected all elements to have an id property`);
|
||||
}
|
||||
|
||||
map.set(element.id, element);
|
||||
}
|
||||
return map;
|
||||
|
||||
} catch (err) {
|
||||
if (err.code == "ENOENT") {
|
||||
// File does not exist, return empty map
|
||||
return new Map();
|
||||
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a Map as a JSON array file
|
||||
*
|
||||
* Save the values of a Map with objects containing an id property that is
|
||||
* equal to the key the objects are stored at into a JSON file.
|
||||
*
|
||||
* @param {string} filePath - The path to the JSON file that will be saved.
|
||||
* @param {Map} map -
|
||||
* Map with objects containing an id property equal to the key they are
|
||||
* stored under.
|
||||
* @throws {Error} if an error occured writing to the file.
|
||||
*/
|
||||
async function saveMapAsJsonArray(filePath, map) {
|
||||
await fs.outputFile(filePath, JSON.stringify([...map.values()], null, 4));
|
||||
}
|
||||
|
||||
|
||||
|
||||
function checkName(name) {
|
||||
if (typeof name !== "string") {
|
||||
@@ -227,5 +298,7 @@ module.exports = {
|
||||
mapToObject,
|
||||
loadJsonAsMap,
|
||||
saveMapAsJson,
|
||||
loadJsonArrayAsMap,
|
||||
saveMapAsJsonArray,
|
||||
ItemDatabase,
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
[null]
|
||||
@@ -0,0 +1 @@
|
||||
[{}]
|
||||
@@ -0,0 +1 @@
|
||||
[{"id":"a"},{"id":"b"}]
|
||||
@@ -0,0 +1,10 @@
|
||||
[
|
||||
[
|
||||
"c",
|
||||
{}
|
||||
],
|
||||
[
|
||||
"d",
|
||||
"foo"
|
||||
]
|
||||
]
|
||||
+74
-1
@@ -60,7 +60,7 @@ describe("lib/database", function() {
|
||||
|
||||
describe("saveMapAsJson()", function() {
|
||||
it("should save a mapping as JSON", async function() {
|
||||
let testFile = 'test/json/save_map.json';
|
||||
let testFile = 'test/temp/save_map.json';
|
||||
async function deleteTestFile() {
|
||||
try {
|
||||
await fs.unlink(testFile);
|
||||
@@ -81,7 +81,80 @@ describe("lib/database", function() {
|
||||
await fs.readFile(testFile, {encoding: 'utf-8'}),
|
||||
'{\n "c": {},\n "d": "foo"\n}'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("loadJsonArrayAsMap()", function() {
|
||||
let badTypes = ['null', 'object', 'number', 'string', 'boolean'];
|
||||
|
||||
for (let type of badTypes) {
|
||||
it(`should reject on ${type} JSON`, async function() {
|
||||
await assert.rejects(
|
||||
database.loadJsonArrayAsMap(`test/json/${type}.json`),
|
||||
new Error(`Expected array but got ${type}`)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
it("should reject on null element", async function() {
|
||||
await assert.rejects(
|
||||
database.loadJsonArrayAsMap('test/json/array_null.json'),
|
||||
new Error("Expected all elements to be objects")
|
||||
);
|
||||
});
|
||||
|
||||
it("should reject on element missing id", async function() {
|
||||
await assert.rejects(
|
||||
database.loadJsonArrayAsMap('test/json/array_object.json'),
|
||||
new Error("Expected all elements to have an id property")
|
||||
);
|
||||
});
|
||||
|
||||
it("should work on empty array JSON", async function() {
|
||||
assert.deepEqual(
|
||||
await database.loadJsonArrayAsMap('test/json/array.json'),
|
||||
new Map()
|
||||
);
|
||||
});
|
||||
|
||||
it("should work on array JSON", async function() {
|
||||
assert.deepEqual(
|
||||
await database.loadJsonArrayAsMap('test/json/load_array_map.json'),
|
||||
new Map([['a', {id: 'a'}], ['b', {id: 'b'}]])
|
||||
);
|
||||
});
|
||||
|
||||
it("should give an empty Map for non-existant file", async function() {
|
||||
assert.deepEqual(
|
||||
await database.loadJsonArrayAsMap('test/json/does-not-exist'),
|
||||
new Map()
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("saveMapAsJsonArray()", function() {
|
||||
it("should save a mapping as JSON", async function() {
|
||||
let testFile = 'test/temp/save_array_map.json';
|
||||
async function deleteTestFile() {
|
||||
try {
|
||||
await fs.unlink(testFile);
|
||||
} catch (err) {
|
||||
/* istanbul ignore if */
|
||||
if (err.code !== 'ENOENT') {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await deleteTestFile();
|
||||
await database.saveMapAsJsonArray(
|
||||
testFile, new Map([['c', {id: 'c'}], ['d', {id: 'd'}]])
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
await fs.readFile(testFile, {encoding: 'utf-8'}),
|
||||
'[\n {\n "id": "c"\n },\n {\n "id": "d"\n }\n]'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in new issue
Block a user