diff --git a/.gitignore b/.gitignore
index 98bdd26..1a331da 100644
--- a/.gitignore
+++ b/.gitignore
@@ -117,5 +117,4 @@ dist
.DS_store
-# build files
-/lib
\ No newline at end of file
+# build files
\ No newline at end of file
diff --git a/.idea/admin-bro-mongoose.iml b/.idea/admin-bro-mongoose.iml
new file mode 100644
index 0000000..24643cc
--- /dev/null
+++ b/.idea/admin-bro-mongoose.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..8e218a4
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..79ee123
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..03d9549
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..28a804d
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..e5f171d
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..44462e3
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,138 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1620640553632
+
+
+ 1620640553632
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lib/index.d.ts b/lib/index.d.ts
new file mode 100644
index 0000000..dee5c96
--- /dev/null
+++ b/lib/index.d.ts
@@ -0,0 +1,3 @@
+import Database from './src/database';
+import Resource from './src/resource';
+export { Database, Resource };
diff --git a/lib/index.js b/lib/index.js
new file mode 100644
index 0000000..229dcd4
--- /dev/null
+++ b/lib/index.js
@@ -0,0 +1,12 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.Resource = exports.Database = void 0;
+const database_1 = __importDefault(require("./src/database"));
+exports.Database = database_1.default;
+const resource_1 = __importDefault(require("./src/resource"));
+exports.Resource = resource_1.default;
+module.exports = { Database: database_1.default, Resource: resource_1.default };
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/lib/index.js.map b/lib/index.js.map
new file mode 100644
index 0000000..995d5b7
--- /dev/null
+++ b/lib/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;;;;;AAAA,8DAAqC;AAI5B,mBAJF,kBAAQ,CAIE;AAHjB,8DAAqC;AAGlB,mBAHZ,kBAAQ,CAGY;AAD3B,MAAM,CAAC,OAAO,GAAG,EAAE,QAAQ,EAAR,kBAAQ,EAAE,QAAQ,EAAR,kBAAQ,EAAE,CAAA"}
\ No newline at end of file
diff --git a/lib/src/database.d.ts b/lib/src/database.d.ts
new file mode 100644
index 0000000..cb36ba3
--- /dev/null
+++ b/lib/src/database.d.ts
@@ -0,0 +1,8 @@
+import { BaseDatabase } from 'admin-bro';
+declare class Database extends BaseDatabase {
+ private readonly connection;
+ constructor(connection: any);
+ static isAdapterFor(connection: any): boolean;
+ resources(): any;
+}
+export default Database;
diff --git a/lib/src/database.js b/lib/src/database.js
new file mode 100644
index 0000000..6354768
--- /dev/null
+++ b/lib/src/database.js
@@ -0,0 +1,21 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const admin_bro_1 = require("admin-bro");
+const resource_1 = __importDefault(require("./resource"));
+class Database extends admin_bro_1.BaseDatabase {
+ constructor(connection) {
+ super(connection);
+ this.connection = connection;
+ }
+ static isAdapterFor(connection) {
+ return connection.constructor.name === 'Mongoose';
+ }
+ resources() {
+ return this.connection.modelNames().map(name => (new resource_1.default(this.connection.model(name))));
+ }
+}
+exports.default = Database;
+//# sourceMappingURL=database.js.map
\ No newline at end of file
diff --git a/lib/src/database.js.map b/lib/src/database.js.map
new file mode 100644
index 0000000..105fd4e
--- /dev/null
+++ b/lib/src/database.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"database.js","sourceRoot":"","sources":["../../src/database.ts"],"names":[],"mappings":";;;;;AAAA,yCAAwC;AAGxC,0DAAiC;AAEjC,MAAM,QAAS,SAAQ,wBAAY;IAGjC,YAAY,UAAU;QACpB,KAAK,CAAC,UAAU,CAAC,CAAA;QACjB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;IAC9B,CAAC;IAED,MAAM,CAAC,YAAY,CAAC,UAAU;QAC5B,OAAO,UAAU,CAAC,WAAW,CAAC,IAAI,KAAK,UAAU,CAAA;IACnD,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAC9C,IAAI,kBAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAC1C,CAAC,CAAA;IACJ,CAAC;CACF;AAED,kBAAe,QAAQ,CAAA"}
\ No newline at end of file
diff --git a/lib/src/index.d.ts b/lib/src/index.d.ts
new file mode 100644
index 0000000..1732264
--- /dev/null
+++ b/lib/src/index.d.ts
@@ -0,0 +1,8 @@
+/**
+ * @module @admin-bro/mongoose
+ * @subcategory Adapters
+ * @section modules
+ * @load ./index.doc.md
+ */
+export { default as Resource } from './resource';
+export { default as Database } from './database';
diff --git a/lib/src/index.js b/lib/src/index.js
new file mode 100644
index 0000000..16f72a4
--- /dev/null
+++ b/lib/src/index.js
@@ -0,0 +1,17 @@
+"use strict";
+/**
+ * @module @admin-bro/mongoose
+ * @subcategory Adapters
+ * @section modules
+ * @load ./index.doc.md
+ */
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.Database = exports.Resource = void 0;
+var resource_1 = require("./resource");
+Object.defineProperty(exports, "Resource", { enumerable: true, get: function () { return __importDefault(resource_1).default; } });
+var database_1 = require("./database");
+Object.defineProperty(exports, "Database", { enumerable: true, get: function () { return __importDefault(database_1).default; } });
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/lib/src/index.js.map b/lib/src/index.js.map
new file mode 100644
index 0000000..c279451
--- /dev/null
+++ b/lib/src/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;AAEH,uCAAgD;AAAvC,qHAAA,OAAO,OAAY;AAC5B,uCAAgD;AAAvC,qHAAA,OAAO,OAAY"}
\ No newline at end of file
diff --git a/lib/src/property.d.ts b/lib/src/property.d.ts
new file mode 100644
index 0000000..8ffcc93
--- /dev/null
+++ b/lib/src/property.d.ts
@@ -0,0 +1,43 @@
+import { BaseProperty } from 'admin-bro';
+declare class Property extends BaseProperty {
+ mongoosePath: any;
+ /**
+ * Crates an object from mongoose schema path
+ *
+ * @param {SchemaString} path
+ * @param {String[]} path.enumValues
+ * @param {String} path.regExp
+ * @param {String} path.path
+ * @param {String} path.instance
+ * @param {Object[]} path.validators
+ * @param {Object[]} path.setters
+ * @param {Object[]} path.getters
+ * @param {Object} path.options
+ * @param {Object} path._index
+ * @param {number} position
+ *
+ * @private
+ *
+ * @example
+ *
+ * const schema = new mongoose.Schema({
+ * email: String,
+ * })
+ *
+ * property = new Property(schema.paths.email))
+ */
+ constructor(path: any, position?: number);
+ instanceToType(mongooseInstance: any): "string" | "number" | "boolean" | "datetime" | "mixed" | "reference" | "float";
+ name(): any;
+ isEditable(): boolean;
+ reference(): any;
+ isVisible(): boolean;
+ isId(): boolean;
+ availableValues(): any;
+ isArray(): boolean;
+ subProperties(): Property[];
+ type(): "string" | "number" | "boolean" | "datetime" | "mixed" | "reference" | "float";
+ isSortable(): boolean;
+ isRequired(): boolean;
+}
+export default Property;
diff --git a/lib/src/property.js b/lib/src/property.js
new file mode 100644
index 0000000..635808e
--- /dev/null
+++ b/lib/src/property.js
@@ -0,0 +1,112 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const admin_bro_1 = require("admin-bro");
+const ID_PROPERTY = '_id';
+const VERSION_KEY_PROPERTY = '__v';
+class Property extends admin_bro_1.BaseProperty {
+ /**
+ * Crates an object from mongoose schema path
+ *
+ * @param {SchemaString} path
+ * @param {String[]} path.enumValues
+ * @param {String} path.regExp
+ * @param {String} path.path
+ * @param {String} path.instance
+ * @param {Object[]} path.validators
+ * @param {Object[]} path.setters
+ * @param {Object[]} path.getters
+ * @param {Object} path.options
+ * @param {Object} path._index
+ * @param {number} position
+ *
+ * @private
+ *
+ * @example
+ *
+ * const schema = new mongoose.Schema({
+ * email: String,
+ * })
+ *
+ * property = new Property(schema.paths.email))
+ */
+ constructor(path, position = 0) {
+ super({ path: path.path, position });
+ this.mongoosePath = path;
+ }
+ instanceToType(mongooseInstance) {
+ switch (mongooseInstance) {
+ case 'String':
+ return 'string';
+ case 'Boolean':
+ return 'boolean';
+ case 'Number':
+ return 'number';
+ case 'Date':
+ return 'datetime';
+ case 'Embedded':
+ return 'mixed';
+ case 'ObjectID':
+ if (this.reference()) {
+ return 'reference';
+ }
+ return 'string';
+ case 'Decimal128':
+ return 'float';
+ default:
+ return 'string';
+ }
+ }
+ name() {
+ return this.mongoosePath.path;
+ }
+ isEditable() {
+ return this.name() !== VERSION_KEY_PROPERTY && this.name() !== ID_PROPERTY;
+ }
+ reference() {
+ if (this.isArray()) {
+ return this.mongoosePath.caster.options && this.mongoosePath.caster.options.ref;
+ }
+ return this.mongoosePath.options && this.mongoosePath.options.ref;
+ }
+ isVisible() {
+ return this.name() !== VERSION_KEY_PROPERTY;
+ }
+ isId() {
+ return this.name() === ID_PROPERTY;
+ }
+ availableValues() {
+ var _a;
+ return ((_a = this.mongoosePath.enumValues) === null || _a === void 0 ? void 0 : _a.length) ? this.mongoosePath.enumValues : null;
+ }
+ isArray() {
+ return this.mongoosePath.instance === 'Array';
+ }
+ subProperties() {
+ if (this.type() === 'mixed') {
+ const subPaths = Object.values(this.mongoosePath.caster.schema.paths);
+ return subPaths.map(p => new Property(p));
+ }
+ return [];
+ }
+ type() {
+ if (this.isArray()) {
+ let { instance } = this.mongoosePath.caster;
+ // For array of embedded schemas mongoose returns null for caster.instance
+ // That is why we have to check if caster has a schema
+ if (!instance && this.mongoosePath.caster.schema) {
+ instance = 'Embedded';
+ }
+ return this.instanceToType(instance);
+ }
+ return this.instanceToType(this.mongoosePath.instance);
+ }
+ isSortable() {
+ return this.type() !== 'mixed' && !this.isArray();
+ }
+ isRequired() {
+ var _a, _b;
+ return !!((_b = (_a = this.mongoosePath.validators) === null || _a === void 0 ? void 0 : _a.find) === null || _b === void 0 ? void 0 : _b.call(_a, validator => validator.type === 'required'));
+ }
+}
+exports.default = Property;
+//# sourceMappingURL=property.js.map
\ No newline at end of file
diff --git a/lib/src/property.js.map b/lib/src/property.js.map
new file mode 100644
index 0000000..03fb448
--- /dev/null
+++ b/lib/src/property.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"property.js","sourceRoot":"","sources":["../../src/property.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/lib/src/resource.d.ts b/lib/src/resource.d.ts
new file mode 100644
index 0000000..2c1dce2
--- /dev/null
+++ b/lib/src/resource.d.ts
@@ -0,0 +1,53 @@
+import { BaseResource } from 'admin-bro';
+import mongoose from 'mongoose';
+import { FindOptions } from './utils/filter.types';
+import Property from './property';
+/**
+ * Adapter for mongoose resource
+ * @private
+ */
+declare class Resource extends BaseResource {
+ private readonly dbType;
+ /**
+ * @typedef {Object} MongooseModel
+ * @private
+ * @see https://mongoosejs.com/docs/models.html
+ */
+ readonly MongooseModel: mongoose.Model;
+ /**
+ * Initialize the class with the Resource name
+ * @param {MongooseModel} MongooseModel Class which subclass mongoose.Model
+ * @memberof Resource
+ */
+ constructor(MongooseModel: any);
+ static isAdapterFor(MoongooseModel: any): boolean;
+ databaseName(): any;
+ databaseType(): string;
+ name(): any;
+ id(): any;
+ get selectFields(): string;
+ properties(): Property[];
+ property(name: string): Property;
+ count(filters?: any): Promise;
+ find(filters: {}, { limit, offset, sort }: FindOptions): Promise;
+ findOne(id: string): Promise;
+ findMany(ids: string[]): Promise;
+ build(params: any): any;
+ create(params: any): Promise;
+ update(id: any, params: any): Promise;
+ delete(id: any): Promise;
+ static stringifyId(mongooseObj: any): any;
+ /**
+ * Check all params against values they hold. In case of wrong value it corrects it.
+ *
+ * What it does exactly:
+ * - changes all empty strings to `null`s for the ObjectID properties.
+ * - changes all empty strings to [] for array fields
+ *
+ * @param {Object} params received from AdminBro form
+ *
+ * @return {Object} converted params
+ */
+ parseParams(params: any): any;
+}
+export default Resource;
diff --git a/lib/src/resource.js b/lib/src/resource.js
new file mode 100644
index 0000000..466db9b
--- /dev/null
+++ b/lib/src/resource.js
@@ -0,0 +1,209 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const admin_bro_1 = require("admin-bro");
+const lodash_1 = require("lodash");
+const property_1 = __importDefault(require("./property"));
+const convert_filter_1 = require("./utils/convert-filter");
+const create_validation_error_1 = require("./utils/create-validation-error");
+const create_duplicate_error_1 = require("./utils/create-duplicate-error");
+const create_cast_error_1 = require("./utils/create-cast-error");
+const errors_1 = __importDefault(require("./utils/errors"));
+const { MONGOOSE_CAST_ERROR, MONGOOSE_DUPLICATE_ERROR_CODE, MONGOOSE_VALIDATION_ERROR } = errors_1.default;
+/**
+ * Adapter for mongoose resource
+ * @private
+ */
+class Resource extends admin_bro_1.BaseResource {
+ /**
+ * Initialize the class with the Resource name
+ * @param {MongooseModel} MongooseModel Class which subclass mongoose.Model
+ * @memberof Resource
+ */
+ constructor(MongooseModel) {
+ super(MongooseModel);
+ this.dbType = 'mongodb';
+ this.MongooseModel = MongooseModel;
+ }
+ static isAdapterFor(MoongooseModel) {
+ return lodash_1.get(MoongooseModel, 'base.constructor.name') === 'Mongoose';
+ }
+ databaseName() {
+ return this.MongooseModel.db.name;
+ }
+ databaseType() {
+ return this.dbType;
+ }
+ name() {
+ return this.MongooseModel.modelName;
+ }
+ id() {
+ return this.MongooseModel.modelName;
+ }
+ get selectFields() {
+ return Object.keys(this.MongooseModel.schema.paths).join(' ');
+ }
+ properties() {
+ return Object.entries(this.MongooseModel.schema.paths).map(([, path], position) => (new property_1.default(path, position)));
+ }
+ property(name) {
+ var _a;
+ return (_a = this.properties().find(property => property.path() === name)) !== null && _a !== void 0 ? _a : null;
+ }
+ async count(filters = null) {
+ return this.MongooseModel.countDocuments(convert_filter_1.convertFilter(filters));
+ }
+ async find(filters = {}, { limit = 20, offset = 0, sort = {} }) {
+ const { direction, sortBy } = sort;
+ const sortingParam = {
+ [sortBy]: direction,
+ };
+ const mongooseObjects = await this.MongooseModel
+ .find(convert_filter_1.convertFilter(filters), {}, {
+ skip: offset, limit, sort: sortingParam, select: this.selectFields
+ });
+ return mongooseObjects.map(mongooseObject => new admin_bro_1.BaseRecord(Resource.stringifyId(mongooseObject), this));
+ }
+ async findOne(id) {
+ const mongooseObject = await this.MongooseModel.findById(id).select(this.selectFields);
+ return new admin_bro_1.BaseRecord(Resource.stringifyId(mongooseObject), this);
+ }
+ async findMany(ids) {
+ const mongooseObjects = await this.MongooseModel.find({ _id: ids }, {}, { select: this.selectFields });
+ return mongooseObjects.map(mongooseObject => (new admin_bro_1.BaseRecord(Resource.stringifyId(mongooseObject), this)));
+ }
+ build(params) {
+ return new admin_bro_1.BaseRecord(Resource.stringifyId(params), this);
+ }
+ async create(params) {
+ const parsedParams = this.parseParams(params);
+ let mongooseDocument = new this.MongooseModel(parsedParams);
+ try {
+ mongooseDocument = await mongooseDocument.save();
+ }
+ catch (error) {
+ if (error.name === MONGOOSE_VALIDATION_ERROR) {
+ throw create_validation_error_1.createValidationError(error);
+ }
+ if (error.code === MONGOOSE_DUPLICATE_ERROR_CODE) {
+ throw create_duplicate_error_1.createDuplicateError(error, mongooseDocument.toJSON());
+ }
+ throw error;
+ }
+ return Resource.stringifyId(mongooseDocument.toObject());
+ }
+ async update(id, params) {
+ const parsedParams = this.parseParams(params);
+ const unflattedParams = admin_bro_1.flat.unflatten(parsedParams);
+ try {
+ const mongooseObject = await this.MongooseModel.findOneAndUpdate({
+ _id: id,
+ }, {
+ $set: unflattedParams,
+ }, {
+ new: true,
+ runValidators: true,
+ });
+ return Resource.stringifyId(mongooseObject.toObject());
+ }
+ catch (error) {
+ if (error.name === MONGOOSE_VALIDATION_ERROR) {
+ throw create_validation_error_1.createValidationError(error);
+ }
+ if (error.code === MONGOOSE_DUPLICATE_ERROR_CODE) {
+ throw create_duplicate_error_1.createDuplicateError(error, unflattedParams);
+ }
+ // In update cast errors are not wrapped into a validation errors (as it happens in create).
+ // that is why we have to have a different way of handling them - check out tests to see
+ // example error
+ if (error.name === MONGOOSE_CAST_ERROR) {
+ throw create_cast_error_1.createCastError(error);
+ }
+ throw error;
+ }
+ }
+ async delete(id) {
+ return this.MongooseModel.findOneAndRemove({ _id: id });
+ }
+ static stringifyId(mongooseObj) {
+ // By default Id field is an ObjectID and when we change entire mongoose model to
+ // raw object it changes _id field not to a string but to an object.
+ // stringify/parse is a path found here: https://github.com/Automattic/mongoose/issues/2790
+ // @todo We can somehow speed this up
+ const strinigified = JSON.stringify(mongooseObj && 'toObject' in mongooseObj ? mongooseObj.toObject({ getters: true, virtuals: true }) : mongooseObj);
+ return JSON.parse(strinigified);
+ }
+ /**
+ * Check all params against values they hold. In case of wrong value it corrects it.
+ *
+ * What it does exactly:
+ * - changes all empty strings to `null`s for the ObjectID properties.
+ * - changes all empty strings to [] for array fields
+ *
+ * @param {Object} params received from AdminBro form
+ *
+ * @return {Object} converted params
+ */
+ parseParams(params) {
+ const parsedParams = { ...params };
+ // this function handles ObjectIDs and Arrays recursively
+ const handleProperty = (prefix = '') => (property) => {
+ const { path, schema, instance, } = property;
+ // mongoose doesn't supply us with the same path as we're using in our data
+ // so we need to improvise
+ const fullPath = [prefix, path].filter(Boolean).join('.');
+ const value = parsedParams[fullPath];
+ // this handles missing ObjectIDs
+ if (instance === 'ObjectID') {
+ if (value === '') {
+ parsedParams[fullPath] = null;
+ }
+ else if (value) {
+ // this works similar as this.stringifyId
+ parsedParams[fullPath] = value.toString();
+ }
+ }
+ // this handles empty Arrays or recurse into all properties of a filled Array
+ if (instance === 'Array') {
+ if (value === '') {
+ parsedParams[fullPath] = [];
+ }
+ else if (schema && schema.paths) { // we only want arrays of objects (with sub-paths)
+ const subProperties = Object.values(schema.paths);
+ // eslint-disable-next-line no-plusplus, no-constant-condition
+ for (let i = 0; true; i++) { // loop over every item
+ const newPrefix = `${fullPath}.${i}`;
+ if (parsedParams[newPrefix] === '') {
+ // this means we have an empty object here
+ parsedParams[newPrefix] = {};
+ }
+ else if (!Object.keys(parsedParams).some(key => key.startsWith(newPrefix))) {
+ // we're past the last index of this array
+ break;
+ }
+ else {
+ // recurse into the object
+ subProperties.forEach(handleProperty(newPrefix));
+ }
+ }
+ }
+ }
+ // this handles all properties of an object
+ if (instance === 'Embedded') {
+ if (parsedParams[fullPath] === '') {
+ parsedParams[fullPath] = {};
+ }
+ else {
+ const subProperties = Object.values(schema.paths);
+ subProperties.forEach(handleProperty(fullPath));
+ }
+ }
+ };
+ this.properties().forEach(({ mongoosePath }) => handleProperty()(mongoosePath));
+ return parsedParams;
+ }
+}
+exports.default = Resource;
+//# sourceMappingURL=resource.js.map
diff --git a/lib/src/resource.js.map b/lib/src/resource.js.map
new file mode 100644
index 0000000..6439dbb
--- /dev/null
+++ b/lib/src/resource.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"resource.js","sourceRoot":"","sources":["../../src/resource.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/lib/src/utils/convert-filter.d.ts b/lib/src/utils/convert-filter.d.ts
new file mode 100644
index 0000000..b1e0baa
--- /dev/null
+++ b/lib/src/utils/convert-filter.d.ts
@@ -0,0 +1,7 @@
+/**
+ * Changes AdminBro's {@link Filter} to an object acceptible by a mongoose query.
+ *
+ * @param {Filter} filter
+ * @private
+ */
+export declare const convertFilter: (filter: any) => any;
diff --git a/lib/src/utils/convert-filter.js b/lib/src/utils/convert-filter.js
new file mode 100644
index 0000000..cf0bf82
--- /dev/null
+++ b/lib/src/utils/convert-filter.js
@@ -0,0 +1,57 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.convertFilter = void 0;
+const escape_regexp_1 = __importDefault(require("escape-regexp"));
+const mongoose_1 = __importDefault(require("mongoose"));
+/**
+ * Changes AdminBro's {@link Filter} to an object acceptible by a mongoose query.
+ *
+ * @param {Filter} filter
+ * @private
+ */
+const convertFilter = (filter) => {
+ if (!filter) {
+ return {};
+ }
+ return filter.reduce((memo, filterProperty) => {
+ const { property, value } = filterProperty;
+ switch (property.type()) {
+ case 'string':
+ return {
+ [property.name()]: { $regex: escape_regexp_1.default(value), $options: 'i' },
+ ...memo,
+ };
+ case 'date':
+ case 'datetime':
+ if (value.from || value.to) {
+ return {
+ [property.name()]: {
+ ...value.from && { $gte: value.from },
+ ...value.to && { $lte: value.to },
+ },
+ ...memo,
+ };
+ }
+ break;
+ case 'id':
+ if (mongoose_1.default.Types.ObjectId.isValid(value)) {
+ return {
+ [property.name()]: value,
+ ...memo,
+ };
+ }
+ return {};
+ default:
+ break;
+ }
+ return {
+ [property.name()]: value,
+ ...memo,
+ };
+ }, {});
+};
+exports.convertFilter = convertFilter;
+//# sourceMappingURL=convert-filter.js.map
\ No newline at end of file
diff --git a/lib/src/utils/convert-filter.js.map b/lib/src/utils/convert-filter.js.map
new file mode 100644
index 0000000..3c68be3
--- /dev/null
+++ b/lib/src/utils/convert-filter.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"convert-filter.js","sourceRoot":"","sources":["../../../src/utils/convert-filter.ts"],"names":[],"mappings":";;;;;;AAAA,kEAAkC;AAClC,wDAA+B;AAE/B;;;;;GAKG;AACI,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,EAAE;IACtC,IAAI,CAAC,MAAM,EAAE;QACX,OAAO,EAAE,CAAA;KACV;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,cAAc,EAAE,EAAE;QAC5C,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,cAAc,CAAA;QAC1C,QAAQ,QAAQ,CAAC,IAAI,EAAE,EAAE;YACzB,KAAK,QAAQ;gBACX,OAAO;oBACL,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,uBAAM,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE;oBAC3D,GAAG,IAAI;iBACR,CAAA;YACH,KAAK,MAAM,CAAC;YACZ,KAAK,UAAU;gBACb,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE,EAAE;oBAC1B,OAAO;wBACL,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE;4BACjB,GAAG,KAAK,CAAC,IAAI,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE;4BACrC,GAAG,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE;yBAClC;wBACD,GAAG,IAAI;qBACR,CAAA;iBACF;gBACD,MAAK;YACP,KAAK,IAAI;gBACP,IAAI,kBAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;oBAC1C,OAAO;wBACL,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK;wBACxB,GAAG,IAAI;qBACR,CAAA;iBACF;gBACD,OAAO,EAAE,CAAA;YACX;gBACE,MAAK;SACN;QACD,OAAO;YACL,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK;YACxB,GAAG,IAAI;SACR,CAAA;IACH,CAAC,EAAE,EAAE,CAAC,CAAA;AACR,CAAC,CAAA;AAxCY,QAAA,aAAa,iBAwCzB"}
\ No newline at end of file
diff --git a/lib/src/utils/create-cast-error.d.ts b/lib/src/utils/create-cast-error.d.ts
new file mode 100644
index 0000000..32c1728
--- /dev/null
+++ b/lib/src/utils/create-cast-error.d.ts
@@ -0,0 +1 @@
+export declare const createCastError: (originalError: any) => any;
diff --git a/lib/src/utils/create-cast-error.js b/lib/src/utils/create-cast-error.js
new file mode 100644
index 0000000..dbeb938
--- /dev/null
+++ b/lib/src/utils/create-cast-error.js
@@ -0,0 +1,19 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.createCastError = void 0;
+const admin_bro_1 = require("admin-bro");
+const createCastError = (originalError) => {
+ // cas error has only the nested path. So when an actual path is 'parents.age'
+ // originalError will have just a 'age'. That is why we are finding first param
+ // with the same value as the error has and path ending the same like path in
+ // originalError or ending with path with array notation: "${path}.0"
+ const errors = {
+ [originalError.path]: {
+ message: originalError.message,
+ type: originalError.kind || originalError.name,
+ },
+ };
+ return new admin_bro_1.ValidationError(errors);
+};
+exports.createCastError = createCastError;
+//# sourceMappingURL=create-cast-error.js.map
\ No newline at end of file
diff --git a/lib/src/utils/create-cast-error.js.map b/lib/src/utils/create-cast-error.js.map
new file mode 100644
index 0000000..1d8a2d7
--- /dev/null
+++ b/lib/src/utils/create-cast-error.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"create-cast-error.js","sourceRoot":"","sources":["../../../src/utils/create-cast-error.ts"],"names":[],"mappings":";;;AAAA,yCAA2C;AAGpC,MAAM,eAAe,GAAG,CAAC,aAAa,EAAmB,EAAE;IAChE,8EAA8E;IAC9E,+EAA+E;IAC/E,6EAA6E;IAC7E,qEAAqE;IACrE,MAAM,MAAM,GAAG;QACb,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE;YACpB,OAAO,EAAE,aAAa,CAAC,OAAO;YAC9B,IAAI,EAAE,aAAa,CAAC,IAAI,IAAI,aAAa,CAAC,IAAI;SAC/C;KACF,CAAA;IACD,OAAO,IAAI,2BAAe,CAAC,MAAM,CAAC,CAAA;AACpC,CAAC,CAAA;AAZY,QAAA,eAAe,mBAY3B"}
\ No newline at end of file
diff --git a/lib/src/utils/create-duplicate-error.d.ts b/lib/src/utils/create-duplicate-error.d.ts
new file mode 100644
index 0000000..599cdc7
--- /dev/null
+++ b/lib/src/utils/create-duplicate-error.d.ts
@@ -0,0 +1,4 @@
+export declare const createDuplicateError: ({ keyValue: duplicateEntry, errmsg }: {
+ keyValue: any;
+ errmsg: any;
+}, document: any) => any;
diff --git a/lib/src/utils/create-duplicate-error.js b/lib/src/utils/create-duplicate-error.js
new file mode 100644
index 0000000..2b94914
--- /dev/null
+++ b/lib/src/utils/create-duplicate-error.js
@@ -0,0 +1,22 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.createDuplicateError = void 0;
+const admin_bro_1 = require("admin-bro");
+const createDuplicateMessage = message => ({
+ type: 'duplicate',
+ message,
+});
+const createDuplicateError = ({ keyValue: duplicateEntry, errmsg }, document) => {
+ if (!duplicateEntry) {
+ const duplicatedKey = Object.keys(document).find(key => errmsg.includes(key));
+ return new admin_bro_1.ValidationError({
+ [duplicatedKey]: createDuplicateMessage(`Record with that ${duplicatedKey} already exists`),
+ });
+ }
+ const [[keyName]] = Object.entries(duplicateEntry);
+ return new admin_bro_1.ValidationError({
+ [keyName]: createDuplicateMessage(`Record with that ${keyName} already exists`),
+ });
+};
+exports.createDuplicateError = createDuplicateError;
+//# sourceMappingURL=create-duplicate-error.js.map
\ No newline at end of file
diff --git a/lib/src/utils/create-duplicate-error.js.map b/lib/src/utils/create-duplicate-error.js.map
new file mode 100644
index 0000000..0f15f26
--- /dev/null
+++ b/lib/src/utils/create-duplicate-error.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"create-duplicate-error.js","sourceRoot":"","sources":["../../../src/utils/create-duplicate-error.ts"],"names":[],"mappings":";;;AAAA,yCAA2C;AAE3C,MAAM,sBAAsB,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC;IACzC,IAAI,EAAE,WAAW;IACjB,OAAO;CACR,CAAC,CAAA;AAEK,MAAM,oBAAoB,GAAG,CAClC,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,EAAE,EAAE,QAAQ,EAC7B,EAAE;IACnB,IAAI,CAAC,cAAc,EAAE;QACnB,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAA;QAE7E,OAAO,IAAI,2BAAe,CAAC;YACzB,CAAC,aAAa,CAAC,EAAE,sBAAsB,CAAC,oBAAoB,aAAa,iBAAiB,CAAC;SAC5F,CAAC,CAAA;KACH;IAED,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAA;IAElD,OAAO,IAAI,2BAAe,CAAC;QACzB,CAAC,OAAO,CAAC,EAAE,sBAAsB,CAAC,oBAAoB,OAAO,iBAAiB,CAAC;KAChF,CAAC,CAAA;AACJ,CAAC,CAAA;AAhBY,QAAA,oBAAoB,wBAgBhC"}
\ No newline at end of file
diff --git a/lib/src/utils/create-validation-error.d.ts b/lib/src/utils/create-validation-error.d.ts
new file mode 100644
index 0000000..d9c4d3c
--- /dev/null
+++ b/lib/src/utils/create-validation-error.d.ts
@@ -0,0 +1 @@
+export declare const createValidationError: (originalError: any) => any;
diff --git a/lib/src/utils/create-validation-error.js b/lib/src/utils/create-validation-error.js
new file mode 100644
index 0000000..20a1faa
--- /dev/null
+++ b/lib/src/utils/create-validation-error.js
@@ -0,0 +1,19 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.createValidationError = void 0;
+const admin_bro_1 = require("admin-bro");
+const createValidationError = (originalError) => {
+ const errors = Object.keys(originalError.errors).reduce((memo, key) => {
+ const { message, kind, name } = originalError.errors[key];
+ return {
+ ...memo,
+ [key]: {
+ message,
+ type: kind || name,
+ },
+ };
+ }, {});
+ return new admin_bro_1.ValidationError(errors);
+};
+exports.createValidationError = createValidationError;
+//# sourceMappingURL=create-validation-error.js.map
\ No newline at end of file
diff --git a/lib/src/utils/create-validation-error.js.map b/lib/src/utils/create-validation-error.js.map
new file mode 100644
index 0000000..b3f868c
--- /dev/null
+++ b/lib/src/utils/create-validation-error.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"create-validation-error.js","sourceRoot":"","sources":["../../../src/utils/create-validation-error.ts"],"names":[],"mappings":";;;AAAA,yCAA2C;AAEpC,MAAM,qBAAqB,GAAG,CAAC,aAAa,EAAmB,EAAE;IACtE,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QACpE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QACzD,OAAO;YACL,GAAG,IAAI;YACP,CAAC,GAAG,CAAC,EAAE;gBACL,OAAO;gBACP,IAAI,EAAE,IAAI,IAAI,IAAI;aACnB;SACF,CAAA;IACH,CAAC,EAAE,EAAE,CAAC,CAAA;IACN,OAAO,IAAI,2BAAe,CAAC,MAAM,CAAC,CAAA;AACpC,CAAC,CAAA;AAZY,QAAA,qBAAqB,yBAYjC"}
\ No newline at end of file
diff --git a/lib/src/utils/errors.d.ts b/lib/src/utils/errors.d.ts
new file mode 100644
index 0000000..6265f3d
--- /dev/null
+++ b/lib/src/utils/errors.d.ts
@@ -0,0 +1,6 @@
+declare const _default: {
+ MONGOOSE_VALIDATION_ERROR: string;
+ MONGOOSE_CAST_ERROR: string;
+ MONGOOSE_DUPLICATE_ERROR_CODE: number;
+};
+export default _default;
diff --git a/lib/src/utils/errors.js b/lib/src/utils/errors.js
new file mode 100644
index 0000000..3f5b6ed
--- /dev/null
+++ b/lib/src/utils/errors.js
@@ -0,0 +1,12 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.default = {
+ // Error thrown by mongoose in case of validation error
+ MONGOOSE_VALIDATION_ERROR: 'ValidationError',
+ // Error thrown by mongoose in case of casting error (writing string to Number field)
+ MONGOOSE_CAST_ERROR: 'CastError',
+ // Error thrown by mongoose in case of inserting duplicate record
+ // with some property marked as `unique`
+ MONGOOSE_DUPLICATE_ERROR_CODE: 11000,
+};
+//# sourceMappingURL=errors.js.map
\ No newline at end of file
diff --git a/lib/src/utils/errors.js.map b/lib/src/utils/errors.js.map
new file mode 100644
index 0000000..e709685
--- /dev/null
+++ b/lib/src/utils/errors.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/utils/errors.ts"],"names":[],"mappings":";;AACA,kBAAe;IACb,uDAAuD;IACvD,yBAAyB,EAAE,iBAAiB;IAE5C,qFAAqF;IACrF,mBAAmB,EAAE,WAAW;IAEhC,iEAAiE;IACjE,wCAAwC;IACxC,6BAA6B,EAAE,KAAK;CACrC,CAAA"}
\ No newline at end of file
diff --git a/lib/src/utils/filter.types.d.ts b/lib/src/utils/filter.types.d.ts
new file mode 100644
index 0000000..4bbfb36
--- /dev/null
+++ b/lib/src/utils/filter.types.d.ts
@@ -0,0 +1,8 @@
+export declare type FindOptions = {
+ limit?: number;
+ offset?: number;
+ sort?: {
+ sortBy?: string;
+ direction?: 'asc' | 'desc';
+ };
+};
diff --git a/lib/src/utils/filter.types.js b/lib/src/utils/filter.types.js
new file mode 100644
index 0000000..ba00d51
--- /dev/null
+++ b/lib/src/utils/filter.types.js
@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=filter.types.js.map
\ No newline at end of file
diff --git a/lib/src/utils/filter.types.js.map b/lib/src/utils/filter.types.js.map
new file mode 100644
index 0000000..c0358d8
--- /dev/null
+++ b/lib/src/utils/filter.types.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"filter.types.js","sourceRoot":"","sources":["../../../src/utils/filter.types.ts"],"names":[],"mappings":""}
\ No newline at end of file
diff --git a/lib/test/database.spec.d.ts b/lib/test/database.spec.d.ts
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/lib/test/database.spec.d.ts
@@ -0,0 +1 @@
+export {};
diff --git a/lib/test/database.spec.js b/lib/test/database.spec.js
new file mode 100644
index 0000000..494836d
--- /dev/null
+++ b/lib/test/database.spec.js
@@ -0,0 +1,19 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const mongoose_1 = __importDefault(require("mongoose"));
+const database_1 = __importDefault(require("../src/database"));
+describe('Database', () => {
+ describe('#resources', () => {
+ let resources;
+ beforeEach(() => {
+ resources = new database_1.default(mongoose_1.default.connection).resources();
+ });
+ it('return all resources', () => {
+ expect(resources.length).toEqual(3);
+ });
+ });
+});
+//# sourceMappingURL=database.spec.js.map
\ No newline at end of file
diff --git a/lib/test/database.spec.js.map b/lib/test/database.spec.js.map
new file mode 100644
index 0000000..b6014bc
--- /dev/null
+++ b/lib/test/database.spec.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"database.spec.js","sourceRoot":"","sources":["../../test/database.spec.ts"],"names":[],"mappings":";;;;;AAAA,wDAA+B;AAC/B,+DAA8C;AAG9C,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE;IACxB,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;QAC1B,IAAI,SAAqB,CAAA;QAEzB,UAAU,CAAC,GAAG,EAAE;YACd,SAAS,GAAG,IAAI,kBAAgB,CAAC,kBAAQ,CAAC,UAAU,CAAC,CAAC,SAAS,EAAE,CAAA;QACnE,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;YAC9B,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;QACrC,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
\ No newline at end of file
diff --git a/lib/test/errors/create-cast-error.spec.d.ts b/lib/test/errors/create-cast-error.spec.d.ts
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/lib/test/errors/create-cast-error.spec.d.ts
@@ -0,0 +1 @@
+export {};
diff --git a/lib/test/errors/create-cast-error.spec.js b/lib/test/errors/create-cast-error.spec.js
new file mode 100644
index 0000000..4f1ba1e
--- /dev/null
+++ b/lib/test/errors/create-cast-error.spec.js
@@ -0,0 +1,20 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const create_cast_error_1 = require("../../src/utils/create-cast-error");
+const mongoose_cast_error_1 = require("../fixtures/mongoose-cast-error");
+const mongoose_cast_array_error_1 = require("../fixtures/mongoose-cast-array-error");
+describe('createCastError', () => {
+ describe('throwin cast error on update after one key has error', () => {
+ it('has error for nested "parent.age" (errorKey) field', () => {
+ const error = create_cast_error_1.createCastError(mongoose_cast_error_1.SAMPLE_CAST_ERROR);
+ expect(error.propertyErrors.age.type).toEqual('Number');
+ });
+ });
+ describe('throwing cast error on update when one array field has error', () => {
+ it('throws an error for root field', () => {
+ const error = create_cast_error_1.createCastError(mongoose_cast_array_error_1.SAMPLE_CAST_ARRAY_ERROR);
+ expect(error.propertyErrors.authors.type).toEqual('ObjectId');
+ });
+ });
+});
+//# sourceMappingURL=create-cast-error.spec.js.map
\ No newline at end of file
diff --git a/lib/test/errors/create-cast-error.spec.js.map b/lib/test/errors/create-cast-error.spec.js.map
new file mode 100644
index 0000000..2819540
--- /dev/null
+++ b/lib/test/errors/create-cast-error.spec.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"create-cast-error.spec.js","sourceRoot":"","sources":["../../../test/errors/create-cast-error.spec.ts"],"names":[],"mappings":";;AAAA,yEAAmE;AACnE,yEAAmE;AACnE,qFAA+E;AAE/E,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,QAAQ,CAAC,sDAAsD,EAAE,GAAG,EAAE;QACpE,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;YAC5D,MAAM,KAAK,GAAG,mCAAe,CAAC,uCAAiB,CAAC,CAAA;YAEhD,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QACzD,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,QAAQ,CAAC,8DAA8D,EAAE,GAAG,EAAE;QAC5E,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,KAAK,GAAG,mCAAe,CAAC,mDAAuB,CAAC,CAAA;YAEtD,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;QAC/D,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
\ No newline at end of file
diff --git a/lib/test/errors/create-validation-error.spec.d.ts b/lib/test/errors/create-validation-error.spec.d.ts
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/lib/test/errors/create-validation-error.spec.d.ts
@@ -0,0 +1 @@
+export {};
diff --git a/lib/test/errors/create-validation-error.spec.js b/lib/test/errors/create-validation-error.spec.js
new file mode 100644
index 0000000..388d950
--- /dev/null
+++ b/lib/test/errors/create-validation-error.spec.js
@@ -0,0 +1,32 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const create_validation_error_1 = require("../../src/utils/create-validation-error");
+const mongoose_validation_error_1 = require("../fixtures/mongoose-validation-error");
+const mongoose_nested_validation_error_1 = require("../fixtures/mongoose-nested-validation-error");
+describe('#createValidationError', () => {
+ describe('regular error', () => {
+ it('has errors', () => {
+ const error = create_validation_error_1.createValidationError(mongoose_validation_error_1.SAMPLE_VALIDATION_ERROR);
+ expect(Object.keys(error.propertyErrors).length).toEqual(2);
+ });
+ it('has error for email', () => {
+ const error = create_validation_error_1.createValidationError(mongoose_validation_error_1.SAMPLE_VALIDATION_ERROR);
+ expect(error.propertyErrors.email.type).toEqual('required');
+ });
+ });
+ describe('error for nested field', () => {
+ it('2 errors, one for root field and one for an actual nested field', () => {
+ const error = create_validation_error_1.createValidationError(mongoose_nested_validation_error_1.SAMPLE_NESTED_VALIDATION_ERROR);
+ expect(Object.keys(error.propertyErrors).length).toEqual(2);
+ });
+ it('has error for nested "parent.age" field', () => {
+ const error = create_validation_error_1.createValidationError(mongoose_nested_validation_error_1.SAMPLE_NESTED_VALIDATION_ERROR);
+ expect(error.propertyErrors['parent.age'].type).toEqual('Number');
+ });
+ it('has error for "parent" field', () => {
+ const error = create_validation_error_1.createValidationError(mongoose_nested_validation_error_1.SAMPLE_NESTED_VALIDATION_ERROR);
+ expect(error.propertyErrors.parent.type).toEqual('ValidationError');
+ });
+ });
+});
+//# sourceMappingURL=create-validation-error.spec.js.map
\ No newline at end of file
diff --git a/lib/test/errors/create-validation-error.spec.js.map b/lib/test/errors/create-validation-error.spec.js.map
new file mode 100644
index 0000000..7d32ede
--- /dev/null
+++ b/lib/test/errors/create-validation-error.spec.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"create-validation-error.spec.js","sourceRoot":"","sources":["../../../test/errors/create-validation-error.spec.ts"],"names":[],"mappings":";;AAAA,qFAA+E;AAC/E,qFAA+E;AAC/E,mGAA6F;AAE7F,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;QAC7B,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE;YACpB,MAAM,KAAK,GAAG,+CAAqB,CAAC,mDAAuB,CAAC,CAAA;YAE5D,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;QAC7D,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;YAC7B,MAAM,KAAK,GAAG,+CAAqB,CAAC,mDAAuB,CAAC,CAAA;YAE5D,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;QAC7D,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;QACtC,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;YACzE,MAAM,KAAK,GAAG,+CAAqB,CAAC,iEAA8B,CAAC,CAAA;YAEnE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;QAC7D,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;YACjD,MAAM,KAAK,GAAG,+CAAqB,CAAC,iEAA8B,CAAC,CAAA;YAEnE,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QACnE,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;YACtC,MAAM,KAAK,GAAG,+CAAqB,CAAC,iEAA8B,CAAC,CAAA;YAEnE,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAA;QACrE,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
\ No newline at end of file
diff --git a/lib/test/fixtures/duplicate-error.d.ts b/lib/test/fixtures/duplicate-error.d.ts
new file mode 100644
index 0000000..e69de29
diff --git a/lib/test/fixtures/duplicate-error.js b/lib/test/fixtures/duplicate-error.js
new file mode 100644
index 0000000..4f6e3e1
--- /dev/null
+++ b/lib/test/fixtures/duplicate-error.js
@@ -0,0 +1,8 @@
+module.exports = {
+ driver: true,
+ name: 'MongoError',
+ index: 0,
+ code: 11000,
+ errmsg: 'insertDocument :: caused by :: 11000 E11000 duplicate key error index: admin-bro-mongoose.pesels.$pesel_1 dup key: { : "1" }',
+};
+//# sourceMappingURL=duplicate-error.js.map
\ No newline at end of file
diff --git a/lib/test/fixtures/duplicate-error.js.map b/lib/test/fixtures/duplicate-error.js.map
new file mode 100644
index 0000000..f478813
--- /dev/null
+++ b/lib/test/fixtures/duplicate-error.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"duplicate-error.js","sourceRoot":"","sources":["../../../test/fixtures/duplicate-error.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,GAAG;IACf,MAAM,EAAE,IAAI;IACZ,IAAI,EAAE,YAAY;IAClB,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,KAAK;IACX,MAAM,EAAE,+HAA+H;CACxI,CAAA"}
\ No newline at end of file
diff --git a/lib/test/fixtures/mongoose-cast-array-error.d.ts b/lib/test/fixtures/mongoose-cast-array-error.d.ts
new file mode 100644
index 0000000..23c7af5
--- /dev/null
+++ b/lib/test/fixtures/mongoose-cast-array-error.d.ts
@@ -0,0 +1,9 @@
+export declare const SAMPLE_CAST_ARRAY_ERROR: {
+ stringValue: string;
+ kind: string;
+ value: string;
+ path: string;
+ reason: {};
+ message: string;
+ name: string;
+};
diff --git a/lib/test/fixtures/mongoose-cast-array-error.js b/lib/test/fixtures/mongoose-cast-array-error.js
new file mode 100644
index 0000000..aed14d8
--- /dev/null
+++ b/lib/test/fixtures/mongoose-cast-array-error.js
@@ -0,0 +1,13 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.SAMPLE_CAST_ARRAY_ERROR = void 0;
+exports.SAMPLE_CAST_ARRAY_ERROR = {
+ stringValue: '""',
+ kind: 'ObjectId',
+ value: '',
+ path: 'authors',
+ reason: {},
+ message: 'Cast to ObjectId failed for value "" at path "authors"',
+ name: 'CastError',
+};
+//# sourceMappingURL=mongoose-cast-array-error.js.map
\ No newline at end of file
diff --git a/lib/test/fixtures/mongoose-cast-array-error.js.map b/lib/test/fixtures/mongoose-cast-array-error.js.map
new file mode 100644
index 0000000..26cf647
--- /dev/null
+++ b/lib/test/fixtures/mongoose-cast-array-error.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"mongoose-cast-array-error.js","sourceRoot":"","sources":["../../../test/fixtures/mongoose-cast-array-error.ts"],"names":[],"mappings":";;;AAAa,QAAA,uBAAuB,GAAG;IACrC,WAAW,EAAE,IAAI;IACjB,IAAI,EAAE,UAAU;IAChB,KAAK,EAAE,EAAE;IACT,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,EAEP;IACD,OAAO,EAAE,wDAAwD;IACjE,IAAI,EAAE,WAAW;CAClB,CAAA"}
\ No newline at end of file
diff --git a/lib/test/fixtures/mongoose-cast-error.d.ts b/lib/test/fixtures/mongoose-cast-error.d.ts
new file mode 100644
index 0000000..be5b9ca
--- /dev/null
+++ b/lib/test/fixtures/mongoose-cast-error.d.ts
@@ -0,0 +1,24 @@
+export declare const SAMPLE_CAST_ERROR: {
+ stringValue: string;
+ kind: string;
+ value: string;
+ path: string;
+ reason: {
+ stringValue: string;
+ kind: string;
+ value: string;
+ path: string;
+ reason: {
+ generatedMessage: boolean;
+ name: string;
+ code: string;
+ actual: boolean;
+ expected: boolean;
+ operator: string;
+ };
+ message: string;
+ name: string;
+ };
+ message: string;
+ name: string;
+};
diff --git a/lib/test/fixtures/mongoose-cast-error.js b/lib/test/fixtures/mongoose-cast-error.js
new file mode 100644
index 0000000..8c92725
--- /dev/null
+++ b/lib/test/fixtures/mongoose-cast-error.js
@@ -0,0 +1,28 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.SAMPLE_CAST_ERROR = void 0;
+exports.SAMPLE_CAST_ERROR = {
+ stringValue: '"asdasd"',
+ kind: 'Number',
+ value: 'asdasd',
+ path: 'age',
+ reason: {
+ stringValue: '"asdasd"',
+ kind: 'number',
+ value: 'asdasd',
+ path: 'age',
+ reason: {
+ generatedMessage: true,
+ name: 'AssertionError [ERR_ASSERTION]',
+ code: 'ERR_ASSERTION',
+ actual: false,
+ expected: true,
+ operator: '==',
+ },
+ message: 'Cast to number failed for value "asdasd" at path "age"',
+ name: 'CastError',
+ },
+ message: 'Cast to Number failed for value "asdasd" at path "age"',
+ name: 'CastError',
+};
+//# sourceMappingURL=mongoose-cast-error.js.map
\ No newline at end of file
diff --git a/lib/test/fixtures/mongoose-cast-error.js.map b/lib/test/fixtures/mongoose-cast-error.js.map
new file mode 100644
index 0000000..d34d9e6
--- /dev/null
+++ b/lib/test/fixtures/mongoose-cast-error.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"mongoose-cast-error.js","sourceRoot":"","sources":["../../../test/fixtures/mongoose-cast-error.ts"],"names":[],"mappings":";;;AAAa,QAAA,iBAAiB,GAAG;IAC/B,WAAW,EAAE,UAAU;IACvB,IAAI,EAAE,QAAQ;IACd,KAAK,EAAE,QAAQ;IACf,IAAI,EAAE,KAAK;IACX,MAAM,EAAE;QACN,WAAW,EAAE,UAAU;QACvB,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,QAAQ;QACf,IAAI,EAAE,KAAK;QACX,MAAM,EAAE;YACN,gBAAgB,EAAE,IAAI;YACtB,IAAI,EAAE,gCAAgC;YACtC,IAAI,EAAE,eAAe;YACrB,MAAM,EAAE,KAAK;YACb,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,IAAI;SACf;QACD,OAAO,EAAE,wDAAwD;QACjE,IAAI,EAAE,WAAW;KAClB;IACD,OAAO,EAAE,wDAAwD;IACjE,IAAI,EAAE,WAAW;CAClB,CAAA"}
\ No newline at end of file
diff --git a/lib/test/fixtures/mongoose-nested-validation-error.d.ts b/lib/test/fixtures/mongoose-nested-validation-error.d.ts
new file mode 100644
index 0000000..6729627
--- /dev/null
+++ b/lib/test/fixtures/mongoose-nested-validation-error.d.ts
@@ -0,0 +1,46 @@
+export declare const SAMPLE_NESTED_VALIDATION_ERROR: {
+ errors: {
+ 'parent.age': {
+ message: string;
+ name: string;
+ stringValue: string;
+ kind: string;
+ value: string;
+ path: string;
+ reason: {
+ message: string;
+ name: string;
+ stringValue: string;
+ kind: string;
+ value: string;
+ path: string;
+ };
+ };
+ parent: {
+ errors: {
+ age: {
+ message: string;
+ name: string;
+ stringValue: string;
+ kind: string;
+ value: string;
+ path: string;
+ reason: {
+ message: string;
+ name: string;
+ stringValue: string;
+ kind: string;
+ value: string;
+ path: string;
+ };
+ };
+ };
+ _message: string;
+ message: string;
+ name: string;
+ };
+ };
+ _message: string;
+ message: string;
+ name: string;
+};
diff --git a/lib/test/fixtures/mongoose-nested-validation-error.js b/lib/test/fixtures/mongoose-nested-validation-error.js
new file mode 100644
index 0000000..a571d68
--- /dev/null
+++ b/lib/test/fixtures/mongoose-nested-validation-error.js
@@ -0,0 +1,50 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.SAMPLE_NESTED_VALIDATION_ERROR = void 0;
+exports.SAMPLE_NESTED_VALIDATION_ERROR = {
+ errors: {
+ 'parent.age': {
+ message: 'Cast to Number failed for value "not a number" at path "age"',
+ name: 'CastError',
+ stringValue: '"not a number"',
+ kind: 'Number',
+ value: 'not a number',
+ path: 'age',
+ reason: {
+ message: 'Cast to number failed for value "not a number" at path "age"',
+ name: 'CastError',
+ stringValue: '"not a number"',
+ kind: 'number',
+ value: 'not a number',
+ path: 'age',
+ },
+ },
+ parent: {
+ errors: {
+ age: {
+ message: 'Cast to Number failed for value "not a number" at path "age"',
+ name: 'CastError',
+ stringValue: '"not a number"',
+ kind: 'Number',
+ value: 'not a number',
+ path: 'age',
+ reason: {
+ message: 'Cast to number failed for value "not a number" at path "age"',
+ name: 'CastError',
+ stringValue: '"not a number"',
+ kind: 'number',
+ value: 'not a number',
+ path: 'age',
+ },
+ },
+ },
+ _message: 'Validation failed',
+ message: 'Validation failed: age: Cast to Number failed for value "not a number" at path "age"',
+ name: 'ValidationError',
+ },
+ },
+ _message: 'User validation failed',
+ message: 'User validation failed: parent.age: Cast to Number failed for value "not a number" at path "age", parent: Validation failed: age: Cast to Number failed for value "not a number" at path "age"',
+ name: 'ValidationError',
+};
+//# sourceMappingURL=mongoose-nested-validation-error.js.map
\ No newline at end of file
diff --git a/lib/test/fixtures/mongoose-nested-validation-error.js.map b/lib/test/fixtures/mongoose-nested-validation-error.js.map
new file mode 100644
index 0000000..cdea6c6
--- /dev/null
+++ b/lib/test/fixtures/mongoose-nested-validation-error.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"mongoose-nested-validation-error.js","sourceRoot":"","sources":["../../../test/fixtures/mongoose-nested-validation-error.ts"],"names":[],"mappings":";;;AAAa,QAAA,8BAA8B,GAAG;IAC5C,MAAM,EAAE;QACN,YAAY,EAAE;YACZ,OAAO,EAAE,8DAA8D;YACvE,IAAI,EAAE,WAAW;YACjB,WAAW,EAAE,gBAAgB;YAC7B,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,cAAc;YACrB,IAAI,EAAE,KAAK;YACX,MAAM,EAAE;gBACN,OAAO,EAAE,8DAA8D;gBACvE,IAAI,EAAE,WAAW;gBACjB,WAAW,EAAE,gBAAgB;gBAC7B,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,cAAc;gBACrB,IAAI,EAAE,KAAK;aACZ;SACF;QACD,MAAM,EAAE;YACN,MAAM,EAAE;gBACN,GAAG,EAAE;oBACH,OAAO,EAAE,8DAA8D;oBACvE,IAAI,EAAE,WAAW;oBACjB,WAAW,EAAE,gBAAgB;oBAC7B,IAAI,EAAE,QAAQ;oBACd,KAAK,EAAE,cAAc;oBACrB,IAAI,EAAE,KAAK;oBACX,MAAM,EAAE;wBACN,OAAO,EAAE,8DAA8D;wBACvE,IAAI,EAAE,WAAW;wBACjB,WAAW,EAAE,gBAAgB;wBAC7B,IAAI,EAAE,QAAQ;wBACd,KAAK,EAAE,cAAc;wBACrB,IAAI,EAAE,KAAK;qBACZ;iBACF;aACF;YACD,QAAQ,EAAE,mBAAmB;YAC7B,OAAO,EAAE,sFAAsF;YAC/F,IAAI,EAAE,iBAAiB;SACxB;KACF;IACD,QAAQ,EAAE,wBAAwB;IAClC,OAAO,EAAE,gMAAgM;IACzM,IAAI,EAAE,iBAAiB;CACxB,CAAA"}
\ No newline at end of file
diff --git a/lib/test/fixtures/mongoose-validation-error.d.ts b/lib/test/fixtures/mongoose-validation-error.d.ts
new file mode 100644
index 0000000..dad9e1c
--- /dev/null
+++ b/lib/test/fixtures/mongoose-validation-error.d.ts
@@ -0,0 +1,35 @@
+export declare const SAMPLE_VALIDATION_ERROR: {
+ _message: string;
+ errors: {
+ email: {
+ $isValidatorError: boolean;
+ kind: string;
+ message: string;
+ name: string;
+ path: string;
+ properties: {
+ message: string;
+ path: string;
+ type: string;
+ value: string;
+ };
+ value: string;
+ };
+ passwordHash: {
+ $isValidatorError: boolean;
+ kind: string;
+ message: string;
+ name: string;
+ path: string;
+ properties: {
+ message: string;
+ path: string;
+ type: string;
+ value: string;
+ };
+ value: string;
+ };
+ };
+ message: string;
+ name: string;
+};
diff --git a/lib/test/fixtures/mongoose-validation-error.js b/lib/test/fixtures/mongoose-validation-error.js
new file mode 100644
index 0000000..c221e33
--- /dev/null
+++ b/lib/test/fixtures/mongoose-validation-error.js
@@ -0,0 +1,39 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.SAMPLE_VALIDATION_ERROR = void 0;
+exports.SAMPLE_VALIDATION_ERROR = {
+ _message: 'User validation failed',
+ errors: {
+ email: {
+ $isValidatorError: true,
+ kind: 'required',
+ message: 'Path `email` is required.',
+ name: 'ValidatorError',
+ path: 'email',
+ properties: {
+ message: 'Path `email` is required.',
+ path: 'email',
+ type: 'required',
+ value: '',
+ },
+ value: '',
+ },
+ passwordHash: {
+ $isValidatorError: true,
+ kind: 'required',
+ message: 'Path `passwordHash` is required.',
+ name: 'ValidatorError',
+ path: 'passwordHash',
+ properties: {
+ message: 'Path `passwordHash` is required.',
+ path: 'passwordHash',
+ type: 'required',
+ value: '',
+ },
+ value: '',
+ },
+ },
+ message: 'User validation failed: email: Path `email` is required., passwordHash: Path `passwordHash` is required.',
+ name: 'ValidationError',
+};
+//# sourceMappingURL=mongoose-validation-error.js.map
\ No newline at end of file
diff --git a/lib/test/fixtures/mongoose-validation-error.js.map b/lib/test/fixtures/mongoose-validation-error.js.map
new file mode 100644
index 0000000..e8a942d
--- /dev/null
+++ b/lib/test/fixtures/mongoose-validation-error.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"mongoose-validation-error.js","sourceRoot":"","sources":["../../../test/fixtures/mongoose-validation-error.ts"],"names":[],"mappings":";;;AAAa,QAAA,uBAAuB,GAAG;IACrC,QAAQ,EAAE,wBAAwB;IAClC,MAAM,EAAE;QACN,KAAK,EAAE;YACL,iBAAiB,EAAE,IAAI;YACvB,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,2BAA2B;YACpC,IAAI,EAAE,gBAAgB;YACtB,IAAI,EAAE,OAAO;YACb,UAAU,EAAE;gBACV,OAAO,EAAE,2BAA2B;gBACpC,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,UAAU;gBAChB,KAAK,EAAE,EAAE;aACV;YACD,KAAK,EAAE,EAAE;SACV;QACD,YAAY,EAAE;YACZ,iBAAiB,EAAE,IAAI;YACvB,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,kCAAkC;YAC3C,IAAI,EAAE,gBAAgB;YACtB,IAAI,EAAE,cAAc;YACpB,UAAU,EAAE;gBACV,OAAO,EAAE,kCAAkC;gBAC3C,IAAI,EAAE,cAAc;gBACpB,IAAI,EAAE,UAAU;gBAChB,KAAK,EAAE,EAAE;aACV;YACD,KAAK,EAAE,EAAE;SACV;KACF;IACD,OAAO,EAAE,0GAA0G;IACnH,IAAI,EAAE,iBAAiB;CACxB,CAAA"}
\ No newline at end of file
diff --git a/lib/test/fixtures/valid-user-record.d.ts b/lib/test/fixtures/valid-user-record.d.ts
new file mode 100644
index 0000000..d0e01f3
--- /dev/null
+++ b/lib/test/fixtures/valid-user-record.d.ts
@@ -0,0 +1,27 @@
+declare const _default: {
+ email: string;
+ passwordHash: string;
+ 'genre.type': string;
+ 'genre.enum': string;
+ 'arrayed.0': string;
+ 'arrayed.1': string;
+ 'parent.name': string;
+ 'parent.surname': string;
+ 'parent.age': number;
+ 'parent.nestedArray.0.someProperty': number;
+ 'parent.nestedArray.1.someProperty': number;
+ 'parent.nestedObject.someProperty': number;
+ 'family.0.name': string;
+ 'family.0.surname': string;
+ 'family.0.age': number;
+ 'family.0.nestedArray.0.someProperty': number;
+ 'family.0.nestedArray.1.someProperty': number;
+ 'family.0.nestedObject.someProperty': number;
+ 'family.1.name': string;
+ 'family.1.surname': string;
+ 'family.1.age': number;
+ 'family.1.nestedArray.0.someProperty': number;
+ 'family.1.nestedArray.1.someProperty': number;
+ 'family.1.nestedObject.someProperty': number;
+};
+export default _default;
diff --git a/lib/test/fixtures/valid-user-record.js b/lib/test/fixtures/valid-user-record.js
new file mode 100644
index 0000000..b1770c8
--- /dev/null
+++ b/lib/test/fixtures/valid-user-record.js
@@ -0,0 +1,29 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.default = {
+ email: 'john@doe.com',
+ passwordHash: 'somesecretpasswordhash',
+ 'genre.type': 'some type',
+ 'genre.enum': 'male',
+ 'arrayed.0': 'first',
+ 'arrayed.1': 'second',
+ 'parent.name': 'name',
+ 'parent.surname': 'surname',
+ 'parent.age': 12,
+ 'parent.nestedArray.0.someProperty': 12,
+ 'parent.nestedArray.1.someProperty': 12,
+ 'parent.nestedObject.someProperty': 12,
+ 'family.0.name': 'some string',
+ 'family.0.surname': 'some string',
+ 'family.0.age': 13,
+ 'family.0.nestedArray.0.someProperty': 12,
+ 'family.0.nestedArray.1.someProperty': 12,
+ 'family.0.nestedObject.someProperty': 12,
+ 'family.1.name': 'some string',
+ 'family.1.surname': 'some string',
+ 'family.1.age': 14,
+ 'family.1.nestedArray.0.someProperty': 12,
+ 'family.1.nestedArray.1.someProperty': 12,
+ 'family.1.nestedObject.someProperty': 12,
+};
+//# sourceMappingURL=valid-user-record.js.map
\ No newline at end of file
diff --git a/lib/test/fixtures/valid-user-record.js.map b/lib/test/fixtures/valid-user-record.js.map
new file mode 100644
index 0000000..0749f8c
--- /dev/null
+++ b/lib/test/fixtures/valid-user-record.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"valid-user-record.js","sourceRoot":"","sources":["../../../test/fixtures/valid-user-record.ts"],"names":[],"mappings":";;AAAA,kBAAe;IACb,KAAK,EAAE,cAAc;IACrB,YAAY,EAAE,wBAAwB;IACtC,YAAY,EAAE,WAAW;IACzB,YAAY,EAAE,MAAM;IACpB,WAAW,EAAE,OAAO;IACpB,WAAW,EAAE,QAAQ;IACrB,aAAa,EAAE,MAAM;IACrB,gBAAgB,EAAE,SAAS;IAC3B,YAAY,EAAE,EAAE;IAChB,mCAAmC,EAAE,EAAE;IACvC,mCAAmC,EAAE,EAAE;IACvC,kCAAkC,EAAE,EAAE;IACtC,eAAe,EAAE,aAAa;IAC9B,kBAAkB,EAAE,aAAa;IACjC,cAAc,EAAE,EAAE;IAClB,qCAAqC,EAAE,EAAE;IACzC,qCAAqC,EAAE,EAAE;IACzC,oCAAoC,EAAE,EAAE;IACxC,eAAe,EAAE,aAAa;IAC9B,kBAAkB,EAAE,aAAa;IACjC,cAAc,EAAE,EAAE;IAClB,qCAAqC,EAAE,EAAE;IACzC,qCAAqC,EAAE,EAAE;IACzC,oCAAoC,EAAE,EAAE;CACzC,CAAA"}
\ No newline at end of file
diff --git a/lib/test/property.spec.d.ts b/lib/test/property.spec.d.ts
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/lib/test/property.spec.d.ts
@@ -0,0 +1 @@
+export {};
diff --git a/lib/test/property.spec.js b/lib/test/property.spec.js
new file mode 100644
index 0000000..b0ba065
--- /dev/null
+++ b/lib/test/property.spec.js
@@ -0,0 +1,84 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const models_1 = require("./utils/models");
+const property_1 = __importDefault(require("../src/property"));
+describe('Property', () => {
+ describe('#availableValues', () => {
+ it('returns null for all standard (Non enum) values', () => {
+ const property = new property_1.default(models_1.User.schema.paths.email);
+ expect(property.availableValues()).toEqual(null);
+ });
+ it('returns array of values for the enum field', () => {
+ const property = new property_1.default(models_1.User.schema.paths.genre);
+ expect(property.availableValues()).toEqual(['male', 'female']);
+ });
+ });
+ describe('#isArray', () => {
+ it('returns false for regular (not arrayed) property', () => {
+ const property = new property_1.default(models_1.User.schema.paths.email);
+ expect(property.isArray()).toEqual(false);
+ });
+ it('returns true for array property', () => {
+ const property = new property_1.default(models_1.User.schema.paths.arrayed);
+ expect(property.isArray()).toEqual(true);
+ });
+ });
+ describe('#type', () => {
+ it('returns string type for string property', () => {
+ const property = new property_1.default(models_1.User.schema.paths.email);
+ expect(property.type()).toEqual('string');
+ });
+ it('returns string when property is an array of strings', () => {
+ const property = new property_1.default(models_1.User.schema.paths.arrayed);
+ expect(property.type()).toEqual('string');
+ });
+ it('returns mixed when prooperty is an array of embeded schemas', () => {
+ const property = new property_1.default(models_1.User.schema.paths.family);
+ expect(property.type()).toEqual('mixed');
+ });
+ });
+ describe('#reference', () => {
+ it('returns undefined when property without a reference is given', () => {
+ const property = new property_1.default(models_1.User.schema.paths.email);
+ expect(property.reference()).toEqual(undefined);
+ });
+ it('returns reference to User when field with it is given', () => {
+ const property = new property_1.default(models_1.Article.schema.paths.createdBy);
+ expect(property.reference()).toEqual('User');
+ });
+ it('returns reference to User when field is an array fields with references', () => {
+ const property = new property_1.default(models_1.Article.schema.paths.owners);
+ expect(property.reference()).toEqual('User');
+ });
+ });
+ describe('#subProperties', () => {
+ it('returns empty array for regular (not mixed) property', () => {
+ const property = new property_1.default(models_1.User.schema.paths.email);
+ expect(property.subProperties()).toEqual([]);
+ });
+ it('returns an array of all subproperties when nested schema is given', () => {
+ const property = new property_1.default(models_1.User.schema.paths.parent);
+ const subProperties = property.subProperties();
+ expect(subProperties.length).toEqual(6);
+ });
+ it('returns an array of all subproperties when array of nested schema is given', () => {
+ const property = new property_1.default(models_1.User.schema.paths.family);
+ const subProperties = property.subProperties();
+ expect(subProperties.length).toEqual(6);
+ });
+ });
+ describe('#isRequired', () => {
+ it('returns true for required property', () => {
+ const property = new property_1.default(models_1.User.schema.paths.email);
+ expect(property.isRequired()).toEqual(true);
+ });
+ it('returns string when property is an array of strings', () => {
+ const property = new property_1.default(models_1.User.schema.paths.genre);
+ expect(property.isRequired()).toEqual(false);
+ });
+ });
+});
+//# sourceMappingURL=property.spec.js.map
\ No newline at end of file
diff --git a/lib/test/property.spec.js.map b/lib/test/property.spec.js.map
new file mode 100644
index 0000000..9fab1a5
--- /dev/null
+++ b/lib/test/property.spec.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"property.spec.js","sourceRoot":"","sources":["../../test/property.spec.ts"],"names":[],"mappings":";;;;;AAAA,2CAA8C;AAE9C,+DAAsC;AAEtC,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE;IACxB,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAChC,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;YACzD,MAAM,QAAQ,GAAG,IAAI,kBAAQ,CAAC,aAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;YACtD,MAAM,CAAC,QAAQ,CAAC,eAAe,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAClD,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;YACpD,MAAM,QAAQ,GAAG,IAAI,kBAAQ,CAAC,aAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;YACtD,MAAM,CAAC,QAAQ,CAAC,eAAe,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAA;QAChE,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE;QACxB,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;YAC1D,MAAM,QAAQ,GAAG,IAAI,kBAAQ,CAAC,aAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;YACtD,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QAC3C,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,QAAQ,GAAG,IAAI,kBAAQ,CAAC,aAAI,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;YACxD,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAC1C,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE;QACrB,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;YACjD,MAAM,QAAQ,GAAG,IAAI,kBAAQ,CAAC,aAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;YACtD,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QAC3C,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;YAC7D,MAAM,QAAQ,GAAG,IAAI,kBAAQ,CAAC,aAAI,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;YACxD,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QAC3C,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;YACrE,MAAM,QAAQ,GAAG,IAAI,kBAAQ,CAAC,aAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;YACvD,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QAC1C,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;QAC1B,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;YACtE,MAAM,QAAQ,GAAG,IAAI,kBAAQ,CAAC,aAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;YACtD,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;QACjD,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;YAC/D,MAAM,QAAQ,GAAG,IAAI,kBAAQ,CAAC,gBAAO,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;YAC7D,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QAC9C,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,yEAAyE,EAAE,GAAG,EAAE;YACjF,MAAM,QAAQ,GAAG,IAAI,kBAAQ,CAAC,gBAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;YAC1D,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QAC9C,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAC9B,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;YAC9D,MAAM,QAAQ,GAAG,IAAI,kBAAQ,CAAC,aAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;YACtD,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QAC9C,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,mEAAmE,EAAE,GAAG,EAAE;YAC3E,MAAM,QAAQ,GAAG,IAAI,kBAAQ,CAAC,aAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;YACvD,MAAM,aAAa,GAAG,QAAQ,CAAC,aAAa,EAAE,CAAA;YAC9C,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;QACzC,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,4EAA4E,EAAE,GAAG,EAAE;YACpF,MAAM,QAAQ,GAAG,IAAI,kBAAQ,CAAC,aAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;YACvD,MAAM,aAAa,GAAG,QAAQ,CAAC,aAAa,EAAE,CAAA;YAC9C,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;QACzC,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;QAC3B,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;YAC5C,MAAM,QAAQ,GAAG,IAAI,kBAAQ,CAAC,aAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;YACtD,MAAM,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAC7C,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;YAC7D,MAAM,QAAQ,GAAG,IAAI,kBAAQ,CAAC,aAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;YACtD,MAAM,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QAC9C,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
\ No newline at end of file
diff --git a/lib/test/resource/constructor.d.ts b/lib/test/resource/constructor.d.ts
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/lib/test/resource/constructor.d.ts
@@ -0,0 +1 @@
+export {};
diff --git a/lib/test/resource/constructor.js b/lib/test/resource/constructor.js
new file mode 100644
index 0000000..f7139f0
--- /dev/null
+++ b/lib/test/resource/constructor.js
@@ -0,0 +1,16 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const resource_1 = __importDefault(require("../../src/resource"));
+const models_1 = require("../utils/models");
+describe('Resource', () => {
+ describe('#constructor', () => {
+ it('stores original model', () => {
+ const userResource = new resource_1.default(models_1.User);
+ expect(userResource.MongooseModel).toEqual(models_1.User);
+ });
+ });
+});
+//# sourceMappingURL=constructor.js.map
\ No newline at end of file
diff --git a/lib/test/resource/constructor.js.map b/lib/test/resource/constructor.js.map
new file mode 100644
index 0000000..d01cda4
--- /dev/null
+++ b/lib/test/resource/constructor.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"constructor.js","sourceRoot":"","sources":["../../../test/resource/constructor.ts"],"names":[],"mappings":";;;;;AAAA,kEAAyC;AACzC,4CAAsC;AAGtC,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE;IACxB,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;QAC5B,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;YAC/B,MAAM,YAAY,GAAG,IAAI,kBAAQ,CAAC,aAAI,CAAC,CAAA;YACvC,MAAM,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,aAAI,CAAC,CAAA;QAClD,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
\ No newline at end of file
diff --git a/lib/test/resource/count.spec.d.ts b/lib/test/resource/count.spec.d.ts
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/lib/test/resource/count.spec.d.ts
@@ -0,0 +1 @@
+export {};
diff --git a/lib/test/resource/count.spec.js b/lib/test/resource/count.spec.js
new file mode 100644
index 0000000..f558acb
--- /dev/null
+++ b/lib/test/resource/count.spec.js
@@ -0,0 +1,29 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const admin_bro_1 = require("admin-bro");
+const factory_girl_1 = require("factory-girl");
+const resource_1 = __importDefault(require("../../src/resource"));
+const models_1 = require("../utils/models");
+describe('Resource #count', () => {
+ let resource;
+ beforeEach(() => {
+ resource = new resource_1.default(models_1.User);
+ });
+ it('returns given count without filters', async () => {
+ const NUMBER_OF_RECORDS = 12;
+ await factory_girl_1.factory.createMany('user', NUMBER_OF_RECORDS);
+ const countedRecords = await resource.count(new admin_bro_1.Filter({}, resource));
+ expect(countedRecords).toEqual(NUMBER_OF_RECORDS);
+ });
+ it('returns given count for given filters', async () => {
+ const filterOutAllRecords = new admin_bro_1.Filter({
+ email: 'some-not-existing-email',
+ }, resource);
+ const counterRecords = await resource.count(filterOutAllRecords);
+ expect(counterRecords).toEqual(0);
+ });
+});
+//# sourceMappingURL=count.spec.js.map
\ No newline at end of file
diff --git a/lib/test/resource/count.spec.js.map b/lib/test/resource/count.spec.js.map
new file mode 100644
index 0000000..88f4c9f
--- /dev/null
+++ b/lib/test/resource/count.spec.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"count.spec.js","sourceRoot":"","sources":["../../../test/resource/count.spec.ts"],"names":[],"mappings":";;;;;AAAA,yCAAkC;AAClC,+CAAsC;AACtC,kEAAyC;AACzC,4CAAsC;AAGtC,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,IAAI,QAAQ,CAAA;IAEZ,UAAU,CAAC,GAAG,EAAE;QACd,QAAQ,GAAG,IAAI,kBAAQ,CAAC,aAAI,CAAC,CAAA;IAC/B,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,iBAAiB,GAAG,EAAE,CAAA;QAC5B,MAAM,sBAAO,CAAC,UAAU,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;QAEnD,MAAM,cAAc,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,IAAI,kBAAM,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAA;QAErE,MAAM,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAA;IACnD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACrD,MAAM,mBAAmB,GAAG,IAAI,kBAAM,CAAC;YACrC,KAAK,EAAE,yBAAyB;SACjC,EAAE,QAAQ,CAAC,CAAA;QAEZ,MAAM,cAAc,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAA;QAEhE,MAAM,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;IACnC,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
\ No newline at end of file
diff --git a/lib/test/resource/create.spec.d.ts b/lib/test/resource/create.spec.d.ts
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/lib/test/resource/create.spec.d.ts
@@ -0,0 +1 @@
+export {};
diff --git a/lib/test/resource/create.spec.js b/lib/test/resource/create.spec.js
new file mode 100644
index 0000000..a76286e
--- /dev/null
+++ b/lib/test/resource/create.spec.js
@@ -0,0 +1,79 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const admin_bro_1 = require("admin-bro");
+const factory_girl_1 = require("factory-girl");
+const resource_1 = __importDefault(require("../../src/resource"));
+const valid_user_record_1 = __importDefault(require("../fixtures/valid-user-record"));
+const models_1 = require("../utils/models");
+describe('Resource #create', () => {
+ it('creates new record with valid parameters', async () => {
+ const resource = new resource_1.default(models_1.User);
+ const record = await resource.create(valid_user_record_1.default);
+ expect(await resource.count()).toEqual(1);
+ expect(record).toBeInstanceOf(Object);
+ });
+ it('throws validation error for record with invalid parameters', async () => {
+ const resource = new resource_1.default(models_1.User);
+ await expect(() => resource.create({ email: '', passwordHash: '' })).rejects.toThrow(admin_bro_1.ValidationError);
+ });
+ it('throws validation error for record with cast errors in nested schema', async () => {
+ const resource = new resource_1.default(models_1.User);
+ try {
+ await resource.create({
+ email: 'a@a.pl',
+ passwordHash: 'asdasdasd',
+ 'parent.age': 'not a number',
+ });
+ throw new Error('Should throw validation error');
+ }
+ catch (error) {
+ expect(error).toBeInstanceOf(admin_bro_1.ValidationError);
+ expect(error.propertyErrors['parent.age'].type).toEqual('Number');
+ expect(error.propertyErrors.parent.type).toEqual('ValidationError');
+ }
+ });
+ it('throws duplicate error for record with unique field', async () => {
+ const peselResource = new resource_1.default(models_1.Pesel);
+ try {
+ await peselResource.create({ pesel: '1' });
+ await peselResource.create({ pesel: '1' });
+ }
+ catch (error) {
+ expect(error).toBeInstanceOf(admin_bro_1.ValidationError);
+ expect(error.propertyErrors.pesel.type).toEqual('duplicate');
+ }
+ });
+ it('creates resource with id field passed as an empty string', async () => {
+ const resource = new resource_1.default(models_1.Article);
+ await resource.create({ content: 'some content', createdBy: '' });
+ const recordsCount = await resource.count();
+ expect(recordsCount).toEqual(1);
+ });
+ it('creates new resource for record with reference', async () => {
+ const resource = new resource_1.default(models_1.Article);
+ const userRecords = await factory_girl_1.factory.createMany('user', 1);
+ const createdRecord = await resource.create({ content: '', createdBy: userRecords[0]._id });
+ expect(createdRecord.createdBy.toString()).toEqual(userRecords[0]._id.toString());
+ });
+ it('creates new object for record with nested array', async () => {
+ const resource = new resource_1.default(models_1.User);
+ await factory_girl_1.factory.createMany('user', 1);
+ const countBefore = await resource.count();
+ await resource.create({
+ email: 'john@doe.com',
+ passwordHash: 'somesecretpasswordhash',
+ 'parent.name': 'name',
+ 'parent.nestedArray': '',
+ 'parent.nestedObject': '',
+ 'family.0.name': 'some string',
+ 'family.0.nestedArray.0': '',
+ 'family.1': '',
+ });
+ const countAfter = await resource.count();
+ expect(countAfter - countBefore).toEqual(1);
+ });
+});
+//# sourceMappingURL=create.spec.js.map
\ No newline at end of file
diff --git a/lib/test/resource/create.spec.js.map b/lib/test/resource/create.spec.js.map
new file mode 100644
index 0000000..a647346
--- /dev/null
+++ b/lib/test/resource/create.spec.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"create.spec.js","sourceRoot":"","sources":["../../../test/resource/create.spec.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/lib/test/resource/delete.spec.d.ts b/lib/test/resource/delete.spec.d.ts
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/lib/test/resource/delete.spec.d.ts
@@ -0,0 +1 @@
+export {};
diff --git a/lib/test/resource/delete.spec.js b/lib/test/resource/delete.spec.js
new file mode 100644
index 0000000..2ca2214
--- /dev/null
+++ b/lib/test/resource/delete.spec.js
@@ -0,0 +1,19 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const factory_girl_1 = require("factory-girl");
+const resource_1 = __importDefault(require("../../src/resource"));
+const models_1 = require("../utils/models");
+describe('Resource #delete', () => {
+ it('removes the item from the database', async () => {
+ const resource = new resource_1.default(models_1.User);
+ const records = await factory_girl_1.factory.createMany('user', 12);
+ const initialNumberOfRecords = await models_1.User.countDocuments();
+ const idOfItemToDelete = records[0]._id;
+ await resource.delete(idOfItemToDelete);
+ expect(await models_1.User.countDocuments()).toEqual(initialNumberOfRecords - 1);
+ });
+});
+//# sourceMappingURL=delete.spec.js.map
\ No newline at end of file
diff --git a/lib/test/resource/delete.spec.js.map b/lib/test/resource/delete.spec.js.map
new file mode 100644
index 0000000..51fa28b
--- /dev/null
+++ b/lib/test/resource/delete.spec.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"delete.spec.js","sourceRoot":"","sources":["../../../test/resource/delete.spec.ts"],"names":[],"mappings":";;;;;AAAA,+CAAsC;AACtC,kEAAyC;AACzC,4CAAsC;AAEtC,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QAClD,MAAM,QAAQ,GAAG,IAAI,kBAAQ,CAAC,aAAI,CAAC,CAAA;QACnC,MAAM,OAAO,GAAG,MAAM,sBAAO,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;QACpD,MAAM,sBAAsB,GAAG,MAAM,aAAI,CAAC,cAAc,EAAE,CAAA;QAC1D,MAAM,gBAAgB,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;QAEvC,MAAM,QAAQ,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAA;QAEvC,MAAM,CAAC,MAAM,aAAI,CAAC,cAAc,EAAE,CAAC,CAAC,OAAO,CAAC,sBAAsB,GAAG,CAAC,CAAC,CAAA;IACzE,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
\ No newline at end of file
diff --git a/lib/test/resource/find.spec.d.ts b/lib/test/resource/find.spec.d.ts
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/lib/test/resource/find.spec.d.ts
@@ -0,0 +1 @@
+export {};
diff --git a/lib/test/resource/find.spec.js b/lib/test/resource/find.spec.js
new file mode 100644
index 0000000..aae81f1
--- /dev/null
+++ b/lib/test/resource/find.spec.js
@@ -0,0 +1,24 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const admin_bro_1 = require("admin-bro");
+const factory_girl_1 = require("factory-girl");
+const resource_1 = __importDefault(require("../../src/resource"));
+const models_1 = require("../utils/models");
+describe('Resource #find', () => {
+ it('returns first n items', async () => {
+ await factory_girl_1.factory.createMany('user', 10);
+ const resource = new resource_1.default(models_1.User);
+ const limit = 5;
+ const offset = 0;
+ const returnedItems = await resource.find(new admin_bro_1.Filter({}, models_1.User), {
+ limit,
+ offset,
+ });
+ expect(returnedItems.length).toEqual(limit);
+ expect(returnedItems[0]).toBeInstanceOf(admin_bro_1.BaseRecord);
+ });
+});
+//# sourceMappingURL=find.spec.js.map
\ No newline at end of file
diff --git a/lib/test/resource/find.spec.js.map b/lib/test/resource/find.spec.js.map
new file mode 100644
index 0000000..1a47b3e
--- /dev/null
+++ b/lib/test/resource/find.spec.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"find.spec.js","sourceRoot":"","sources":["../../../test/resource/find.spec.ts"],"names":[],"mappings":";;;;;AAAA,yCAA8C;AAC9C,+CAAsC;AACtC,kEAAyC;AACzC,4CAAsC;AAEtC,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,uBAAuB,EAAE,KAAK,IAAI,EAAE;QACrC,MAAM,sBAAO,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;QACpC,MAAM,QAAQ,GAAG,IAAI,kBAAQ,CAAC,aAAI,CAAC,CAAA;QACnC,MAAM,KAAK,GAAG,CAAC,CAAA;QACf,MAAM,MAAM,GAAG,CAAC,CAAA;QAEhB,MAAM,aAAa,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,kBAAM,CAAC,EAAE,EAAE,aAAI,CAAC,EAAE;YAC9D,KAAK;YACL,MAAM;SACP,CAAC,CAAA;QAEF,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QAC3C,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,sBAAU,CAAC,CAAA;IACrD,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
\ No newline at end of file
diff --git a/lib/test/resource/name.spec.d.ts b/lib/test/resource/name.spec.d.ts
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/lib/test/resource/name.spec.d.ts
@@ -0,0 +1 @@
+export {};
diff --git a/lib/test/resource/name.spec.js b/lib/test/resource/name.spec.js
new file mode 100644
index 0000000..e8a18fb
--- /dev/null
+++ b/lib/test/resource/name.spec.js
@@ -0,0 +1,14 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const resource_1 = __importDefault(require("../../src/resource"));
+const models_1 = require("../utils/models");
+describe('Resource #name', () => {
+ it('returns name of the model', () => {
+ const resource = new resource_1.default(models_1.User);
+ expect(resource.name()).toEqual('User');
+ });
+});
+//# sourceMappingURL=name.spec.js.map
\ No newline at end of file
diff --git a/lib/test/resource/name.spec.js.map b/lib/test/resource/name.spec.js.map
new file mode 100644
index 0000000..e45b371
--- /dev/null
+++ b/lib/test/resource/name.spec.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"name.spec.js","sourceRoot":"","sources":["../../../test/resource/name.spec.ts"],"names":[],"mappings":";;;;;AAAA,kEAAyC;AACzC,4CAAsC;AAEtC,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACnC,MAAM,QAAQ,GAAG,IAAI,kBAAQ,CAAC,aAAI,CAAC,CAAA;QAEnC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IACzC,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
\ No newline at end of file
diff --git a/lib/test/resource/parseParams.spec.d.ts b/lib/test/resource/parseParams.spec.d.ts
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/lib/test/resource/parseParams.spec.d.ts
@@ -0,0 +1 @@
+export {};
diff --git a/lib/test/resource/parseParams.spec.js b/lib/test/resource/parseParams.spec.js
new file mode 100644
index 0000000..171ec0d
--- /dev/null
+++ b/lib/test/resource/parseParams.spec.js
@@ -0,0 +1,20 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const resource_1 = __importDefault(require("../../src/resource"));
+const models_1 = require("../utils/models");
+describe('Resource #parseParams', () => {
+ let resource;
+ beforeEach(() => {
+ resource = new resource_1.default(models_1.User);
+ });
+ it('converts empty strings to nulls for ObjectIDs', () => {
+ expect(resource.parseParams({ _id: '' })).toHaveProperty('_id', null);
+ });
+ it('converts empty strings to [] for arrays', () => {
+ expect(resource.parseParams({ family: '' })).toHaveProperty('family', []);
+ });
+});
+//# sourceMappingURL=parseParams.spec.js.map
\ No newline at end of file
diff --git a/lib/test/resource/parseParams.spec.js.map b/lib/test/resource/parseParams.spec.js.map
new file mode 100644
index 0000000..b551bb1
--- /dev/null
+++ b/lib/test/resource/parseParams.spec.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"parseParams.spec.js","sourceRoot":"","sources":["../../../test/resource/parseParams.spec.ts"],"names":[],"mappings":";;;;;AAAA,kEAAyC;AACzC,4CAAsC;AAGtC,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,IAAI,QAAQ,CAAA;IAEZ,UAAU,CAAC,GAAG,EAAE;QACd,QAAQ,GAAG,IAAI,kBAAQ,CAAC,aAAI,CAAC,CAAA;IAC/B,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;IACvE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;IAC3E,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
\ No newline at end of file
diff --git a/lib/test/resource/position.spec.d.ts b/lib/test/resource/position.spec.d.ts
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/lib/test/resource/position.spec.d.ts
@@ -0,0 +1 @@
+export {};
diff --git a/lib/test/resource/position.spec.js b/lib/test/resource/position.spec.js
new file mode 100644
index 0000000..9997c37
--- /dev/null
+++ b/lib/test/resource/position.spec.js
@@ -0,0 +1,14 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const resource_1 = __importDefault(require("../../src/resource"));
+const models_1 = require("../utils/models");
+describe('Resource #position', () => {
+ it('returns position of a parent field', () => {
+ const property = new resource_1.default(models_1.User).property('parent');
+ expect(property.position()).toEqual(4);
+ });
+});
+//# sourceMappingURL=position.spec.js.map
\ No newline at end of file
diff --git a/lib/test/resource/position.spec.js.map b/lib/test/resource/position.spec.js.map
new file mode 100644
index 0000000..58f051b
--- /dev/null
+++ b/lib/test/resource/position.spec.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"position.spec.js","sourceRoot":"","sources":["../../../test/resource/position.spec.ts"],"names":[],"mappings":";;;;;AAAA,kEAAyC;AACzC,4CAAsC;AAGtC,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,QAAQ,GAAG,IAAI,kBAAQ,CAAC,aAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;QAEtD,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;IACxC,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
\ No newline at end of file
diff --git a/lib/test/resource/properties.spec.d.ts b/lib/test/resource/properties.spec.d.ts
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/lib/test/resource/properties.spec.d.ts
@@ -0,0 +1 @@
+export {};
diff --git a/lib/test/resource/properties.spec.js b/lib/test/resource/properties.spec.js
new file mode 100644
index 0000000..76eef98
--- /dev/null
+++ b/lib/test/resource/properties.spec.js
@@ -0,0 +1,39 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const mongoose_1 = __importDefault(require("mongoose"));
+const resource_1 = __importDefault(require("../../src/resource"));
+const models_1 = require("../utils/models");
+const property_1 = __importDefault(require("../../src/property"));
+describe('Resource #properties', () => {
+ let resource;
+ let returnedProperties;
+ beforeEach(() => {
+ resource = new resource_1.default(models_1.User);
+ returnedProperties = resource.properties();
+ });
+ it('returns correct amount of properties', () => {
+ // 8 because of implicit _id and __v properties
+ expect(returnedProperties.length).toEqual(8);
+ });
+ it('sets the position of properties', () => {
+ expect(returnedProperties.map(p => p.position())).toEqual([0, 1, 2, 3, 4, 5, 6, 7]);
+ });
+ it('returns instances of Property class', async () => {
+ expect(returnedProperties[0]).toBeInstanceOf(property_1.default);
+ });
+ it('returns all fields for nested properties', () => {
+ const Nested = mongoose_1.default.model('Nested', new mongoose_1.default.Schema({
+ field: {
+ subfield: String,
+ anotherSubField: String,
+ },
+ }));
+ const nestedResource = new resource_1.default(Nested);
+ const propertiesOfNestedResource = nestedResource.properties();
+ expect(propertiesOfNestedResource.length).toEqual(4);
+ });
+});
+//# sourceMappingURL=properties.spec.js.map
\ No newline at end of file
diff --git a/lib/test/resource/properties.spec.js.map b/lib/test/resource/properties.spec.js.map
new file mode 100644
index 0000000..d660e77
--- /dev/null
+++ b/lib/test/resource/properties.spec.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"properties.spec.js","sourceRoot":"","sources":["../../../test/resource/properties.spec.ts"],"names":[],"mappings":";;;;;AAAA,wDAA+B;AAC/B,kEAAyC;AACzC,4CAAsC;AACtC,kEAAyC;AAEzC,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,IAAI,QAAQ,CAAA;IACZ,IAAI,kBAAkB,CAAA;IAEtB,UAAU,CAAC,GAAG,EAAE;QACd,QAAQ,GAAG,IAAI,kBAAQ,CAAC,aAAI,CAAC,CAAA;QAC7B,kBAAkB,GAAG,QAAQ,CAAC,UAAU,EAAE,CAAA;IAC5C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,+CAA+C;QAC/C,MAAM,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;IAC9C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IACrF,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,kBAAQ,CAAC,CAAA;IACxD,CAAC,CAAC,CAAA;IAGF,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,MAAM,GAAG,kBAAQ,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,kBAAQ,CAAC,MAAM,CAAC;YAC1D,KAAK,EAAE;gBACL,QAAQ,EAAE,MAAM;gBAChB,eAAe,EAAE,MAAM;aACxB;SACF,CAAC,CAAC,CAAA;QACH,MAAM,cAAc,GAAG,IAAI,kBAAQ,CAAC,MAAM,CAAC,CAAA;QAE3C,MAAM,0BAA0B,GAAG,cAAc,CAAC,UAAU,EAAE,CAAA;QAE9D,MAAM,CAAC,0BAA0B,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;IACtD,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
\ No newline at end of file
diff --git a/lib/test/resource/property.spec.d.ts b/lib/test/resource/property.spec.d.ts
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/lib/test/resource/property.spec.d.ts
@@ -0,0 +1 @@
+export {};
diff --git a/lib/test/resource/property.spec.js b/lib/test/resource/property.spec.js
new file mode 100644
index 0000000..d516ad4
--- /dev/null
+++ b/lib/test/resource/property.spec.js
@@ -0,0 +1,23 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const resource_1 = __importDefault(require("../../src/resource"));
+const models_1 = require("../utils/models");
+const property_1 = __importDefault(require("../../src/property"));
+describe('Resource #property', () => {
+ let resource;
+ let returnedProperty;
+ beforeEach(() => {
+ resource = new resource_1.default(models_1.User);
+ returnedProperty = resource.property('email');
+ });
+ it('returns selected property for an email', () => {
+ expect(returnedProperty.name()).toEqual('email');
+ });
+ it('returns instance of Property class', () => {
+ expect(returnedProperty).toBeInstanceOf(property_1.default);
+ });
+});
+//# sourceMappingURL=property.spec.js.map
\ No newline at end of file
diff --git a/lib/test/resource/property.spec.js.map b/lib/test/resource/property.spec.js.map
new file mode 100644
index 0000000..47f6027
--- /dev/null
+++ b/lib/test/resource/property.spec.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"property.spec.js","sourceRoot":"","sources":["../../../test/resource/property.spec.ts"],"names":[],"mappings":";;;;;AAAA,kEAAyC;AACzC,4CAAsC;AACtC,kEAAyC;AAEzC,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,IAAI,QAAQ,CAAA;IACZ,IAAI,gBAAgB,CAAA;IAEpB,UAAU,CAAC,GAAG,EAAE;QACd,QAAQ,GAAG,IAAI,kBAAQ,CAAC,aAAI,CAAC,CAAA;QAC7B,gBAAgB,GAAG,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;IAC/C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAClD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,CAAC,gBAAgB,CAAC,CAAC,cAAc,CAAC,kBAAQ,CAAC,CAAA;IACnD,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
\ No newline at end of file
diff --git a/lib/test/resource/update.spec.d.ts b/lib/test/resource/update.spec.d.ts
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/lib/test/resource/update.spec.d.ts
@@ -0,0 +1 @@
+export {};
diff --git a/lib/test/resource/update.spec.js b/lib/test/resource/update.spec.js
new file mode 100644
index 0000000..97255d2
--- /dev/null
+++ b/lib/test/resource/update.spec.js
@@ -0,0 +1,18 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const resource_1 = __importDefault(require("../../src/resource"));
+const models_1 = require("../utils/models");
+describe('Resource #update', () => {
+ it('changes record and returns updated', async () => {
+ const resource = new resource_1.default(models_1.Article);
+ const initialRecord = await resource.create({
+ content: 'Test content',
+ });
+ const updatedRecord = await resource.update(initialRecord._id, { content: 'Updated content' });
+ expect(updatedRecord.content).toEqual('Updated content');
+ });
+});
+//# sourceMappingURL=update.spec.js.map
\ No newline at end of file
diff --git a/lib/test/resource/update.spec.js.map b/lib/test/resource/update.spec.js.map
new file mode 100644
index 0000000..a7db004
--- /dev/null
+++ b/lib/test/resource/update.spec.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"update.spec.js","sourceRoot":"","sources":["../../../test/resource/update.spec.ts"],"names":[],"mappings":";;;;;AAAA,kEAAyC;AACzC,4CAAyC;AAEzC,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QAClD,MAAM,QAAQ,GAAG,IAAI,kBAAQ,CAAC,gBAAO,CAAC,CAAA;QACtC,MAAM,aAAa,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;YAC1C,OAAO,EAAE,cAAc;SACxB,CAAC,CAAA;QAEF,MAAM,aAAa,GAAG,MAAM,QAAQ,CAAC,MAAM,CACzC,aAAa,CAAC,GAAG,EACjB,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAC/B,CAAA;QAED,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAA;IAC1D,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
\ No newline at end of file
diff --git a/lib/test/utils/beforeEach.d.ts b/lib/test/utils/beforeEach.d.ts
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/lib/test/utils/beforeEach.d.ts
@@ -0,0 +1 @@
+export {};
diff --git a/lib/test/utils/beforeEach.js b/lib/test/utils/beforeEach.js
new file mode 100644
index 0000000..8c94fb8
--- /dev/null
+++ b/lib/test/utils/beforeEach.js
@@ -0,0 +1,20 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const mongoose_1 = __importDefault(require("mongoose"));
+const models_1 = require("./models");
+const dropAllCollections = async () => {
+ await mongoose_1.default.connect('mongodb://localhost/e2e_test', {
+ useNewUrlParser: true,
+ useUnifiedTopology: true,
+ });
+ await Promise.all([
+ models_1.Pesel.deleteMany({}),
+ models_1.User.deleteMany({}),
+ models_1.Article.deleteMany({}),
+ ]);
+};
+beforeEach(dropAllCollections);
+//# sourceMappingURL=beforeEach.js.map
\ No newline at end of file
diff --git a/lib/test/utils/beforeEach.js.map b/lib/test/utils/beforeEach.js.map
new file mode 100644
index 0000000..e10581c
--- /dev/null
+++ b/lib/test/utils/beforeEach.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"beforeEach.js","sourceRoot":"","sources":["../../../test/utils/beforeEach.ts"],"names":[],"mappings":";;;;;AAAA,wDAA+B;AAC/B,qCAA+C;AAE/C,MAAM,kBAAkB,GAAG,KAAK,IAAmB,EAAE;IACnD,MAAM,kBAAQ,CAAC,OAAO,CAAC,8BAA8B,EAAE;QACrD,eAAe,EAAE,IAAI;QACrB,kBAAkB,EAAE,IAAI;KACzB,CAAC,CAAA;IACF,MAAM,OAAO,CAAC,GAAG,CAAC;QAChB,cAAK,CAAC,UAAU,CAAC,EAAE,CAAC;QACpB,aAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QACnB,gBAAO,CAAC,UAAU,CAAC,EAAE,CAAC;KACvB,CAAC,CAAA;AACJ,CAAC,CAAA;AACD,UAAU,CAAC,kBAAkB,CAAC,CAAA"}
\ No newline at end of file
diff --git a/lib/test/utils/models.d.ts b/lib/test/utils/models.d.ts
new file mode 100644
index 0000000..30b698b
--- /dev/null
+++ b/lib/test/utils/models.d.ts
@@ -0,0 +1 @@
+export declare const User: any, Article: any, Pesel: any;
diff --git a/lib/test/utils/models.js b/lib/test/utils/models.js
new file mode 100644
index 0000000..7403fd8
--- /dev/null
+++ b/lib/test/utils/models.js
@@ -0,0 +1,51 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.Pesel = exports.Article = exports.User = void 0;
+const mongoose_1 = __importDefault(require("mongoose"));
+const factory_girl_1 = require("factory-girl");
+const globalAny = global;
+// @ts-ignore
+const NestedObject = new mongoose_1.default.Schema({
+ someProperty: Number,
+});
+// @ts-ignore
+const SubType = new mongoose_1.default.Schema({
+ name: String,
+ surname: String,
+ age: Number,
+ nestedArray: [NestedObject],
+ nestedObject: NestedObject,
+});
+globalAny.User = mongoose_1.default.model('User', new mongoose_1.default.Schema({
+ email: { type: String, required: true },
+ passwordHash: { type: String, required: true },
+ genre: { type: String, enum: ['male', 'female'] },
+ arrayed: [String],
+ parent: SubType,
+ family: [SubType],
+}));
+globalAny.Pesel = mongoose_1.default.model('Pesel', new mongoose_1.default.Schema({
+ pesel: {
+ type: String, unique: true, required: true, sparse: true,
+ },
+}));
+globalAny.Article = mongoose_1.default.model('Article', new mongoose_1.default.Schema({
+ content: String,
+ owners: [{
+ type: mongoose_1.default.Schema.Types.ObjectId,
+ ref: 'User',
+ }],
+ createdBy: {
+ type: mongoose_1.default.Schema.Types.ObjectId,
+ ref: 'User',
+ },
+}));
+exports.User = globalAny.User, exports.Article = globalAny.Article, exports.Pesel = globalAny.Pesel;
+factory_girl_1.factory.define('user', exports.User, {
+ email: factory_girl_1.factory.sequence('User.email', n => `john@doe${n}.com`),
+ passwordHash: 'somehashedpassword',
+});
+//# sourceMappingURL=models.js.map
\ No newline at end of file
diff --git a/lib/test/utils/models.js.map b/lib/test/utils/models.js.map
new file mode 100644
index 0000000..ebc2f66
--- /dev/null
+++ b/lib/test/utils/models.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"models.js","sourceRoot":"","sources":["../../../test/utils/models.ts"],"names":[],"mappings":";;;;;;AAAA,wDAA+B;AAC/B,+CAAsC;AAGtC,MAAM,SAAS,GAAG,MAAa,CAAA;AAE/B,aAAa;AACb,MAAM,YAAY,GAAG,IAAI,kBAAQ,CAAC,MAAM,CAAC;IACvC,YAAY,EAAE,MAAM;CACrB,CAAC,CAAA;AAEF,aAAa;AACb,MAAM,OAAO,GAAG,IAAI,kBAAQ,CAAC,MAAM,CAAC;IAClC,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,MAAM;IACf,GAAG,EAAE,MAAM;IACX,WAAW,EAAE,CAAC,YAAY,CAAC;IAC3B,YAAY,EAAE,YAAY;CAC3B,CAAC,CAAA;AAEF,SAAS,CAAC,IAAI,GAAG,kBAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,kBAAQ,CAAC,MAAM,CAAC;IAC1D,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IACvC,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IAC9C,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE;IACjD,OAAO,EAAE,CAAC,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO;IACf,MAAM,EAAE,CAAC,OAAO,CAAC;CAClB,CAAC,CAAC,CAAA;AAEH,SAAS,CAAC,KAAK,GAAG,kBAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,kBAAQ,CAAC,MAAM,CAAC;IAC5D,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI;KACzD;CACF,CAAC,CAAC,CAAA;AAEH,SAAS,CAAC,OAAO,GAAG,kBAAQ,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,kBAAQ,CAAC,MAAM,CAAC;IAChE,OAAO,EAAE,MAAM;IACf,MAAM,EAAE,CAAC;YACP,IAAI,EAAE,kBAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ;YACpC,GAAG,EAAE,MAAM;SACZ,CAAC;IACF,SAAS,EAAE;QACT,IAAI,EAAE,kBAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ;QACpC,GAAG,EAAE,MAAM;KACZ;CACF,CAAC,CAAC,CAAA;AAEY,YAAI,GAA0D,SAAS,OAAjE,eAAO,GAAiD,SAAS,UAAxD,aAAK,GAA0C,SAAS,OAAA;AAEtF,sBAAO,CAAC,MAAM,CAAC,MAAM,EAAE,YAAI,EAAE;IAC3B,KAAK,EAAE,sBAAO,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC;IAC9D,YAAY,EAAE,oBAAoB;CACnC,CAAC,CAAA"}
\ No newline at end of file
diff --git a/lib/test/utils/teardown.d.ts b/lib/test/utils/teardown.d.ts
new file mode 100644
index 0000000..c93604e
--- /dev/null
+++ b/lib/test/utils/teardown.d.ts
@@ -0,0 +1,2 @@
+declare const teardownE2ETests: () => Promise;
+export default teardownE2ETests;
diff --git a/lib/test/utils/teardown.js b/lib/test/utils/teardown.js
new file mode 100644
index 0000000..b753d7a
--- /dev/null
+++ b/lib/test/utils/teardown.js
@@ -0,0 +1,14 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const mongoose_1 = __importDefault(require("mongoose"));
+const teardownE2ETests = async () => {
+ await Promise.all(mongoose_1.default.connections.map(connection => connection.close(true)));
+ await mongoose_1.default.connection.close();
+ await mongoose_1.default.disconnect();
+ process.exit();
+};
+exports.default = teardownE2ETests;
+//# sourceMappingURL=teardown.js.map
\ No newline at end of file
diff --git a/lib/test/utils/teardown.js.map b/lib/test/utils/teardown.js.map
new file mode 100644
index 0000000..d4f45e1
--- /dev/null
+++ b/lib/test/utils/teardown.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"teardown.js","sourceRoot":"","sources":["../../../test/utils/teardown.ts"],"names":[],"mappings":";;;;;AAAA,wDAA+B;AAE/B,MAAM,gBAAgB,GAAG,KAAK,IAAmB,EAAE;IACjD,MAAM,OAAO,CAAC,GAAG,CACf,kBAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAC/D,CAAA;IACD,MAAM,kBAAQ,CAAC,UAAU,CAAC,KAAK,EAAE,CAAA;IACjC,MAAM,kBAAQ,CAAC,UAAU,EAAE,CAAA;IAC3B,OAAO,CAAC,IAAI,EAAE,CAAA;AAChB,CAAC,CAAA;AAED,kBAAe,gBAAgB,CAAA"}
\ No newline at end of file
diff --git a/src/resource.ts b/src/resource.ts
index 99688aa..256a6ab 100644
--- a/src/resource.ts
+++ b/src/resource.ts
@@ -56,6 +56,10 @@ class Resource extends BaseResource {
return this.MongooseModel.modelName
}
+ get selectFields(){
+ return Object.keys(this.MongooseModel.schema.paths).join(' ');
+ }
+
properties() {
return Object.entries(this.MongooseModel.schema.paths).map(([, path], position) => (
new Property(path, position)
@@ -67,7 +71,7 @@ class Resource extends BaseResource {
}
async count(filters = null) {
- return this.MongooseModel.count(convertFilter(filters))
+ return this.MongooseModel.countDocuments(convertFilter(filters))
}
async find(filters = {}, { limit = 20, offset = 0, sort = {} }: FindOptions) {
@@ -77,7 +81,7 @@ class Resource extends BaseResource {
}
const mongooseObjects = await this.MongooseModel
.find(convertFilter(filters), {}, {
- skip: offset, limit, sort: sortingParam,
+ skip: offset, limit, sort: sortingParam, select: this.selectFields
})
return mongooseObjects.map(mongooseObject => new BaseRecord(
Resource.stringifyId(mongooseObject), this,
@@ -85,7 +89,7 @@ class Resource extends BaseResource {
}
async findOne(id:string) {
- const mongooseObject = await this.MongooseModel.findById(id)
+ const mongooseObject = await this.MongooseModel.findById(id).select(this.selectFields)
return new BaseRecord(Resource.stringifyId(mongooseObject), this)
}
@@ -93,6 +97,7 @@ class Resource extends BaseResource {
const mongooseObjects = await this.MongooseModel.find(
{ _id: ids },
{},
+ {select: this.selectFields}
)
return mongooseObjects.map(mongooseObject => (
new BaseRecord(Resource.stringifyId(mongooseObject), this)
@@ -159,7 +164,7 @@ class Resource extends BaseResource {
// raw object it changes _id field not to a string but to an object.
// stringify/parse is a path found here: https://github.com/Automattic/mongoose/issues/2790
// @todo We can somehow speed this up
- const strinigified = JSON.stringify(mongooseObj)
+ const strinigified = JSON.stringify(mongooseObj && 'toObject' in mongooseObj ? mongooseObj.toObject({getters: true, virtuals: true}): mongooseObj)
return JSON.parse(strinigified)
}