diff --git a/docs/api.md b/docs/api.md index 0bbaca35..36692f84 100644 --- a/docs/api.md +++ b/docs/api.md @@ -1,1262 +1,7 @@ ## Node.js API -### App - -Create a Loopback application. - -```js -var loopback = require('loopback'); -var app = loopback(); - -app.get('/', function(req, res){ - res.send('hello world'); -}); - -app.listen(3000); -``` - -> **Notes** -> -> - extends [express](http://expressjs.com/api.html#express) -> - see [express docs](http://expressjs.com/api.html) for details -> - supports [express / connect middleware](http://expressjs.com/api.html#middleware) - -#### app.boot([options]) - -Initialize an application from an options object or a set of JSON and JavaScript files. - -**What happens during an app _boot_?** - -1. **DataSources** are created from an `options.dataSources` object or `datasources.json` in the current directory -2. **Models** are created from an `options.models` object or `models.json` in the current directory -3. Any JavaScript files in the `./models` directory are loaded with `require()`. - -**Options** - - - `cwd` - _optional_ - the directory to use when loading JSON and JavaScript files - - `models` - _optional_ - an object containing `Model` definitions - - `dataSources` - _optional_ - an object containing `DataSource` definitions - -> **NOTE:** mixing `app.boot()` and `app.model(name, config)` in multiple files may result -> in models being **undefined** due to race conditions. To avoid this when using `app.boot()` -> make sure all models are passed as part of the `models` definition. - - -**Model Definitions** - -The following is an example of an object containing two `Model` definitions: "location" and "inventory". - -```js -{ - "dealership": { - // a reference, by name, to a dataSource definition - "dataSource": "my-db", - // the options passed to Model.extend(name, properties, options) - "options": { - "relationships": { - "cars": { - "type": "hasMany", - "model": "Car", - "foreignKey": "dealerId" - } - }, - "remoteMethods": { - "nearby": { - "description": "Find nearby locations around the geo point", - "accepts": [ - {"arg": "here", "type": "GeoPoint", "required": true, "description": "geo location (lat & lng)"} - ], - "returns": {"arg": "locations", "root": true} - } - } - }, - // the properties passed to Model.extend(name, properties, options) - "properties": { - "id": {"id": true}, - "name": "String", - "zip": "Number", - "address": "String" - } - }, - "car": { - "dataSource": "my-db" - "properties": { - "id": { - "type": "String", - "required": true, - "id": true - }, - "make": { - "type": "String", - "required": true - }, - "model": { - "type": "String", - "required": true - } - } - } -} -``` - -**Model Definition Properties** - - - `dataSource` - **required** - a string containing the name of the data source definition to attach the `Model` to - - `options` - _optional_ - an object containing `Model` options - - `properties` _optional_ - an object defining the `Model` properties in [LoopBack Definition Language](http://docs.strongloop.com/loopback-datasource-juggler/#loopback-definition-language) - -**DataSource Definition Properties** - - - `connector` - **required** - the name of the [connector](#working-with-data-sources-and-connectors) - -#### app.model(name, definition) - -Define a `Model` and export it for use by remote clients. - -**definition** - - - `public` - **default: true** attach the `Model` to the app and export its methods to clients - - `dataSource` - **required** the name of the `DataSource` to attach the `Model` to - -**Example** - -```js -// declare a DataSource -app.boot({ - dataSources: { - db: { - connector: 'mongodb', - url: 'mongodb://localhost:27015/my-database-name' - } - } -}); - -// describe a model -var modelDefinition = {dataSource: 'db'}; - -// create the model -var Product = app.model('product', modelDefinition); - -// use the model api -Product.create({name: 'pencil', price: 0.99}, console.log); -``` - -> **Note** - this will expose all [shared methods](#shared-methods) on the model. - -You may also export an existing `Model` by calling `app.model(Model)` like the example below. - -#### app.models.MyModel - -All models are avaialbe from the `loopback.models` object. In the following -example the `Product` and `CustomerReceipt` models are accessed using -the `models` object. - -> **NOTE:** you must call `app.boot()` in order to build the app.models object. - -```js -var loopback = require('loopback'); -var app = loopback(); -app.boot({ - dataSources: { - db: {connector: 'memory'} - } -}); -app.model('product', {dataSource: 'db'}); -app.model('customer-receipt', {dataSource: 'db'}); - -// available based on the given name -var Product = app.models.Product; - -// also available as camelCase -var product = app.models.product; - -// multi-word models are avaiable as pascal cased -var CustomerReceipt = app.models.CustomerReceipt; - -// also available as camelCase -var customerReceipt = app.models.customerReceipt; -``` - -#### app.models() - -Get the app's exported models. Only models defined using `app.model()` will show up in this list. - -```js -var models = app.models(); - -models.forEach(function (Model) { - console.log(Model.modelName); // color -}); -``` - -#### app.docs(options) - -Enable swagger REST API documentation. - -**Options** - - - `basePath` The basepath for your API - eg. 'http://localhost:3000'. - -**Example** - -```js -// enable docs -app.docs({basePath: 'http://localhost:3000'}); -``` - -Run your app then navigate to [the api explorer](http://petstore.swagger.wordnik.com/). Enter your API basepath to view your generated docs. - -#### app.use( router ) - -Expose models over specified router. -For example, to expose models over REST using the `loopback.rest` router: - -```js -app.use(loopback.rest()); -``` - -View generated REST documentation by visiting: [http://localhost:3000/_docs](http://localhost:3000/_docs). - - -### Middleware - -LoopBack comes bundled with several `connect` / `express` style middleware. - -#### loopback.token(options) - -**Options** - - - `cookies` - An `Array` of cookie names - - `headers` - An `Array` of header names - - `params` - An `Array` of param names - -Each array is used to add additional keys to find an `accessToken` for a `request`. - -The following example illustrates how to check for an `accessToken` in a custom cookie, query string parameter -and header called `foo-auth`. - -```js -app.use(loopback.token({ - cookies: ['foo-auth'], - headers: ['foo-auth', 'X-Foo-Auth'], - cookies: ['foo-auth', 'foo_auth'] -})); -``` - -**Defaults** - -By default the following names will be checked. These names are appended to any optional names. They will always -be checked, but any names specified will be checked first. - -```js - params.push('access_token'); - headers.push('X-Access-Token'); - headers.push('authorization'); - cookies.push('access_token'); - cookies.push('authorization'); -``` - -> **NOTE:** The `loopback.token()` middleware will only check for [signed cookies](http://expressjs.com/api.html#req.signedCookies). - -### Model - -A Loopback `Model` is a vanilla JavaScript class constructor with an attached set of properties and options. A `Model` instance is created by passing a data object containing properties to the `Model` constructor. A `Model` constructor will clean the object passed to it and only set the values matching the properties you define. - -```js -// valid color -var Color = loopback.createModel('color', {name: String}); -var red = new Color({name: 'red'}); -console.log(red.name); // red - -// invalid color -var foo = new Color({bar: 'bat baz'}); -console.log(foo.bar); // undefined -``` - -**Properties** - -A model defines a list of property names, types and other validation metadata. A [DataSource](#data-source) uses this definition to validate a `Model` during operations such as `save()`. - -**Options** - -Some [DataSources](#data-source) may support additional `Model` options. - -Define A Loopbackmodel. - -```js -var User = loopback.createModel('user', { - first: String, - last: String, - age: Number -}); -``` - -#### Validation (expiremental) - -##### Model.validatesFormatOf(property, options) - -Require a model to include a property that matches the given format. - -```js -User.validatesFormat('name', {with: /\w+/}); -``` - -##### Model.validatesPresenceOf(properties...) - -Require a model to include a property to be considered valid. - -```js -User.validatesPresenceOf('first', 'last', 'age'); -``` - -##### Model.validatesLengthOf(property, options) - -Require a property length to be within a specified range. - -```js -User.validatesLengthOf('password', {min: 5, message: {min: 'Password is too short'}}); -``` - -##### Model.validatesInclusionOf(property, options) - -Require a value for `property` to be in the specified array. - -```js -User.validatesInclusionOf('gender', {in: ['male', 'female']}); -``` - -##### Model.validatesExclusionOf(property, options) - -Require a value for `property` to not exist in the specified array. - -```js -User.validatesExclusionOf('domain', {in: ['www', 'billing', 'admin']}); -``` - -##### Model.validatesNumericalityOf(property, options) - -Require a value for `property` to be a specific type of `Number`. - -```js -User.validatesNumericalityOf('age', {int: true}); -``` - -##### Model.validatesUniquenessOf(property, options) - -Ensure the value for `property` is unique in the collection of models. - -```js -User.validatesUniquenessOf('email', {message: 'email is not unique'}); -``` - -**Note:** not available for all [connectors](#connectors). - -Currently supported in these connectors: - - - [In Memory](#memory-connector) - - [Oracle](http://github.com/strongloop/loopback-connector-oracle) - - [MongoDB](http://github.com/strongloop/loopback-connector-mongodb) - -##### myModel.isValid() - -Validate the model instance. - -```js -user.isValid(function (valid) { - if (!valid) { - console.log(user.errors); - // => hash of errors - // => { - // => username: [errmessage, errmessage, ...], - // => email: ... - // => } - } -}); -``` - -#### Model.properties - -An object containing a normalized set of properties supplied to `loopback.createModel(name, properties)`. - -Example: - -```js -var props = { - a: String, - b: {type: 'Number'}, - c: {type: 'String', min: 10, max: 100}, - d: Date, - e: loopback.GeoPoint -}; - -var MyModel = loopback.createModel('foo', props); - -console.log(MyModel.properties); -``` - -Outputs: - -```js -{ - "a": {type: String}, - "b": {type: Number}, - "c": { - "type": String, - "min": 10, - "max": 100 - }, - "d": {type: Date}, - "e": {type: GeoPoint}, - "id": { - "id": 1 - } -} -``` - -#### Model.attachTo(dataSource) - -Attach a model to a [DataSource](#data-source). Attaching a [DataSource](#data-source) updates the model with additional methods and behaviors. - -```js -var oracle = loopback.createDataSource({ - connector: require('loopback-connector-oracle'), - host: '111.22.333.44', - database: 'MYDB', - username: 'username', - password: 'password' -}); - -User.attachTo(oracle); -``` - -**Note:** until a model is attached to a data source it will **not** have any **attached methods**. - -#### CRUD and Query Mixins - -Mixins are added by attaching a vanilla model to a [data source](#data-source) with a [connector](#connectors). Each [connector](#connectors) enables its own set of operations that are mixed into a `Model` as methods. To see available methods for a data source call `dataSource.operations()`. - -Log the available methods for a memory data source. - -```js -var ops = loopback - .createDataSource({connector: loopback.Memory}) - .operations(); - -console.log(Object.keys(ops)); -``` - -Outputs: - -```js -[ 'create', - 'updateOrCreate', - 'upsert', - 'findOrCreate', - 'exists', - 'findById', - 'find', - 'all', - 'findOne', - 'destroyAll', - 'deleteAll', - 'count', - 'include', - 'relationNameFor', - 'hasMany', - 'belongsTo', - 'hasAndBelongsToMany', - 'save', - 'isNewRecord', - 'destroy', - 'delete', - 'updateAttribute', - 'updateAttributes', - 'reload' ] -``` - -Here is the definition of the `count()` operation. - -```js -{ - accepts: [ { arg: 'where', type: 'object' } ], - http: { verb: 'get', path: '/count' }, - remoteEnabled: true, - name: 'count' -} -``` - -#### Static Methods - -**Note:** These are the default mixin methods for a `Model` attached to a data source. See the specific connector for additional API documentation. - -##### Model.create(data, [callback]) - -Create an instance of Model with given data and save to the attached data source. Callback is optional. - -```js -User.create({first: 'Joe', last: 'Bob'}, function(err, user) { - console.log(user instanceof User); // true -}); -``` - -**Note:** You must include a callback and use the created model provided in the callback if your code depends on your model being saved or having an `id`. - -##### Model.count([query], callback) - -Query count of Model instances in data source. Optional query param allows to count filtered set of Model instances. - -```js -User.count({approved: true}, function(err, count) { - console.log(count); // 2081 -}); -``` - -##### Model.find(filter, callback) - -Find all instances of Model, matched by query. Fields used for filter and sort should be declared with `{index: true}` in model definition. - -**filter** - - - **where** `Object` { key: val, key2: {gt: 'val2'}} The search criteria - - Format: {key: val} or {key: {op: val}} - - Operations: - - gt: > - - gte: >= - - lt: < - - lte: <= - - between - - inq: IN - - nin: NOT IN - - neq: != - - like: LIKE - - nlike: NOT LIKE - - - **include** `String`, `Object` or `Array` Allows you to load relations of several objects and optimize numbers of requests. - - Format: - - 'posts': Load posts - - ['posts', 'passports']: Load posts and passports - - {'owner': 'posts'}: Load owner and owner's posts - - {'owner': ['posts', 'passports']}: Load owner, owner's posts, and owner's passports - - {'owner': [{posts: 'images'}, 'passports']}: Load owner, owner's posts, owner's posts' images, and owner's passports - - - **order** `String` The sorting order - - Format: 'key1 ASC, key2 DESC' - - - **limit** `Number` The maximum number of instances to be returned - - **skip** `Number` Skip the number of instances - - **offset** `Number` Alias for skip - - - **fields** `Object|Array|String` The included/excluded fields - - `['foo']` or `'foo'` - include only the foo property - - `['foo', 'bar']` - include the foo and bar properties - - `{foo: true}` - include only foo - - `{bat: false}` - include all properties, exclude bat - -Find the second page of 10 users over age 21 in descending order exluding the password property. - -```js -User.find({ - where: { - age: {gt: 21}}, - order: 'age DESC', - limit: 10, - skip: 10, - fields: {password: false} - }, - console.log -); -``` - -**Note:** See the specific connector's [docs](#connectors) for more info. - -##### Model.destroyAll(callback) - -Delete all Model instances from data source. **Note:** destroyAll method does not perform destroy hooks. - -##### Model.findById(id, callback) - -Find instance by id. - -```js -User.findById(23, function(err, user) { - console.info(user.id); // 23 -}); -``` - -##### Model.findOne(where, callback) - -Find a single instance that matches the given where expression. - -```js -User.findOne({id: 23}, function(err, user) { - console.info(user.id); // 23 -}); -``` - -##### Model.upsert(data, callback) - -Update when record with id=data.id found, insert otherwise. **Note:** no setters, validations or hooks applied when using upsert. - -##### Custom Static Methods - -Define a static model method. - -```js -User.login = function (username, password, fn) { - var passwordHash = hashPassword(password); - this.findOne({username: username}, function (err, user) { - var failErr = new Error('login failed'); - - if(err) { - fn(err); - } else if(!user) { - fn(failErr); - } else if(user.password === passwordHash) { - MyAccessTokenModel.create({userId: user.id}, function (err, accessToken) { - fn(null, accessToken.id); - }); - } else { - fn(failErr); - } - }); -} -``` - -Setup the static model method to be exposed to clients as a [remote method](#remote-method). - -```js -loopback.remoteMethod( - User.login, - { - accepts: [ - {arg: 'username', type: 'string', required: true}, - {arg: 'password', type: 'string', required: true} - ], - returns: {arg: 'accessTokenId', type: 'any'}, - http: {path: '/sign-in'} - } -); -``` - -#### Instance Methods - -**Note:** These are the default mixin methods for a `Model` attached to a data source. See the specific connector for additional API documentation. - -##### model.save([options], [callback]) - -Save an instance of a Model to the attached data source. - -```js -var joe = new User({first: 'Joe', last: 'Bob'}); -joe.save(function(err, user) { - if(user.errors) { - console.log(user.errors); - } else { - console.log(user.id); - } -}); -``` - -##### model.updateAttributes(data, [callback]) - -Save specified attributes to the attached data source. - -```js -user.updateAttributes({ - first: 'updatedFirst', - name: 'updatedLast' -}, fn); -``` - -##### model.destroy([callback]) - -Remove a model from the attached data source. - -```js -model.destroy(function(err) { - // model instance destroyed -}); -``` - -##### Custom Instance Methods - -Define an instance method. - -```js -User.prototype.logout = function (fn) { - MyAccessTokenModel.destroyAll({userId: this.id}, fn); -} -``` - -Define a remote model instance method. - -```js -loopback.remoteMethod(User.prototype.logout) -``` - -#### Remote Methods - -Both instance and static methods can be exposed to clients. A remote method must accept a callback with the conventional `fn(err, result, ...)` signature. - -##### loopback.remoteMethod(fn, [options]) - -Expose a remote method. - -```js -Product.stats = function(fn) { - var statsResult = { - totalPurchased: 123456 - }; - var err = null; - - // callback with an error and the result - fn(err, statsResult); -} - -loopback.remoteMethod( - Product.stats, - { - returns: {arg: 'stats', type: 'object'}, - http: {path: '/info', verb: 'get'} - } -); -``` - -**Options** - - - **accepts** - (optional) an arguments description specifying the remote method's arguments. - - **returns** - (optional) an arguments description specifying the remote methods callback arguments. - - **http** - (advanced / optional, object) http routing info - - **http.path** - the path relative to the model the method will be exposed at. May be a path fragment (eg. '/:myArg') which will be populated by an arg of the same name in the accepts description. For example the stats method above will be at the whole path `/products/stats`. - - **http.verb** - (get, post, put, del, all) - the route verb the method will be available from. - -**Argument Description** - -An arguments description defines either a single argument as an object or an ordered set of arguments as an array. - -```js -// examples -{arg: 'myArg', type: 'number'} - -[ - {arg: 'arg1', type: 'number', required: true}, - {arg: 'arg2', type: 'array'} -] -``` - -**Types** - -Each argument may define any of the [loopback types](#loopback-types). - -**Notes:** - - - The callback is an assumed argument and does not need to be specified in the accepts array. - - The err argument is also assumed and does not need to be specified in the returns array. - -#### Remote Hooks - -Run a function before or after a remote method is called by a client. - -```js -// *.save === prototype.save -User.beforeRemote('*.save', function(ctx, user, next) { - if(ctx.user) { - next(); - } else { - next(new Error('must be logged in to update')) - } -}); - -User.afterRemote('*.save', function(ctx, user, next) { - console.log('user has been saved', user); - next(); -}); -``` - -Remote hooks also support wildcards. Run a function before any remote method is called. - -```js -// ** will match both prototype.* and *.* -User.beforeRemote('**', function(ctx, user, next) { - console.log(ctx.methodString, 'was invoked remotely'); // users.prototype.save was invoked remotely - next(); -}); -``` - -Other wildcard examples - -```js -// run before any static method eg. User.find -User.beforeRemote('*', ...); - -// run before any instance method eg. User.prototype.save -User.beforeRemote('prototype.*', ...); - -// prevent password hashes from being sent to clients -User.afterRemote('**', function (ctx, user, next) { - if(ctx.result) { - if(Array.isArray(ctx.result)) { - ctx.result.forEach(function (result) { - result.password = undefined; - }); - } else { - ctx.result.password = undefined; - } - } - - next(); -}); -``` - -#### Context - -Remote hooks are provided with a Context `ctx` object which contains transport specific data (eg. for http: `req` and `res`). The `ctx` object also has a set of consistent apis across transports. - -##### ctx.user - -A `Model` representing the user calling the method remotely. **Note:** this is undefined if the remote method is not invoked by a logged in user. - -##### ctx.result - -During `afterRemote` hooks, `ctx.result` will contain the data about to be sent to a client. Modify this object to transform data before it is sent. - -##### Rest - -When [loopback.rest](#loopbackrest) is used the following `ctx` properties are available. - -###### ctx.req - -The express ServerRequest object. [See full documentation](http://expressjs.com/api.html#req). - -###### ctx.res - -The express ServerResponse object. [See full documentation](http://expressjs.com/api.html#res). - -#### Relationships - -##### Model.hasMany(Model, options) - -Define a "one to many" relationship. - -```js -// by referencing model -Book.hasMany(Chapter); -// specify the name -Book.hasMany('chapters', {model: Chapter}); -``` - -Query and create the related models. - -```js -Book.create(function(err, book) { - // create a chapter instance - // ready to be saved in the data source - var chapter = book.chapters.build({name: 'Chapter 1'}); - - // save the new chapter - chapter.save(); - - // you can also call the Chapter.create method with - // the `chapters` property which will build a chapter - // instance and save the it in the data source - book.chapters.create({name: 'Chapter 2'}, function(err, savedChapter) { - // this callback is optional - }); - - // query chapters for the book using the - book.chapters(function(err, chapters) { - // all chapters with bookId = book.id - console.log(chapters); - }); - - book.chapters({where: {name: 'test'}, function(err, chapters) { - // all chapters with bookId = book.id and name = 'test' - console.log(chapters); - }); -}); -``` - -##### Model.belongsTo(Model, options) - -A `belongsTo` relation sets up a one-to-one connection with another model, such -that each instance of the declaring model "belongs to" one instance of the other -model. For example, if your application includes users and posts, and each post -can be written by exactly one user. - -```js - Post.belongsTo(User, {as: 'author', foreignKey: 'userId'}); -``` - -The code above basically says Post has a reference called `author` to User using -the `userId` property of Post as the foreign key. Now we can access the author -in one of the following styles: - -```js - post.author(callback); // Get the User object for the post author asynchronously - post.author(); // Get the User object for the post author synchronously - post.author(user) // Set the author to be the given user -``` - -##### Model.hasAndBelongsToMany(Model, options) - -A `hasAndBelongsToMany` relation creates a direct many-to-many connection with -another model, with no intervening model. For example, if your application -includes users and groups, with each group having many users and each user -appearing in many groups, you could declare the models this way, - -```js - User.hasAndBelongsToMany('groups', {model: Group, foreignKey: 'groupId'}); - user.groups(callback); // get groups of the user - user.groups.create(data, callback); // create a new group and connect it with the user - user.groups.add(group, callback); // connect an existing group with the user - user.groups.remove(group, callback); // remove the user from the group -``` - -#### Shared Methods - -Any static or instance method can be decorated as `shared`. These methods are exposed over the provided transport (eg. [loopback.rest](#rest)). - -### Data Source - -A Loopback `DataSource` provides [Models](#model) with the ability to manipulate data. Attaching a `DataSource` to a `Model` adds [instance methods](#instance-methods) and [static methods](#static-methods) to the `Model`. The added methods may be [remote methods](#remote-methods). - -Define a data source for persisting models. - -```js -var oracle = loopback.createDataSource({ - connector: 'oracle', - host: '111.22.333.44', - database: 'MYDB', - username: 'username', - password: 'password' -}); -``` - -#### dataSource.createModel(name, properties, options) - -Define a model and attach it to a `DataSource`. - -```js -var Color = oracle.createModel('color', {name: String}); -``` - -#### dataSource.discoverModelDefinitions([username], fn) - -Discover a set of model definitions (table or collection names) based on tables or collections in a data source. - -```js -oracle.discoverModelDefinitions(function (err, models) { - models.forEach(function (def) { - // def.name ~ the model name - oracle.discoverSchema(null, def.name, function (err, schema) { - console.log(schema); - }); - }); -}); -``` - -#### dataSource.discoverSchema([owner], name, fn) - -Discover the schema of a specific table or collection. - -**Example schema from oracle connector:** - -```js - { - "name": "Product", - "options": { - "idInjection": false, - "oracle": { - "schema": "BLACKPOOL", - "table": "PRODUCT" - } - }, - "properties": { - "id": { - "type": "String", - "required": true, - "length": 20, - "id": 1, - "oracle": { - "columnName": "ID", - "dataType": "VARCHAR2", - "dataLength": 20, - "nullable": "N" - } - }, - "name": { - "type": "String", - "required": false, - "length": 64, - "oracle": { - "columnName": "NAME", - "dataType": "VARCHAR2", - "dataLength": 64, - "nullable": "Y" - } - }, - "audibleRange": { - "type": "Number", - "required": false, - "length": 22, - "oracle": { - "columnName": "AUDIBLE_RANGE", - "dataType": "NUMBER", - "dataLength": 22, - "nullable": "Y" - } - }, - "effectiveRange": { - "type": "Number", - "required": false, - "length": 22, - "oracle": { - "columnName": "EFFECTIVE_RANGE", - "dataType": "NUMBER", - "dataLength": 22, - "nullable": "Y" - } - }, - "rounds": { - "type": "Number", - "required": false, - "length": 22, - "oracle": { - "columnName": "ROUNDS", - "dataType": "NUMBER", - "dataLength": 22, - "nullable": "Y" - } - }, - "extras": { - "type": "String", - "required": false, - "length": 64, - "oracle": { - "columnName": "EXTRAS", - "dataType": "VARCHAR2", - "dataLength": 64, - "nullable": "Y" - } - }, - "fireModes": { - "type": "String", - "required": false, - "length": 64, - "oracle": { - "columnName": "FIRE_MODES", - "dataType": "VARCHAR2", - "dataLength": 64, - "nullable": "Y" - } - } - } - } -``` - -#### dataSource.enableRemote(operation) - -Enable remote access to a data source operation. Each [connector](#connector) has its own set of set remotely enabled and disabled operations. You can always list these by calling `dataSource.operations()`. - - -#### dataSource.disableRemote(operation) - -Disable remote access to a data source operation. Each [connector](#connector) has its own set of set enabled and disabled operations. You can always list these by calling `dataSource.operations()`. - -```js -// all rest data source operations are -// disabled by default -var oracle = loopback.createDataSource({ - connector: require('loopback-connector-oracle'), - host: '...', - ... -}); - -// or only disable it as a remote method -oracle.disableRemote('destroyAll'); -``` - -**Notes:** - - - disabled operations will not be added to attached models - - disabling the remoting for a method only affects client access (it will still be available from server models) - - data sources must enable / disable operations before attaching or creating models - -#### dataSource.operations() - -List the enabled and disabled operations. - - console.log(oracle.operations()); - -Output: - -```js -{ - find: { - remoteEnabled: true, - accepts: [...], - returns: [...] - enabled: true - }, - save: { - remoteEnabled: true, - prototype: true, - accepts: [...], - returns: [...], - enabled: true - }, - ... -} -``` - -#### Connectors - -Create a data source with a specific connector. See **available connectors** for specific connector documentation. - -```js -var memory = loopback.createDataSource({ - connector: loopback.Memory -}); -``` - -**Database Connectors** - - - [In Memory](#memory-connector) - - [Oracle](http://github.com/strongloop/loopback-connector-oracle) - - [MongoDB](http://github.com/strongloop/loopback-connector-mongodb) - - [MySQL](http://github.com/strongloop/loopback-connector-mysql) - In Development - - [SQLite3](http://github.com/strongloop/loopback-connector-sqlite) - In Development - - [Postgres](http://github.com/strongloop/loopback-connector-postgres) - In Development - - [Redis](http://github.com/strongloop/loopback-connector-redis) - In Development - - [CouchDB](http://github.com/strongloop/loopback-connector-couch) - In Development - - [Firebird](http://github.com/strongloop/loopback-connector-firebird) - In Development - -**Other Connectors** - - - [REST](http://github.com/strongloop/loopback-connector-rest) - - [Email](#email-model) - - [JSON RPC](http://github.com/strongloop/loopback-connector-jsonrpc) - In Development - - [SOAP](http://github.com/strongloop/loopback-connector-soap) - In Development - - [Push Notifications](https://github.com/strongloop/loopback-push-notification) - In Development - - [File Storage](https://github.com/strongloop/loopback-storage-service) - In Development - -**Installing Connectors** - -Include the connector in your package.json dependencies and run `npm install`. - -```js -{ - "dependencies": { - "loopback-connector-oracle": "latest" - } -} -``` - -##### Memory Connector - -The built-in memory connector allows you to test your application without connecting to an actual persistent data source, such as a database. Although the memory connector is very well tested it is not recommended to be used in production. Creating a data source using the memory connector is very simple. - -```js -// use the built in memory function -// to create a memory data source -var memory = loopback.memory(); - -// or create it using the standard -// data source creation api -var memory = loopback.createDataSource({ - connector: loopback.Memory -}); - -// create a model using the -// memory data source -var properties = { - name: String, - price: Number -}; - -var Product = memory.createModel('product', properties); - -Product.create([ - {name: 'apple', price: 0.79}, - {name: 'pear', price: 1.29}, - {name: 'orange', price: 0.59}, -], count); - -function count() { - Product.count(console.log); // 3 -} -``` - -**CRUD / Query** - -The memory connector supports all the standard [query and crud operations](#crud-and-query-mixins) to allow you to test your models against an in memory data source. - -**GeoPoint Filtering** - -The memory connector also supports geo-filtering when using the `find()` operation with an attached model. See [GeoPoint](#geopoint) for more information on geo-filtering. - -### GeoPoint - -Use the `GeoPoint` class. - -```js -var GeoPoint = require('loopback').GeoPoint; -``` - -Embed a latitude / longitude point in a [Model](#model). - -```js -var CoffeeShop = loopback.createModel('coffee-shop', { - location: 'GeoPoint' -}); -``` - -Loopback Model's with a GeoPoint property and an attached DataSource may be queried using geo spatial filters and sorting. - -Find the 3 nearest coffee shops. - -```js -CoffeeShop.attachTo(oracle); -var here = new GeoPoint({lat: 10.32424, lng: 5.84978}); -CoffeeShop.find({where: {location: {near: here}}, limit:3}, function(err, nearbyShops) { - console.info(nearbyShops); // [CoffeeShop, ...] -}); -``` - -#### geoPoint.distanceTo(geoPoint, options) - -Get the distance to another `GeoPoint`. - -```js -var here = new GeoPoint({lat: 10, lng: 10}); -var there = new GeoPoint({lat: 5, lng: 5}); -console.log(here.distanceTo(there, {type: 'miles'})); // 438 -``` - -#### GeoPoint.distanceBetween(a, b, options) - -Get the distance between two points. - -```js -GeoPoint.distanceBetween(here, there, {type: 'miles'}) // 438 -``` - -#### Distance Types - -**Note:** all distance methods use `miles` by default. - - - `miles` - - `radians` - - `kilometers` - - `meters` - - `miles` - - `feet` - - `degrees` - -#### geoPoint.lat - -The latitude point in degrees. Range: -90 to 90. - -#### geoPoint.lng - -The longitude point in degrees. Range: -180 to 180. + * [App](api-app.md) + * [Model](api-model.md) + * [Remote methods and hooks](api-model-remote.md) + * [DataSource](api-datasource.md) + * [GeoPoint](api-geopoint.md)