function Mapper(opts) {
  utils.classCallCheck(this, Mapper);
  Component$1.call(this);
  opts || (opts = {}); // Prepare certain properties to be non-enumerable

  Object.defineProperties(this, {
    _adapters: {
      value: undefined,
      writable: true
    },

    /**
     * The {@link Container} that holds this Mapper. __Do not modify.__
     *
     * @name Mapper#lifecycleMethods
     * @since 3.0.0
     * @type {Object}
     */
    datastore: {
      value: undefined,
      writable: true
    },

    /**
     * The meta information describing this Mapper's available lifecycle
     * methods. __Do not modify.__
     *
     * @name Mapper#lifecycleMethods
     * @since 3.0.0
     * @type {Object}
     */
    lifecycleMethods: {
      value: LIFECYCLE_METHODS
    },

    /**
     * Set to `false` to force the Mapper to work with POJO objects only.
     *
     * @example
     * // Use POJOs only.
     * import { Mapper, Record } from 'js-data';
     * const UserMapper = new Mapper({ recordClass: false });
     * UserMapper.recordClass // false;
     * const user = UserMapper.createRecord();
     * user instanceof Record; // false
     *
     * @example
     * // Set to a custom class to have records wrapped in your custom class.
     * import { Mapper, Record } from 'js-data';
     *  // Custom class
     * class User {
     *   constructor (props = {}) {
     *     for (var key in props) {
     *       if (props.hasOwnProperty(key)) {
     *         this[key] = props[key];
     *       }
     *     }
     *   }
     * }
     * const UserMapper = new Mapper({ recordClass: User });
     * UserMapper.recordClass; // function User() {}
     * const user = UserMapper.createRecord();
     * user instanceof Record; // false
     * user instanceof User; // true
     *
     *
     * @example
     * // Extend the {@link Record} class.
     * import { Mapper, Record } from 'js-data';
     *  // Custom class
     * class User extends Record {
     *   constructor () {
     *     super(props);
     *   }
     * }
     * const UserMapper = new Mapper({ recordClass: User });
     * UserMapper.recordClass; // function User() {}
     * const user = UserMapper.createRecord();
     * user instanceof Record; // true
     * user instanceof User; // true
     *
     * @name Mapper#recordClass
     * @default {@link Record}
     * @see Record
     * @since 3.0.0
     */
    recordClass: {
      value: undefined,
      writable: true
    },

    /**
     * This Mapper's {@link Schema}.
     *
     * @example <caption>Mapper#schema</caption>
     * const JSData = require('js-data');
     * const { Mapper } = JSData;
     * console.log('Using JSData v' + JSData.version.full);
     *
     * const UserMapper = new Mapper({
     *   name: 'user',
     *   schema: {
     *     properties: {
     *       id: { type: 'number' },
     *       first: { type: 'string', track: true },
     *       last: { type: 'string', track: true },
     *       role: { type: 'string', track: true, required: true },
     *       age: { type: 'integer', track: true },
     *       is_active: { type: 'number' }
     *     }
     *   }
     * });
     * const user = UserMapper.createRecord({
     *   id: 1,
     *   name: 'John',
     *   role: 'admin'
     * });
     * user.on('change', function (user, changes) {
     *   console.log(changes);
     * });
     * user.on('change:role', function (user, value) {
     *   console.log('change:role - ' + value);
     * });
     * user.role = 'owner';
     *
     * @name Mapper#schema
     * @see Schema
     * @since 3.0.0
     * @type {Schema}
     */
    schema: {
      value: undefined,
      writable: true
    }
  }); // Apply user-provided configuration

  utils.fillIn(this, opts); // Fill in any missing options with the defaults

  utils.fillIn(this, utils.copy(MAPPER_DEFAULTS));
  /**
   * The name for this Mapper. This is the minimum amount of meta information
   * required for a Mapper to be able to execute CRUD operations for a
   * Resource.
   *
   * @name Mapper#name
   * @since 3.0.0
   * @type {string}
   */

  if (!this.name) {
    throw utils.err("new ".concat(DOMAIN$6), 'opts.name')(400, 'string', this.name);
  } // Setup schema, with an empty default schema if necessary


  if (this.schema) {
    this.schema.type || (this.schema.type = 'object');

    if (!(this.schema instanceof Schema$1)) {
      this.schema = new Schema$1(this.schema || {
        type: 'object'
      });
    }
  } // Create a subclass of Record that's tied to this Mapper


  if (this.recordClass === undefined) {
    var superClass = Record$1;
    this.recordClass = superClass.extend({
      constructor: function Record() {
        var subClass = function Record(props, opts) {
          utils.classCallCheck(this, subClass);
          superClass.call(this, props, opts);
        };

        return subClass;
      }()
    });
  }

  if (this.recordClass) {
    this.recordClass.mapper = this;
    /**
     * Functions that should be added to the prototype of {@link Mapper#recordClass}.
     *
     * @name Mapper#methods
     * @since 3.0.0
     * @type {Object}
     */

    if (utils.isObject(this.methods)) {
      utils.addHiddenPropsToTarget(this.recordClass.prototype, this.methods);
    } // We can only apply the schema to the prototype of this.recordClass if the
    // class extends Record


    if (Object.isPrototypeOf.call(Record$1, this.recordClass) && this.schema && this.schema.apply && this.applySchema) {
      this.schema.apply(this.recordClass.prototype);
    }
  }
}
The core of JSData's [ORM/ODM][orm] implementation. Given a minimum amout of
meta information about a resource, a Mapper can perform generic CRUD
operations against that resource. Apart from its configuration, a Mapper is
stateless. The particulars of various persistence layers have been abstracted
into adapters, which a Mapper uses to perform its operations.

