lib/model.js
function defineModel(modelType, options) {
  var primaryAttributes;
  var attributes;
  var prototype;
  var staticProto;
  var ModelConstructor;
  var typeName;
  var namespace;

  if (types.isValidType(modelType).indexes) {
    throw ModelException('Model type cannot be an array `{{type}}`', null, null, { type: String(modelType) });
  } else if (models[modelType]) {
    throw ModelException('Model already defined `{{type}}`', null, null, { type: String(modelType) });
  }

  options = options || {};
  primaryAttributes = [];
  namespace = _getNamespace(modelType);
  typeName = _getTypeName(modelType);
  attributes = _prepareAttributes(options.attributes || {}, primaryAttributes);
  prototype = _preparePrototype(options.methods || {}, primaryAttributes, modelType, namespace, typeName);
  staticProto = _prepareStaticProto(options.staticMethods || {}, primaryAttributes, options.attributes, prototype._type);

  ModelConstructor = Function('Model, events, attributes',
    'return function ' + typeName + 'Model(data) { ' +
      'if (!(this instanceof ' + typeName + 'Model)){' +
        'return new ' + typeName + 'Model(data);' +
      '}' +
      (attributes ? 'Object.defineProperties(this, attributes);' : '') +
      'events.emit("create", data);' +
      'Model.call(this, data);' +
    ' }'
  )(Model, events, attributes);
  util.inherits(ModelConstructor, Model);

  Object.defineProperties(ModelConstructor.prototype, prototype);
  Object.defineProperties(ModelConstructor, staticProto);

  if (!types.isDefined(modelType)) {
    types.define(modelType, options.typeValidator || _modelTypeValidator(ModelConstructor));
  }

  // assign
  models[modelType] = ModelConstructor;

  events.emit('define', {
    modelType: modelType,
    namespace: namespace,
    typeName: typeName,
    attributes: attributes,
    constructor: ModelConstructor,
    options: options
  });

  // Freeze model API
  for (var attr in attributes) {
    Object.freeze(attributes[attr]);
  }

  if (options.attributes) {
    Object.freeze(options.attributes); // freeze declared attributes
  }

  if (attributes) {
    Object.freeze(attributes);         // freeze attributes list
  }

  Object.freeze(primaryAttributes);  // freeze primary attributes
  //Object.freeze(ModelConstructor.prototype);  // do not freeze to allow extensions

  return ModelConstructor;
}
function defineModel(modelType, options) {
  var primaryAttributes;
  var attributes;
  var prototype;
  var staticProto;
  var ModelConstructor;
  var typeName;
  var namespace;

  if (types.isValidType(modelType).indexes) {
    throw ModelException('Model type cannot be an array `{{type}}`', null, null, { type: String(modelType) });
  } else if (models[modelType]) {
    throw ModelException('Model already defined `{{type}}`', null, null, { type: String(modelType) });
  }

  options = options || {};
  primaryAttributes = [];
  namespace = _getNamespace(modelType);
  typeName = _getTypeName(modelType);
  attributes = _prepareAttributes(options.attributes || {}, primaryAttributes);
  prototype = _preparePrototype(options.methods || {}, primaryAttributes, modelType, namespace, typeName);
  staticProto = _prepareStaticProto(options.staticMethods || {}, primaryAttributes, options.attributes, prototype._type);

  ModelConstructor = Function('Model, events, attributes',
    'return function ' + typeName + 'Model(data) { ' +
      'if (!(this instanceof ' + typeName + 'Model)){' +
        'return new ' + typeName + 'Model(data);' +
      '}' +
      (attributes ? 'Object.defineProperties(this, attributes);' : '') +
      'events.emit("create", data);' +
      'Model.call(this, data);' +
    ' }'
  )(Model, events, attributes);
  util.inherits(ModelConstructor, Model);

  Object.defineProperties(ModelConstructor.prototype, prototype);
  Object.defineProperties(ModelConstructor, staticProto);

  if (!types.isDefined(modelType)) {
    types.define(modelType, options.typeValidator || _modelTypeValidator(ModelConstructor));
  }

  // assign
  models[modelType] = ModelConstructor;

  events.emit('define', {
    modelType: modelType,
    namespace: namespace,
    typeName: typeName,
    attributes: attributes,
    constructor: ModelConstructor,
    options: options
  });

  // Freeze model API
  for (var attr in attributes) {
    Object.freeze(attributes[attr]);
  }

  if (options.attributes) {
    Object.freeze(options.attributes); // freeze declared attributes
  }

  if (attributes) {
    Object.freeze(attributes);         // freeze attributes list
  }

  Object.freeze(primaryAttributes);  // freeze primary attributes
  //Object.freeze(ModelConstructor.prototype);  // do not freeze to allow extensions

  return ModelConstructor;
}
Define a new model prototype.

This will define a new model

@param {String} modelType         the model type name
@param {Object} options           the model options
@return {Function}                the model constructor