git-documentdb
Version:
Offline-first database that syncs with Git
151 lines • 6.3 kB
JavaScript
"use strict";
/**
* GitDocumentDB
* Copyright (c) Hidekazu Kubota
*
* This source code is licensed under the Mozilla Public License Version 2.0
* found in the LICENSE file in the root directory of gitDDB source tree.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.putWorker = exports.putImpl = void 0;
const path_1 = __importDefault(require("path"));
const fs_extra_1 = __importDefault(require("fs-extra"));
const isomorphic_git_1 = __importDefault(require("isomorphic-git"));
const utils_1 = require("../utils");
const const_1 = require("../const");
const error_1 = require("../error");
/**
* Common implementation of put-like commands.
*
* @throws {@link Err.DatabaseClosingError}
* @throws {@link Err.RepositoryNotOpenError}
* @throws {@link Err.TaskCancelError}
*
* @throws # Errors from putWorker
* @throws {@link Err.UndefinedDBError}
* @throws {@link Err.CannotCreateDirectoryError}
* @throws {@link Err.SameIdExistsError}
* @throws {@link Err.DocumentNotFoundError}
* @throws {@link Err.CannotWriteDataError}
*
* @internal
*/
// eslint-disable-next-line complexity
function putImpl(gitDDB, collectionPath, shortId, shortName, data, options) {
var _a, _b, _c;
if (gitDDB.isClosing) {
return Promise.reject(new error_1.Err.DatabaseClosingError());
}
if (!gitDDB.isOpened) {
return Promise.reject(new error_1.Err.RepositoryNotOpenError());
}
options !== null && options !== void 0 ? options : (options = {
commitMessage: undefined,
insertOrUpdate: undefined,
taskId: undefined,
enqueueCallback: undefined,
debounceTime: undefined,
});
(_a = options.debounceTime) !== null && _a !== void 0 ? _a : (options.debounceTime = -1);
const fullDocPath = collectionPath + shortName;
const commitMessage = (_b = options.commitMessage) !== null && _b !== void 0 ? _b : `<%insertOrUpdate%>: ${fullDocPath}(<%file_oid%>)`;
const taskId = (_c = options.taskId) !== null && _c !== void 0 ? _c : gitDDB.taskQueue.newTaskId();
// put() must be serial.
return new Promise((resolve, reject) => {
gitDDB.taskQueue.pushToTaskQueue({
label: options.insertOrUpdate === undefined ? 'put' : options.insertOrUpdate,
taskId: taskId,
shortId,
shortName,
collectionPath,
debounceTime: options.debounceTime,
func: (beforeResolve, beforeReject) => putWorker(gitDDB, collectionPath, shortName, data, commitMessage, options.insertOrUpdate)
.then(result => {
beforeResolve();
resolve(result);
})
.catch(err => {
beforeReject();
reject(err);
}),
cancel: () => {
reject(new error_1.Err.TaskCancelError(taskId));
},
enqueueCallback: options === null || options === void 0 ? void 0 : options.enqueueCallback,
});
});
}
exports.putImpl = putImpl;
/**
* Add and commit a file
*
* @throws {@link Err.UndefinedDBError}
* @throws {@link Err.CannotCreateDirectoryError}
* @throws {@link Err.SameIdExistsError}
* @throws {@link Err.DocumentNotFoundError}
* @throws {@link Err.CannotWriteDataError}
*/
async function putWorker(gitDDB, collectionPath, shortName, data, commitMessage, insertOrUpdate) {
if (gitDDB === undefined) {
throw new error_1.Err.UndefinedDBError();
}
const fullDocPath = collectionPath + shortName;
let fileOid;
let commit;
const filePath = path_1.default.resolve(gitDDB.workingDir, fullDocPath);
await fs_extra_1.default.ensureDir(path_1.default.dirname(filePath)).catch((err) => {
throw new error_1.Err.CannotCreateDirectoryError(err.message);
});
try {
const headCommit = await isomorphic_git_1.default
.resolveRef({ fs: fs_extra_1.default, dir: gitDDB.workingDir, ref: 'HEAD' })
.catch(() => undefined);
const oldEntryExists = fs_extra_1.default.existsSync(filePath);
if (oldEntryExists) {
if (insertOrUpdate === 'insert')
return Promise.reject(new error_1.Err.SameIdExistsError());
insertOrUpdate !== null && insertOrUpdate !== void 0 ? insertOrUpdate : (insertOrUpdate = 'update');
}
else {
if (insertOrUpdate === 'update')
return Promise.reject(new error_1.Err.DocumentNotFoundError());
insertOrUpdate !== null && insertOrUpdate !== void 0 ? insertOrUpdate : (insertOrUpdate = 'insert');
}
await fs_extra_1.default.writeFile(filePath, data);
await isomorphic_git_1.default.add({ fs: fs_extra_1.default, dir: gitDDB.workingDir, filepath: fullDocPath });
const { oid } = await isomorphic_git_1.default.hashBlob({ object: data });
fileOid = oid;
// isomorphic-git automatically adds trailing LF to commitMessage.
// (Trailing LFs are usually ignored when displaying git log.)
commitMessage = commitMessage
.replace(/<%insertOrUpdate%>/, insertOrUpdate)
.replace(/<%file_oid%>/, fileOid.substr(0, const_1.SHORT_SHA_LENGTH));
// Default ref is HEAD
const commitOid = await isomorphic_git_1.default.commit({
fs: fs_extra_1.default,
dir: gitDDB.workingDir,
author: gitDDB.author,
committer: gitDDB.committer,
message: commitMessage,
});
const readCommitResult = await isomorphic_git_1.default.readCommit({
fs: fs_extra_1.default,
dir: gitDDB.workingDir,
oid: commitOid,
});
commit = (0, utils_1.normalizeCommit)(readCommitResult);
}
catch (err) {
throw new error_1.Err.CannotWriteDataError(err.message);
}
return {
fileOid,
commit,
name: shortName,
};
}
exports.putWorker = putWorker;
//# sourceMappingURL=put.js.map