@webiny/commodo-fields-storage-db-proxy
Version:
A MongoDB driver for the [fields-storage](../fields-storage) package.
256 lines (210 loc) • 7.05 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _lambda = _interopRequireDefault(require("aws-sdk/clients/lambda"));
var _bson = require("bson");
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
const MONGO_CONNECTION_ERRORS = ["MongoServerSelectionError", "MongoNetworkError"];
class DbProxyClient {
constructor({
dbProxyFunction
}) {
(0, _defineProperty2.default)(this, "dbProxyFunction", void 0);
this.dbProxyFunction = dbProxyFunction;
}
async runOperation(requestPayload) {
const singleOperation = !Array.isArray(requestPayload);
const Lambda = new _lambda.default({
region: process.env.AWS_REGION
});
const {
Payload
} = await Lambda.invoke({
FunctionName: this.dbProxyFunction,
Payload: JSON.stringify({
body: _bson.EJSON.stringify({
operations: singleOperation ? [requestPayload] : requestPayload
})
})
}).promise();
let parsedPayload;
try {
parsedPayload = JSON.parse(Payload);
} catch (e) {
throw new Error("Could not JSON.parse DB Proxy's response.");
}
if (parsedPayload.error) {
console.log("[commodo-fields-storage-db-proxy error:]", parsedPayload.error);
if (MONGO_CONNECTION_ERRORS.includes(parsedPayload.error.name)) {
throw new Error(`Could not connect to the MongoDB server, make sure the connection string is correct and that the database server allows outside connections. Check https://docs.webiny.com/docs/get-started/quick-start#3-setup-database-connection for more information.`);
}
throw new Error(`${parsedPayload.error.name}: ${parsedPayload.error.message}`);
}
if (!parsedPayload.response) {
throw new Error(`Missing "response" key in received DB Proxy's response.`);
}
const {
results
} = _bson.EJSON.parse(parsedPayload.response);
if (singleOperation) {
return results[0];
}
return results;
}
}
class DbProxyDriver {
constructor({
dbProxyFunction = process.env.DB_PROXY_FUNCTION
} = {}) {
(0, _defineProperty2.default)(this, "client", void 0);
this.client = new DbProxyClient({
dbProxyFunction
});
}
async create(items) {
const payload = items.map(({
name,
data
}) => {
return {
collection: this.getCollectionName(name),
operation: ["insertOne", data]
};
});
await this.client.runOperation(payload);
return true;
}
async update(items) {
const payload = items.map(({
name,
query,
data
}) => {
return {
collection: this.getCollectionName(name),
operation: ["updateOne", query, {
$set: data
}]
};
});
await this.client.runOperation(payload);
return true;
}
async delete({
name,
options
}) {
const clonedOptions = _objectSpread({}, options);
DbProxyDriver.__prepareSearchOption(clonedOptions);
await this.client.runOperation({
collection: this.getCollectionName(name),
operation: ["deleteMany", clonedOptions.query]
});
return true;
}
async find({
name,
options
}) {
const clonedOptions = _objectSpread({
limit: 0,
offset: 0
}, options);
DbProxyDriver.__prepareSearchOption(clonedOptions);
DbProxyDriver.__prepareProjectFields(clonedOptions);
const results = await this.client.runOperation({
collection: this.getCollectionName(name),
operation: ["find", clonedOptions.query, {
limit: clonedOptions.limit,
sort: clonedOptions.sort,
offset: clonedOptions.offset,
project: clonedOptions.project
}]
});
return [!Array.isArray(results) ? [] : results, {}];
}
async findOne({
name,
options
}) {
const clonedOptions = _objectSpread({}, options);
DbProxyDriver.__prepareSearchOption(clonedOptions);
DbProxyDriver.__prepareProjectFields(clonedOptions); // Get first documents from cursor using each
const results = await this.client.runOperation({
collection: this.getCollectionName(name),
operation: ["find", clonedOptions.query, {
limit: 1,
sort: clonedOptions.sort,
project: clonedOptions.project
}]
});
return results[0];
}
async count({
name,
options
}) {
const clonedOptions = _objectSpread({}, options);
DbProxyDriver.__prepareSearchOption(clonedOptions); // Get first documents from cursor using each
return await this.client.runOperation({
collection: this.getCollectionName(name),
operation: ["count", clonedOptions.query]
});
}
getCollectionName(name) {
return name;
}
getClient() {
return this.client;
}
static __prepareSearchOption(options) {
// Here we handle search (if passed) - we transform received arguments into linked LIKE statements.
if (options.search && options.search.query) {
const {
query,
operator,
fields
} = options.search;
const searches = [];
fields.forEach(field => {
searches.push({
[field]: {
$regex: `.*${query}.*`,
$options: "i"
}
});
});
const search = {
[operator === "and" ? "$and" : "$or"]: searches
};
if (options.query instanceof Object) {
options.query = {
$and: [search, options.query]
};
} else {
options.query = search;
}
delete options.search;
}
}
static __prepareProjectFields(options) {
// Here we convert requested fields into a "project" parameter
if (options.fields) {
options.project = options.fields.reduce((acc, item) => {
acc[item] = 1;
return acc;
}, {
id: 1
});
delete options.fields;
}
}
}
var _default = DbProxyDriver;
exports.default = _default;
//# sourceMappingURL=DbProxyDriver.js.map