The term "Mapper" comes from the [Data Mapper Pattern][pattern] described in
Martin Fowler's [Patterns of Enterprise Application Architecture][book]. A
Data Mapper moves data between [in-memory object instances][record] and a
relational or document-based database. JSData's Mapper can work with any
persistence layer you can write an adapter for.

_("Model" is a heavily overloaded term and is avoided in this documentation
to prevent confusion.)_

[orm]: https://en.wikipedia.org/wiki/Object-relational_mapping

@example
[pattern]: https://en.wikipedia.org/wiki/Data_mapper_pattern
[book]: http://martinfowler.com/books/eaa.html
[record]: Record.html
// Import and instantiate
import { Mapper } from 'js-data';
const UserMapper = new Mapper({ name: 'user' });

@example
// Define a Mapper using the Container component
import { Container } from 'js-data';
const store = new Container();
store.defineMapper('user');

@class Mapper
@extends Component
@param {object} opts Configuration options.
@param {boolean} [opts.applySchema=true] See {@link Mapper#applySchema}.
@param {boolean} [opts.debug=false] See {@link Component#debug}.
@param {string} [opts.defaultAdapter=http] See {@link Mapper#defaultAdapter}.
@param {string} [opts.idAttribute=id] See {@link Mapper#idAttribute}.
@param {object} [opts.methods] See {@link Mapper#methods}.
@param {string} opts.name See {@link Mapper#name}.
@param {boolean} [opts.notify] See {@link Mapper#notify}.
@param {boolean} [opts.raw=false] See {@link Mapper#raw}.
@param {Function|boolean} [opts.recordClass] See {@link Mapper#recordClass}.
@param {Object|Schema} [opts.schema] See {@link Mapper#schema}.
@returns {Mapper} A new {@link Mapper} instance.
@see http://www.js-data.io/v3.0/docs/components-of-jsdata#mapper
@since 3.0.0
@tutorial ["http://www.js-data.io/v3.0/docs/components-of-jsdata#mapper","Components of JSData: Mapper"]
@tutorial ["http://www.js-data.io/v3.0/docs/modeling-your-data","Modeling your data"]