feathers-nedb
Version:
Feathers NeDB Service
202 lines • 7.5 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.NeDbAdapter = void 0;
const adapter_commons_1 = require("@feathersjs/adapter-commons");
const commons_1 = require("@feathersjs/commons");
const errors_1 = require("@feathersjs/errors");
const crypto_1 = __importDefault(require("crypto"));
function errorHandler(error) {
throw error;
}
class NeDbAdapter extends adapter_commons_1.AdapterBase {
constructor(options) {
if (!options || !options.Model) {
throw new Error("NeDB datastore `Model` needs to be provided");
}
super({
id: "_id",
...options,
});
}
getSelect(select) {
if (Array.isArray(select)) {
const result = { [this.id]: 1 };
select.forEach((name) => (result[name] = 1));
return result;
}
return select;
}
filterQuery(id, params) {
const options = this.getOptions(params);
const { $select, $sort, $limit: _limit, $skip = 0, ...query } = (params.query || {});
const $limit = (0, adapter_commons_1.getLimit)(_limit, options.paginate);
if (id !== null) {
query.$and = (query.$and || []).concat({
[this.id]: id,
});
}
return {
filters: { $select, $sort, $limit, $skip },
query,
};
}
async _findOrGet(id, params) {
return id === null ? await this._find(params) : await this._get(id, params);
}
normalizeId(id, data) {
if (id !== null) {
// If not using the default Mongo _id field set the ID to its
// previous value. This prevents orphaned documents.
return {
...data,
[this.id]: id,
};
}
return data;
}
async _find(params = {}) {
const { Model, paginate } = this.getOptions(params);
const { filters: { $select, $sort, $limit, $skip }, query, } = this.filterQuery(null, params);
const countDocuments = async () => {
if (paginate && paginate.default) {
return await Model.countAsync(query);
}
return Promise.resolve(0);
};
const q = $select
? Model.findAsync(query, this.getSelect($select))
: Model.findAsync(query);
// Handle $sort
if ($sort) {
q.sort($sort);
}
// Handle $limit
if ($limit) {
q.limit($limit);
}
if ($skip) {
q.skip($skip);
}
const [request, total] = await Promise.all([q, countDocuments()]);
const page = {
total,
limit: $limit,
skip: $skip || 0,
data: $limit === 0 ? [] : (await request),
};
return paginate && paginate.default ? page : page.data;
}
_get(id, params = {}) {
const { Model } = this.getOptions(params);
const { query, filters: { $select }, } = this.filterQuery(id, params);
return $select
? Model.findOneAsync(query, this.getSelect($select))
: Model.findOneAsync(query)
.then((data) => {
if (data == null) {
throw new errors_1.NotFound(`No record found for id '${id}'`);
}
return data;
})
.catch(errorHandler);
}
async _create(_data, params = {}) {
if (Array.isArray(_data) && !this.allowsMulti("create", params)) {
throw new errors_1.MethodNotAllowed("Can not create multiple entries");
}
const { Model } = this.getOptions(params);
const addId = (item) => {
if (this.id !== "_id" && item[this.id] === undefined) {
return Object.assign({
[this.id]: crypto_1.default.randomBytes(8).toString("hex"),
}, item);
}
return item;
};
const data = Array.isArray(_data) ? _data.map(addId) : addId(_data);
//@ts-ignore
return Model.insertAsync(data)
.then((0, adapter_commons_1.select)(params, this.id))
.catch(errorHandler);
}
async _update(id, data, params = {}) {
if (id === null || Array.isArray(data)) {
throw new errors_1.BadRequest("You can not replace multiple instances. Did you mean 'patch'?");
}
const { Model } = this.getOptions(params);
const { query } = this.filterQuery(id, params);
const entry = commons_1._.omit(data, "_id");
if (this.id !== "_id" || (params.nedb && params.nedb.upsert)) {
entry[this.id] = id;
}
const response = await Model.updateAsync(query, entry, {
returnUpdatedDocs: true,
multi: false,
...params.nedb,
});
if (response.affectedDocuments == null) {
throw new errors_1.NotFound(`No record found for id '${id}'`);
}
if (Array.isArray(response.affectedDocuments)) {
return response.affectedDocuments[0];
}
return (0, adapter_commons_1.select)(params, this.id)(response.affectedDocuments);
}
async _patch(id, data, params = {}) {
if (id === null && !this.allowsMulti("patch", params)) {
throw new errors_1.MethodNotAllowed("Can not patch multiple entries");
}
const { Model } = this.getOptions(params);
const { query, filters: { $select, $sort, $limit, $skip }, } = this.filterQuery(id, params);
const updateOptions = {
returnUpdatedDocs: true,
multi: id == null ? true : false,
};
//@ts-ignore
const updateData = Object.keys(data).reduce((result, key) => {
if (key.indexOf("$") === 0) {
//@ts-ignore
result[key] = data[key];
}
else if (key !== "_id" && key !== this.id) {
//@ts-ignore
result.$set[key] = data[key];
}
return result;
}, { $set: {} });
const response = await Model.updateAsync(query, updateData, updateOptions);
if (response.affectedDocuments == null) {
throw new errors_1.NotFound(`No record found for id '${id}'`);
}
return (0, adapter_commons_1.select)(params, this.id)(response.affectedDocuments);
}
async _remove(id, params = {}) {
if (id === null && !this.allowsMulti("remove", params)) {
throw new errors_1.MethodNotAllowed("Can not remove multiple entries");
}
const { Model } = this.getOptions(params);
const { query, filters: { $select }, } = this.filterQuery(id, params);
const deleteOptions = {
multi: id == null ? true : false,
};
const findParams = {
...params,
paginate: false,
query: {
...query,
$select,
},
};
return this._findOrGet(id, findParams)
.then(async (items) => {
await Model.removeAsync(query, deleteOptions);
return items;
})
.catch(errorHandler);
}
}
exports.NeDbAdapter = NeDbAdapter;
//# sourceMappingURL=adapter.js.map