158 lines
3.9 KiB
JavaScript
158 lines
3.9 KiB
JavaScript
"use strict";
|
|
|
|
const _ = require(`lodash`);
|
|
|
|
const fs = require(`fs-extra`);
|
|
|
|
const path = require(`path`);
|
|
|
|
const loki = require(`lokijs`);
|
|
|
|
const uuidv4 = require(`uuid/v4`);
|
|
|
|
const customComparators = require(`./custom-comparators`); // Ensure sorting behavior matches old lodash `orderBy`
|
|
// implementation. See `custom-comparators.js` for why.
|
|
|
|
|
|
loki.Comparators.lt = customComparators.ltHelper;
|
|
loki.Comparators.gt = customComparators.gtHelper; // Loki is a document store with the same semantics as mongo. This
|
|
// means there are no tables or relationships. Just a bunch of
|
|
// collections, each with objects.
|
|
//
|
|
// Gatsby stores nodes in collections by splitting them up by their
|
|
// `node.internal.type`. All nodes of a particular type go in 1
|
|
// collection. The below `colls` object contains the metadata for
|
|
// these collections, and the "meta collections" used to track them.
|
|
//
|
|
// You won't use these directly. They are used by the collection
|
|
// functions in `./nodes.js`. E.g `getTypeCollName()` and
|
|
// `getNodeTypeCollection`
|
|
|
|
const colls = {
|
|
// Each object has keys `id` and `typeCollName`. It's a way of
|
|
// quickly looking up the collection that a node is contained in.
|
|
// E.g { id: `someNodeId`, typeCollName: `gatsby:nodeType:myType` }
|
|
nodeMeta: {
|
|
name: `gatsby:nodeMeta`,
|
|
options: {
|
|
unique: [`id`],
|
|
indices: [`id`]
|
|
}
|
|
},
|
|
// The list of all node type collections. Each object has keys
|
|
// `type` and `collName` so you can quickly look up the collection
|
|
// name for a node type.
|
|
// e.g { type: `myType`, collName: `gatsby:nodeType:myType` }
|
|
nodeTypes: {
|
|
name: `gatsby:nodeTypes`,
|
|
options: {
|
|
unique: [`type`, `collName`],
|
|
indices: [`type`]
|
|
}
|
|
} // Must be set using `start()`
|
|
|
|
};
|
|
let db;
|
|
/**
|
|
* Ensures that the collections that support nodes have been
|
|
* created. See `colls` var in this file
|
|
*/
|
|
|
|
function ensureNodeCollections(db) {
|
|
_.forEach(colls, collInfo => {
|
|
const {
|
|
name,
|
|
options
|
|
} = collInfo;
|
|
db.addCollection(name, options);
|
|
});
|
|
}
|
|
|
|
function startFileDb(saveFile) {
|
|
return new Promise((resolve, reject) => {
|
|
const dbOptions = {
|
|
autoload: true,
|
|
autoloadCallback: err => {
|
|
if (err) {
|
|
reject(err);
|
|
} else {
|
|
resolve();
|
|
}
|
|
}
|
|
};
|
|
db = new loki(saveFile, dbOptions);
|
|
});
|
|
}
|
|
|
|
async function startInMemory() {
|
|
// Use uuid purely for a random name
|
|
db = new loki(uuidv4());
|
|
}
|
|
/**
|
|
* Starts a loki database. If the file already exists, it will be
|
|
* loaded as the database state. If not, a new database will be
|
|
* created. If `saveFile` is omitted, an in-memory DB will be created.
|
|
*
|
|
* @param {string} saveFile on disk file that the database will be
|
|
* saved and loaded from. If this is omitted, an in-memory database
|
|
* will be created instead
|
|
* @returns {Promise} promise that is resolved once the database and
|
|
* the existing state has been loaded (if there was an existing
|
|
* saveFile)
|
|
*/
|
|
|
|
|
|
async function start({
|
|
saveFile
|
|
} = {}) {
|
|
if (saveFile && !_.isString(saveFile)) {
|
|
throw new Error(`saveFile must be a path`);
|
|
}
|
|
|
|
if (saveFile) {
|
|
const saveDir = path.dirname(saveFile);
|
|
await fs.ensureDir(saveDir);
|
|
await startFileDb(saveFile);
|
|
} else {
|
|
await startInMemory();
|
|
}
|
|
|
|
ensureNodeCollections(db);
|
|
} // Saves the database to disk and returns a promise that will be
|
|
// resolved once the save has finished
|
|
|
|
|
|
function saveState() {
|
|
return new Promise((resolve, reject) => {
|
|
if (db) {
|
|
db.saveDatabase(err => {
|
|
if (err) {
|
|
reject(err);
|
|
} else {
|
|
resolve();
|
|
}
|
|
});
|
|
} else {
|
|
reject(`No database found.`);
|
|
}
|
|
});
|
|
}
|
|
/**
|
|
* Returns a reference to the database. If undefined, the db has not been
|
|
* initialized yet. Call `start()`
|
|
*
|
|
* @returns {Object} database, or undefined
|
|
*/
|
|
|
|
|
|
function getDb() {
|
|
return db;
|
|
}
|
|
|
|
module.exports = {
|
|
start,
|
|
getDb,
|
|
colls,
|
|
saveState
|
|
};
|
|
//# sourceMappingURL=index.js.map
|