├── .travis.yml ├── .babelrc ├── .npmignore ├── src ├── rest │ ├── index.js │ ├── request.js │ ├── superagent.js │ ├── fetch.js │ ├── jquery.js │ └── base.js ├── sockets │ ├── index.js │ └── base.js ├── client.js └── utils.js ├── bower.json ├── test ├── rest │ ├── fetch.test.js │ ├── request.test.js │ ├── superagent.test.js │ └── jquery.test.js ├── sockets │ ├── socketio.test.js │ └── primus.test.js ├── client.test.js ├── fixture.js └── base.js ├── .jshintrc ├── .gitignore ├── LICENSE ├── package.json ├── readme.md └── dist └── feathers.js /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: "node" 4 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["transform-object-assign"], 3 | "presets": [ "es2015" ] 4 | } 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .git* 2 | .DS_Store 3 | .babelrc 4 | *.markdown 5 | *.md 6 | .idea 7 | !dist/ 8 | !lib/ 9 | src/ 10 | -------------------------------------------------------------------------------- /src/rest/index.js: -------------------------------------------------------------------------------- 1 | import jquery from './jquery'; 2 | import request from './request'; 3 | import superagent from './superagent'; 4 | import fetch from './fetch'; 5 | 6 | export default { jquery, request, superagent, fetch }; 7 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "feathers-client", 3 | "version": "0.1.0", 4 | "repo": "feathersjs/feathers-client", 5 | "keywords": [ 6 | "feathers", 7 | "jquery", 8 | "websocket", 9 | "socket.io", 10 | "ajax", 11 | "rest", 12 | "rel-time" 13 | ], 14 | "main": "dist/feathers.js", 15 | "license": "MIT" 16 | } 17 | -------------------------------------------------------------------------------- /src/sockets/index.js: -------------------------------------------------------------------------------- 1 | import { Service } from './base'; 2 | 3 | function base(socket) { 4 | if(!socket) { 5 | throw new Error('No socket provided'); 6 | } 7 | 8 | return function() { 9 | this.Service = Service; 10 | this.connection = socket; 11 | }; 12 | } 13 | 14 | function socketio(socket) { 15 | if(typeof window !== 'undefined' && window.io && typeof socket === 'string'){ 16 | socket = window.io(socket); 17 | } 18 | 19 | return base(socket); 20 | } 21 | 22 | export default { 23 | socketio, 24 | primus: base 25 | }; -------------------------------------------------------------------------------- /test/rest/fetch.test.js: -------------------------------------------------------------------------------- 1 | import fetch from 'node-fetch'; 2 | 3 | import app from '../fixture'; 4 | import baseTests from '../base'; 5 | import { Service } from '../../src/rest/fetch'; 6 | 7 | describe('fetch REST connector', function() { 8 | let service = new Service('todos', { 9 | base: 'http://localhost:8889', 10 | connection: fetch 11 | }); 12 | 13 | before(function(done) { 14 | this.server = app().listen(8889, done); 15 | }); 16 | 17 | after(function(done) { 18 | this.server.close(done); 19 | }); 20 | 21 | baseTests(service); 22 | }); 23 | -------------------------------------------------------------------------------- /test/rest/request.test.js: -------------------------------------------------------------------------------- 1 | import request from 'request'; 2 | 3 | import app from '../fixture'; 4 | import baseTests from '../base'; 5 | import { Service } from '../../src/rest/request'; 6 | 7 | describe('node-request REST connector', function() { 8 | let service = new Service('todos', { 9 | base: 'http://localhost:6777', 10 | connection: request 11 | }); 12 | 13 | before(function(done) { 14 | this.server = app().listen(6777, done); 15 | }); 16 | 17 | after(function(done) { 18 | this.server.close(done); 19 | }); 20 | 21 | baseTests(service); 22 | }); 23 | -------------------------------------------------------------------------------- /test/rest/superagent.test.js: -------------------------------------------------------------------------------- 1 | import superagent from 'superagent'; 2 | 3 | import app from '../fixture'; 4 | import baseTests from '../base'; 5 | import { Service } from '../../src/rest/superagent'; 6 | 7 | describe('Superagent REST connector', function() { 8 | let service = new Service('todos', { 9 | base: 'http://localhost:8889', 10 | connection: superagent 11 | }); 12 | 13 | before(function(done) { 14 | this.server = app().listen(8889, done); 15 | }); 16 | 17 | after(function(done) { 18 | this.server.close(done); 19 | }); 20 | 21 | baseTests(service); 22 | }); 23 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "browser": true, 4 | "esnext": true, 5 | "bitwise": true, 6 | "camelcase": false, 7 | "curly": true, 8 | "eqeqeq": true, 9 | "immed": true, 10 | "indent": 2, 11 | "latedef": "nofunc", 12 | "newcap": false, 13 | "noarg": true, 14 | "quotmark": "single", 15 | "regexp": true, 16 | "undef": true, 17 | "unused": true, 18 | "strict": false, 19 | "trailing": true, 20 | "smarttabs": true, 21 | "white": false, 22 | "globals": { 23 | "it": true, 24 | "describe": true, 25 | "before": true, 26 | "beforeEach": true, 27 | "after": true, 28 | "afterEach": true, 29 | "exports": true 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/client.js: -------------------------------------------------------------------------------- 1 | import { stripSlashes } from './utils'; 2 | import rest from './rest'; 3 | import sockets from './sockets'; 4 | 5 | export class Client { 6 | constructor(base) { 7 | this.base = base; 8 | this.services = {}; 9 | } 10 | 11 | configure(cb) { 12 | cb.call(this); 13 | return this; 14 | } 15 | 16 | service(name) { 17 | name = stripSlashes(name); 18 | if (!this.services[name]) { 19 | this.services[name] = new this.Service(name, this); 20 | } 21 | return this.services[name]; 22 | } 23 | } 24 | 25 | function client(base = '/') { 26 | return new Client(base); 27 | } 28 | 29 | Object.assign(client, rest, sockets); 30 | 31 | export default module.exports = client; 32 | -------------------------------------------------------------------------------- /test/sockets/socketio.test.js: -------------------------------------------------------------------------------- 1 | import feathers from 'feathers'; 2 | import io from 'socket.io-client'; 3 | 4 | import app from '../fixture'; 5 | import baseTests from '../base'; 6 | import { Service } from '../../src/sockets/base'; 7 | 8 | describe('Socket.io connector', function() { 9 | let socket = io('http://localhost:9988'); 10 | let service = new Service('todos', { 11 | connection: socket 12 | }); 13 | 14 | before(function(done) { 15 | this.server = app(function() { 16 | this.configure(feathers.socketio()); 17 | }).listen(9988, done); 18 | }); 19 | 20 | after(function(done) { 21 | socket.disconnect(); 22 | this.server.close(done); 23 | }); 24 | 25 | baseTests(service); 26 | }); 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # Compiled binary addons (http://nodejs.org/api/addons.html) 20 | build/Release 21 | 22 | # Dependency directory 23 | # Commenting this out is preferred by some people, see 24 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- 25 | node_modules 26 | 27 | # Users Environment Variables 28 | .lock-wscript 29 | 30 | lib/ 31 | -------------------------------------------------------------------------------- /src/rest/request.js: -------------------------------------------------------------------------------- 1 | import { Base } from './base'; 2 | 3 | export class Service extends Base { 4 | request(options) { 5 | return new Promise((resolve, reject) => { 6 | this.connection(Object.assign({ 7 | json: true 8 | }, options), function(error, res, data) { 9 | if(!error && res.statusCode >= 400) { 10 | return reject(new Error(data)); 11 | } 12 | 13 | resolve(data); 14 | }); 15 | }); 16 | } 17 | } 18 | 19 | export default function(request) { 20 | if(!request) { 21 | throw new Error('request instance needs to be provided'); 22 | } 23 | 24 | return function() { 25 | this.Service = Service; 26 | this.connection = request; 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /test/sockets/primus.test.js: -------------------------------------------------------------------------------- 1 | import feathers from 'feathers'; 2 | 3 | import baseTests from '../base'; 4 | import app from '../fixture'; 5 | import { Service } from '../../src/sockets/base'; 6 | 7 | describe('Primus connector', function() { 8 | var service = new Service('todos', {}); 9 | var socket; 10 | 11 | before(function(done) { 12 | this.server = app(function() { 13 | this.configure(feathers.primus({ 14 | transformer: 'websockets' 15 | }, function(primus) { 16 | service.connection = socket = new primus.Socket('http://localhost:12012'); 17 | })); 18 | }).listen(12012, done); 19 | }); 20 | 21 | after(function(done) { 22 | socket.socket.close(); 23 | this.server.close(done); 24 | }); 25 | 26 | baseTests(service); 27 | }); 28 | -------------------------------------------------------------------------------- /src/rest/superagent.js: -------------------------------------------------------------------------------- 1 | import { Base } from './base'; 2 | 3 | export class Service extends Base { 4 | request(options) { 5 | var superagent = this.connection(options.method, options.url) 6 | .type(options.type || 'json'); 7 | 8 | return new Promise((resolve, reject) => { 9 | if(options.body) { 10 | superagent.send(options.body); 11 | } 12 | 13 | superagent.end(function(error, res) { 14 | if(error) { 15 | return reject(error); 16 | } 17 | 18 | resolve(res && res.body); 19 | }); 20 | }); 21 | } 22 | } 23 | 24 | export default function(superagent) { 25 | if(!superagent) { 26 | throw new Error('Superagent needs to be provided'); 27 | } 28 | 29 | return function() { 30 | this.Service = Service; 31 | this.connection = superagent; 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /test/client.test.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import request from 'request'; 3 | 4 | import feathers from '../src/client'; 5 | import app from './fixture'; 6 | 7 | describe('app functionality tests', function() { 8 | before(function(done) { 9 | this.server = app().listen(7575, done); 10 | }); 11 | 12 | after(function(done) { 13 | this.server.close(done); 14 | }); 15 | 16 | it('initializes and connects to a service', function(done) { 17 | let app = feathers('http://localhost:7575') 18 | .configure(feathers.request(request)); 19 | 20 | let service = app.service('todos'); 21 | 22 | service.get(0, { some: 'test' }).then(todo => { 23 | assert.deepEqual(todo, { 24 | query: { some: 'test' }, 25 | text: 'some todo', 26 | complete: false, 27 | id: 0 28 | }); 29 | }).then(done); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /test/rest/jquery.test.js: -------------------------------------------------------------------------------- 1 | import jsdom from 'jsdom'; 2 | 3 | import app from '../fixture'; 4 | import baseTests from '../base'; 5 | import { Service } from '../../src/rest/jquery'; 6 | 7 | describe('jQuery REST connector', function() { 8 | var service = new Service('todos', { 9 | base: 'http://localhost:7676' 10 | }); 11 | 12 | before(function(done) { 13 | this.server = app().listen(7676, function() { 14 | jsdom.env({ 15 | html: '', 16 | scripts: [ 17 | 'http://code.jquery.com/jquery-2.1.4.js' 18 | ], 19 | done: function (err, window) { 20 | window.jQuery.support.cors = true; 21 | service.connection = window.jQuery; 22 | done(); 23 | } 24 | }); 25 | }); 26 | }); 27 | 28 | after(function(done) { 29 | this.server.close(done); 30 | }); 31 | 32 | baseTests(service); 33 | }); 34 | -------------------------------------------------------------------------------- /src/rest/fetch.js: -------------------------------------------------------------------------------- 1 | import { Base } from './base'; 2 | 3 | export class Service extends Base { 4 | request(options) { 5 | var fetchOptions = { 6 | method: options.method, 7 | headers: { 8 | 'Accept': 'application/json' 9 | } 10 | }; 11 | 12 | return new Promise((resolve, reject) => { 13 | if (options.body) { 14 | fetchOptions.body = JSON.stringify(options.body); 15 | fetchOptions.headers['Content-Type'] = 'application/json'; 16 | } 17 | this.connection(options.url, fetchOptions) 18 | .then((response) => { 19 | return response.json(); 20 | }) 21 | .then((result) => { 22 | resolve(result); 23 | }).catch((e) => { 24 | reject(e); 25 | }); 26 | }); 27 | } 28 | } 29 | 30 | export default function (fetch) { 31 | if (!fetch) { 32 | throw new Error('fetch needs to be provided'); 33 | } 34 | 35 | return function () { 36 | this.Service = Service; 37 | this.connection = fetch; 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /src/rest/jquery.js: -------------------------------------------------------------------------------- 1 | import { Base } from './base'; 2 | 3 | export class Service extends Base { 4 | request(options) { 5 | let opts = Object.assign({ 6 | dataType: options.type || 'json' 7 | }, options); 8 | 9 | if(options.body) { 10 | opts.data = JSON.stringify(options.body); 11 | opts.contentType = 'application/json'; 12 | } 13 | 14 | delete opts.type; 15 | delete opts.body; 16 | 17 | return new Promise((resolve, reject) => 18 | this.connection.ajax(opts).then(resolve, xhr => { 19 | let error = new Error(xhr.responseText); 20 | error.xhr = xhr; 21 | reject(error); 22 | })); 23 | } 24 | } 25 | 26 | export default function(jQuery) { 27 | if(!jQuery && typeof window !== 'undefined') { 28 | jQuery = window.jQuery; 29 | } 30 | 31 | if(typeof jQuery !== 'function') { 32 | throw new Error('jQuery instance needs to be provided'); 33 | } 34 | 35 | return function() { 36 | this.Service = Service; 37 | this.connection = jQuery; 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Feathers 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /src/sockets/base.js: -------------------------------------------------------------------------------- 1 | import { stripSlashes, methods, events, normalize } from '../utils'; 2 | 3 | export class Service { 4 | constructor(name, app) { 5 | this.events = events; 6 | this.path = stripSlashes(name); 7 | this.connection = app.connection; 8 | this.method = (this.connection && this.connection.io) ? 'emit' : 'send'; 9 | 10 | normalize(this); 11 | } 12 | 13 | emit(... args) { 14 | this.connection[this.method](... args); 15 | } 16 | } 17 | 18 | const emitterMethods = ['on', 'once', 'off']; 19 | 20 | emitterMethods.forEach(method => { 21 | Service.prototype[method] = function(name, callback) { 22 | this.connection[method](`${this.path} ${name}`, callback); 23 | }; 24 | }); 25 | 26 | methods.forEach(method => { 27 | Service.prototype[method] = function(... args) { 28 | let callback = null; 29 | if(typeof args[args.length - 1] === 'function') { 30 | callback = args.pop(); 31 | } 32 | 33 | return new Promise((resolve, reject) => { 34 | args.unshift(`${this.path}::${method}`); 35 | args.push(function(error, data) { 36 | if(callback) { 37 | callback(error, data); 38 | } 39 | 40 | return error ? reject(error) : resolve(data); 41 | }); 42 | 43 | this.connection[this.method](... args); 44 | }); 45 | }; 46 | }); 47 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | import { EventEmitter } from 'events'; 2 | import getArguments from 'feathers-commons/lib/arguments'; 3 | 4 | export function stripSlashes(name) { 5 | return name.replace(/^\/|\/$/g, ''); 6 | } 7 | 8 | export const methods = [ 9 | 'find', 10 | 'get', 11 | 'create', 12 | 'update', 13 | 'patch', 14 | 'remove' 15 | ]; 16 | 17 | export const eventMappings = { 18 | create: 'created', 19 | update: 'updated', 20 | patch: 'patched', 21 | remove: 'removed' 22 | }; 23 | 24 | export const events = Object.keys(eventMappings).map(method => eventMappings[method]); 25 | 26 | export function makeEmitting(target) { 27 | Object.assign(target, EventEmitter.prototype); 28 | Object.keys(eventMappings).forEach(method => { 29 | const old = target[method]; 30 | const eventName = eventMappings[method]; 31 | 32 | if(typeof old === 'function') { 33 | target[method] = function(... args) { 34 | let result = old.apply(this, args); 35 | return result.then(data => { 36 | this.emit(eventName, data); 37 | return data; 38 | }); 39 | }; 40 | } 41 | }); 42 | } 43 | 44 | export function normalize(target) { 45 | methods.forEach(method => { 46 | let old = target[method]; 47 | if(typeof old === 'function') { 48 | target[method] = function(... args) { 49 | return old.apply(this, getArguments(method, args)); 50 | }; 51 | } 52 | }); 53 | } 54 | -------------------------------------------------------------------------------- /test/fixture.js: -------------------------------------------------------------------------------- 1 | import feathers from 'feathers'; 2 | import bodyParser from 'body-parser'; 3 | import memory from 'feathers-memory'; 4 | 5 | Object.defineProperty(Error.prototype, 'toJSON', { 6 | value: function () { 7 | var alt = {}; 8 | 9 | Object.getOwnPropertyNames(this).forEach(function (key) { 10 | alt[key] = this[key]; 11 | }, this); 12 | 13 | return alt; 14 | }, 15 | configurable: true 16 | }); 17 | 18 | module.exports = function(configurer) { 19 | // Create an in-memory CRUD service for our Todos 20 | var todoService = memory().extend({ 21 | get: function(id, params, callback) { 22 | if(params.query.error) { 23 | return callback(new Error('Something went wrong')); 24 | } 25 | 26 | this._super(id, params, function(error, data) { 27 | callback(error, Object.assign({ query: params.query }, data)); 28 | }); 29 | } 30 | }); 31 | 32 | var app = feathers() 33 | // Set up REST and SocketIO APIs 34 | .configure(feathers.rest()) 35 | // Parse HTTP bodies 36 | .use(bodyParser.json()) 37 | .use(bodyParser.urlencoded({ extended: true })) 38 | // Host the current directory (for index.html) 39 | .use(feathers.static(__dirname)) 40 | // Host our Todos service on the /todos path 41 | .use('/todos', todoService); 42 | 43 | if(typeof configurer === 'function') { 44 | configurer.call(app); 45 | } 46 | 47 | app.service('todos').create({ text: 'some todo', complete: false }, {}, function() {}); 48 | 49 | return app; 50 | }; 51 | -------------------------------------------------------------------------------- /src/rest/base.js: -------------------------------------------------------------------------------- 1 | import query from 'querystring'; 2 | import { stripSlashes, normalize, makeEmitting } from '../utils'; 3 | 4 | function callbackify(promise, callback) { 5 | if(typeof callback === 'function') { 6 | promise.then(data => callback(null, data), callback); 7 | } 8 | return promise; 9 | } 10 | 11 | export class Base { 12 | constructor(name, options) { 13 | this.name = stripSlashes(name); 14 | this.options = Object.assign({}, options); 15 | this.connection = options.connection; 16 | this.base = `${options.base}/${this.name}`; 17 | delete this.options.base; 18 | 19 | normalize(this); 20 | makeEmitting(this); 21 | } 22 | 23 | makeUrl(params, id) { 24 | let url = this.base; 25 | 26 | if (typeof id !== 'undefined') { 27 | url += `/${id}`; 28 | } 29 | 30 | if(Object.keys(params).length !== 0) { 31 | const queryString = query.stringify(params); 32 | 33 | url += `?${queryString}`; 34 | } 35 | 36 | return url; 37 | } 38 | 39 | find(params, callback) { 40 | return callbackify(this.request({ 41 | url: this.makeUrl(params), 42 | method: 'GET' 43 | }), callback); 44 | } 45 | 46 | get(id, params, callback) { 47 | return callbackify(this.request({ 48 | url: this.makeUrl(params, id), 49 | method: 'GET' 50 | }), callback); 51 | } 52 | 53 | create(body, params, callback) { 54 | return callbackify(this.request({ 55 | url: this.makeUrl(params), 56 | body, 57 | method: 'POST' 58 | }), callback); 59 | } 60 | 61 | update(id, body, params, callback) { 62 | return callbackify(this.request({ 63 | url: this.makeUrl(params, id), 64 | body, 65 | method: 'PUT' 66 | }), callback); 67 | } 68 | 69 | patch(id, body, params, callback) { 70 | return callbackify(this.request({ 71 | url: this.makeUrl(params, id), 72 | body, 73 | method: 'PATCH' 74 | }), callback); 75 | } 76 | 77 | remove(id, params, callback) { 78 | return callbackify(this.request({ 79 | url: this.makeUrl(params, id), 80 | method: 'DELETE' 81 | }), callback); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "feathers-client", 3 | "description": "Feathers service clients for REST (jQuery, Request, Superagent) and Websocket (Socket.io, Primus) connections", 4 | "version": "0.5.0", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/feathersjs/feathers-client.git" 8 | }, 9 | "license": "MIT", 10 | "bugs": { 11 | "url": "https://github.com/feathersjs/feathers-client/issues" 12 | }, 13 | "homepage": "https://github.com/feathersjs/feathers-client", 14 | "keywords": [ 15 | "feathers", 16 | "feathers-plugin", 17 | "batch", 18 | "rest", 19 | "api" 20 | ], 21 | "author": "David Luecke (https://feathersjs.com)", 22 | "contributors": [], 23 | "engines": { 24 | "node": ">=0.10.0" 25 | }, 26 | "main": "lib/client.js", 27 | "scripts": { 28 | "build": "rm -rf dist/ && mkdir -p dist && browserify src/client.js -t babelify --standalone feathers --outfile dist/feathers.js", 29 | "add-dist": "npm run build && git add dist/ --force && git commit -am \"Updating dist\"", 30 | "prepublish": "npm run compile", 31 | "publish": "git push origin && git push origin --tags", 32 | "release:patch": "npm run add-dist && npm version patch && npm publish", 33 | "release:minor": "npm run add-dist && npm version minor && npm publish", 34 | "release:major": "npm run add-dist && npm version major && npm publish", 35 | "compile": "rm -rf lib/ && babel -d lib/ src/", 36 | "watch": "babel --watch -d lib/ src/", 37 | "jshint": "jshint src/. test/. --config", 38 | "mocha": "mocha test/ --compilers js:babel-core/register --recursive --timeout 5000", 39 | "test": "npm run compile && npm run jshint && npm run mocha" 40 | }, 41 | "directories": { 42 | "lib": "lib" 43 | }, 44 | "dependencies": { 45 | "events": "^1.1.0", 46 | "feathers-commons": "^0.3.0", 47 | "querystring": "^0.2.0", 48 | "uberproto": "^1.1.2" 49 | }, 50 | "devDependencies": { 51 | "babel-cli": "^6.1.4", 52 | "babel-core": "^6.1.4", 53 | "babel-plugin-transform-object-assign": "^6.1.18", 54 | "babel-preset-es2015": "^6.1.4", 55 | "babelify": "^7.2.0", 56 | "body-parser": "^1.12.4", 57 | "browserify": "^10.2.3", 58 | "feathers": "^1.1.0-pre.0", 59 | "feathers-memory": "^0.3.4", 60 | "jquery": "^2.1.4", 61 | "jsdom": "^6.5.1", 62 | "jshint": "^2.8.0", 63 | "mocha": "^2.1.0", 64 | "node-fetch": "^1.3.3", 65 | "request": "^2.56.0", 66 | "socket.io-client": "^1.3.5", 67 | "superagent": "^1.2.0", 68 | "ws": "^0.7.2" 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /test/base.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | 3 | module.exports = function(service) { 4 | describe('Service base tests', function() { 5 | it('.find', function(done) { 6 | service.find().then(todos => assert.deepEqual(todos, [ 7 | { 8 | text: 'some todo', 9 | complete: false, 10 | id: 0 11 | } 12 | ])).then(() => done(), done); 13 | }); 14 | 15 | it('.get and params passing', function(done) { 16 | var query = { 17 | some: 'thing', 18 | other: ['one', 'two'] 19 | }; 20 | 21 | service.get(0, query).then(todo => assert.deepEqual(todo, { 22 | id: 0, 23 | text: 'some todo', 24 | complete: false, 25 | query: query 26 | })).then(() => done(), done); 27 | }); 28 | 29 | it('.create and created event', function(done) { 30 | service.once('created', function(data) { 31 | assert.equal(data.text, 'created todo'); 32 | assert.ok(data.complete); 33 | done(); 34 | }); 35 | 36 | service.create({ text: 'created todo', complete: true }); 37 | }); 38 | 39 | it('.update and updated event', function(done) { 40 | service.once('updated', function(data) { 41 | assert.equal(data.text, 'updated todo'); 42 | assert.ok(data.complete); 43 | done(); 44 | }); 45 | 46 | service.create({ text: 'todo to update', complete: false }) 47 | .then(todo => service.update(todo.id, { 48 | text: 'updated todo', 49 | complete: true 50 | })); 51 | }); 52 | 53 | it('.patch and patched event', function(done) { 54 | service.once('patched', function(data) { 55 | assert.equal(data.text, 'todo to patch'); 56 | assert.ok(data.complete); 57 | done(); 58 | }); 59 | 60 | service.create({ text: 'todo to patch', complete: false }) 61 | .then(todo => service.patch(todo.id, { complete: true })); 62 | }); 63 | 64 | it('.remove and removed event', function(done) { 65 | service.once('removed', function(data) { 66 | assert.equal(data.text, 'todo to remove'); 67 | assert.equal(data.complete, false); 68 | done(); 69 | }); 70 | 71 | service.create({ text: 'todo to remove', complete: false }) 72 | .then(todo => service.remove(todo.id)); 73 | }); 74 | 75 | it('.get with error', function(done) { 76 | service.get(0, { error: true }).then(done, error => { 77 | assert.ok(error && error.message); 78 | done(); 79 | }); 80 | }); 81 | 82 | it('is built correctly', () => { 83 | assert.equal(typeof require('../lib/client'), 'function'); 84 | assert.equal(typeof require('../lib/client').jquery, 'function'); 85 | assert.equal(typeof require('../lib/client').request, 'function'); 86 | assert.equal(typeof require('../lib/client').superagent, 'function'); 87 | assert.equal(typeof require('../lib/client').fetch, 'function'); 88 | assert.equal(typeof require('../lib/client').socketio, 'function'); 89 | assert.equal(typeof require('../lib/client').primus, 'function'); 90 | }); 91 | }); 92 | }; 93 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # feathers-client 2 | 3 | [![Build Status](https://travis-ci.org/feathersjs/feathers-client.png?branch=master)](https://travis-ci.org/feathersjs/feathers-client) 4 | 5 | > A client for Feathers services supporting many different transport libraries. 6 | 7 | ## About 8 | 9 | `feathers-client` is a small module that lets you use remote Feathers services relying on any of the following libraries: 10 | 11 | - REST API 12 | - [jQuery](https://jquery.com/) 13 | - [Superagent](http://visionmedia.github.io/superagent/) 14 | - [request](https://github.com/request/request) 15 | - Fetch: works in supported browsers, React Native or modules like [node-fetch](https://github.com/bitinn/node-fetch). 16 | - Websockets (with real-time updates) 17 | - [Socket.io](http://socket.io/) 18 | - [Primus](https://github.com/primus/primus) 19 | 20 | ## Usage 21 | 22 | `feathers-client` is used much the same way as you would use Feathers on the server making it seamless to use in other NodeJS applications or in the browser. With NodeJS or Browserify: 23 | 24 | > npm install feathers-client 25 | 26 | ```js 27 | var feathers = require('feathers-client'); 28 | ``` 29 | 30 | The `dist/feathers.js` file also provides a UMD version that works with most module loaders or standalone (providing a `feathers` global name). 31 | 32 | ```html 33 | 34 | ``` 35 | 36 | ```js 37 | var socket = io('http://example.com'); 38 | var app = feathers() 39 | .configure(feathers.socketio(socket)); 40 | 41 | var todoService = app.service('todos'); 42 | 43 | todoService.on('created', function(todo) { 44 | console.log('Todo created', todo); 45 | }); 46 | 47 | todoService.create({ 48 | text: 'A todo', 49 | complete: false 50 | }).then(function(todo) { 51 | console.log('Success!'); 52 | }); 53 | 54 | todoService.find().then(function(todos) { 55 | console.log('Got the following Todos', todos); 56 | }); 57 | ``` 58 | 59 | ## REST 60 | 61 | Connecting to a Feathers service via the REST API is possible using [jQuery](https://jquery.com/), [request](https://github.com/request/request), [Superagent](http://visionmedia.github.io/superagent/) or Fetch: 62 | 63 | __Important__: REST client services do emit `created`, `updated`, `patched` and `removed` events but only _locally for their own instance_. Real-time events from other clients can only be received by using a websocket connection. 64 | 65 | ### jQuery 66 | 67 | jQuery [$.ajax](http://api.jquery.com/jquery.ajax/) needs the API base URL and an instance of jQuery passed to `feathers.jquery`. If no jQuery instance is passed the global `jQuery` will be used. 68 | 69 | ```js 70 | var app = feathers() 71 | .configure(feathers.jquery()); 72 | ``` 73 | 74 | ### Request 75 | 76 | The [request](https://github.com/request/request) object needs to be passed explicitly to `feathers.request`. Using [request.defaults](https://github.com/request/request#convenience-methods) - which creates a new request object - is a great way to set things like default headers or authentication information: 77 | 78 | ```js 79 | var request = require('request'); 80 | var client = request.defaults({ 81 | 'auth': { 82 | 'user': 'username', 83 | 'pass': 'password', 84 | 'sendImmediately': false 85 | } 86 | }); 87 | 88 | var app = feathers('http://todos.feathersjs.com') 89 | .configure(feathers.request(client)); 90 | ``` 91 | 92 | ### Superagent 93 | 94 | [Superagent](http://visionmedia.github.io/superagent/) currently works with a default configuration: 95 | 96 | ```js 97 | var superagent = require('superagent'); 98 | var app = feathers('http://todos.feathersjs.com') 99 | .configure(feathers.superagent(superagent)); 100 | ``` 101 | 102 | ### Fetch 103 | 104 | Fetch currently works with a default configuration: 105 | 106 | ```js 107 | var app = feathers('http://todos.feathersjs.com') 108 | .configure(feathers.fetch(fetch)); 109 | ``` 110 | 111 | ## Websockets 112 | 113 | Websocket real-time connections can be established via [Socket.io](http://socket.io/) or [Primus](https://github.com/primus/primus). Websocket services emit all events that they receive allowing you to implement real-time functionality. 114 | 115 | ### Socket.io 116 | 117 | #### In the browser 118 | 119 | Provide either a connected socket or the URL of the websocket endpoint: 120 | 121 | ```js 122 | var socket = io('http://todos.feathersjs.com'); 123 | var app = feathers() 124 | .configure(feathers.socketio(socket)) 125 | // or 126 | .configure(feathers.socketio('http://todos.feathersjs.com')); 127 | ``` 128 | 129 | #### Between NodeJS applications 130 | 131 | Websocket connections are also very efficient for real-time communication between different NodeJS servers. First install `socket.io-client`: 132 | 133 | > npm install socket.io-client 134 | 135 | Then pass the connection just like in the browser: 136 | 137 | ```js 138 | var io = require('socket.io-client'); 139 | var socket = io('http://todos.feathersjs.com'); 140 | var app = feathers() 141 | .configure(feathers.socketio(socket)); 142 | ``` 143 | 144 | #### React Native 145 | 146 | Fetch is included in React Native so you don't have to install any additional dependencies 147 | 148 | Then pass in fetch: 149 | 150 | ```js 151 | var app = feathers('http://todos.feathersjs.com') 152 | .configure(feathers.fetch(fetch)); 153 | ``` 154 | 155 | ### Primus 156 | 157 | [Primus](https://github.com/primus/primus) works similar to Socket.io: 158 | 159 | ```html 160 | 161 | 162 | 166 | ``` 167 | 168 | ## Changelog 169 | 170 | __0.5.0__ 171 | 172 | - Adding React Native fetch plugin 173 | 174 | __0.4.0__ 175 | 176 | - updating dependencies 177 | 178 | __0.3.0__ 179 | 180 | - Migrating to ES6 and use with Promises ([#7](https://github.com/feathersjs/feathers-client/issues/7)) 181 | 182 | __0.2.0__ 183 | 184 | - Make client use feathers-commons 185 | 186 | __0.1.0__ 187 | 188 | - Initial release 189 | 190 | ## Author 191 | 192 | - [David Luecke](https://github.com/daffl) 193 | 194 | ## License 195 | 196 | Copyright (c) 2015 David Luecke 197 | 198 | Licensed under the [MIT license](LICENSE). 199 | -------------------------------------------------------------------------------- /dist/feathers.js: -------------------------------------------------------------------------------- 1 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.feathers = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0 && this._events[type].length > m) { 142 | this._events[type].warned = true; 143 | console.error('(node) warning: possible EventEmitter memory ' + 144 | 'leak detected. %d listeners added. ' + 145 | 'Use emitter.setMaxListeners() to increase limit.', 146 | this._events[type].length); 147 | if (typeof console.trace === 'function') { 148 | // not supported in IE 10 149 | console.trace(); 150 | } 151 | } 152 | } 153 | 154 | return this; 155 | }; 156 | 157 | EventEmitter.prototype.on = EventEmitter.prototype.addListener; 158 | 159 | EventEmitter.prototype.once = function(type, listener) { 160 | if (!isFunction(listener)) 161 | throw TypeError('listener must be a function'); 162 | 163 | var fired = false; 164 | 165 | function g() { 166 | this.removeListener(type, g); 167 | 168 | if (!fired) { 169 | fired = true; 170 | listener.apply(this, arguments); 171 | } 172 | } 173 | 174 | g.listener = listener; 175 | this.on(type, g); 176 | 177 | return this; 178 | }; 179 | 180 | // emits a 'removeListener' event iff the listener was removed 181 | EventEmitter.prototype.removeListener = function(type, listener) { 182 | var list, position, length, i; 183 | 184 | if (!isFunction(listener)) 185 | throw TypeError('listener must be a function'); 186 | 187 | if (!this._events || !this._events[type]) 188 | return this; 189 | 190 | list = this._events[type]; 191 | length = list.length; 192 | position = -1; 193 | 194 | if (list === listener || 195 | (isFunction(list.listener) && list.listener === listener)) { 196 | delete this._events[type]; 197 | if (this._events.removeListener) 198 | this.emit('removeListener', type, listener); 199 | 200 | } else if (isObject(list)) { 201 | for (i = length; i-- > 0;) { 202 | if (list[i] === listener || 203 | (list[i].listener && list[i].listener === listener)) { 204 | position = i; 205 | break; 206 | } 207 | } 208 | 209 | if (position < 0) 210 | return this; 211 | 212 | if (list.length === 1) { 213 | list.length = 0; 214 | delete this._events[type]; 215 | } else { 216 | list.splice(position, 1); 217 | } 218 | 219 | if (this._events.removeListener) 220 | this.emit('removeListener', type, listener); 221 | } 222 | 223 | return this; 224 | }; 225 | 226 | EventEmitter.prototype.removeAllListeners = function(type) { 227 | var key, listeners; 228 | 229 | if (!this._events) 230 | return this; 231 | 232 | // not listening for removeListener, no need to emit 233 | if (!this._events.removeListener) { 234 | if (arguments.length === 0) 235 | this._events = {}; 236 | else if (this._events[type]) 237 | delete this._events[type]; 238 | return this; 239 | } 240 | 241 | // emit removeListener for all listeners on all events 242 | if (arguments.length === 0) { 243 | for (key in this._events) { 244 | if (key === 'removeListener') continue; 245 | this.removeAllListeners(key); 246 | } 247 | this.removeAllListeners('removeListener'); 248 | this._events = {}; 249 | return this; 250 | } 251 | 252 | listeners = this._events[type]; 253 | 254 | if (isFunction(listeners)) { 255 | this.removeListener(type, listeners); 256 | } else { 257 | // LIFO order 258 | while (listeners.length) 259 | this.removeListener(type, listeners[listeners.length - 1]); 260 | } 261 | delete this._events[type]; 262 | 263 | return this; 264 | }; 265 | 266 | EventEmitter.prototype.listeners = function(type) { 267 | var ret; 268 | if (!this._events || !this._events[type]) 269 | ret = []; 270 | else if (isFunction(this._events[type])) 271 | ret = [this._events[type]]; 272 | else 273 | ret = this._events[type].slice(); 274 | return ret; 275 | }; 276 | 277 | EventEmitter.listenerCount = function(emitter, type) { 278 | var ret; 279 | if (!emitter._events || !emitter._events[type]) 280 | ret = 0; 281 | else if (isFunction(emitter._events[type])) 282 | ret = 1; 283 | else 284 | ret = emitter._events[type].length; 285 | return ret; 286 | }; 287 | 288 | function isFunction(arg) { 289 | return typeof arg === 'function'; 290 | } 291 | 292 | function isNumber(arg) { 293 | return typeof arg === 'number'; 294 | } 295 | 296 | function isObject(arg) { 297 | return typeof arg === 'object' && arg !== null; 298 | } 299 | 300 | function isUndefined(arg) { 301 | return arg === void 0; 302 | } 303 | 304 | },{}],2:[function(require,module,exports){ 305 | 'use strict'; 306 | 307 | Object.defineProperty(exports, "__esModule", { 308 | value: true 309 | }); 310 | exports.default = getArguments; 311 | 312 | function _typeof(obj) { return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj; } 313 | 314 | var noop = exports.noop = function noop() {}; 315 | var getCallback = function getCallback(args) { 316 | var last = args[args.length - 1]; 317 | return typeof last === 'function' ? last : noop; 318 | }; 319 | var getParams = function getParams(args, position) { 320 | return _typeof(args[position]) === 'object' ? args[position] : {}; 321 | }; 322 | 323 | var updateOrPatch = function updateOrPatch(name) { 324 | return function (args) { 325 | var id = args[0]; 326 | var data = args[1]; 327 | var callback = getCallback(args); 328 | var params = getParams(args, 2); 329 | 330 | if (typeof id === 'function') { 331 | throw new Error('First parameter for \'' + name + '\' can not be a function'); 332 | } 333 | 334 | if ((typeof data === 'undefined' ? 'undefined' : _typeof(data)) !== 'object') { 335 | throw new Error('No data provided for \'' + name + '\''); 336 | } 337 | 338 | if (args.length > 4) { 339 | throw new Error('Too many arguments for \'' + name + '\' service method'); 340 | } 341 | 342 | return [id, data, params, callback]; 343 | }; 344 | }; 345 | 346 | var getOrRemove = function getOrRemove(name) { 347 | return function (args) { 348 | var id = args[0]; 349 | var params = getParams(args, 1); 350 | var callback = getCallback(args); 351 | 352 | if (args.length > 3) { 353 | throw new Error('Too many arguments for \'' + name + '\' service method'); 354 | } 355 | 356 | if (typeof id === 'function') { 357 | throw new Error('First parameter for \'' + name + '\' can not be a function'); 358 | } 359 | 360 | return [id, params, callback]; 361 | }; 362 | }; 363 | 364 | var converters = exports.converters = { 365 | find: function find(args) { 366 | var callback = getCallback(args); 367 | var params = getParams(args, 0); 368 | 369 | if (args.length > 2) { 370 | throw new Error('Too many arguments for \'find\' service method'); 371 | } 372 | 373 | return [params, callback]; 374 | }, 375 | create: function create(args) { 376 | var data = args[0]; 377 | var params = getParams(args, 1); 378 | var callback = getCallback(args); 379 | 380 | if ((typeof data === 'undefined' ? 'undefined' : _typeof(data)) !== 'object') { 381 | throw new Error('First parameter for \'create\' must be an object'); 382 | } 383 | 384 | if (args.length > 3) { 385 | throw new Error('Too many arguments for \'create\' service method'); 386 | } 387 | 388 | return [data, params, callback]; 389 | }, 390 | 391 | update: updateOrPatch('update'), 392 | 393 | patch: updateOrPatch('patch'), 394 | 395 | get: getOrRemove('get'), 396 | 397 | remove: getOrRemove('remove') 398 | }; 399 | 400 | function getArguments(method, args) { 401 | return converters[method](args); 402 | } 403 | },{}],3:[function(require,module,exports){ 404 | // Copyright Joyent, Inc. and other Node contributors. 405 | // 406 | // Permission is hereby granted, free of charge, to any person obtaining a 407 | // copy of this software and associated documentation files (the 408 | // "Software"), to deal in the Software without restriction, including 409 | // without limitation the rights to use, copy, modify, merge, publish, 410 | // distribute, sublicense, and/or sell copies of the Software, and to permit 411 | // persons to whom the Software is furnished to do so, subject to the 412 | // following conditions: 413 | // 414 | // The above copyright notice and this permission notice shall be included 415 | // in all copies or substantial portions of the Software. 416 | // 417 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 418 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 419 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 420 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 421 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 422 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 423 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 424 | 425 | 'use strict'; 426 | 427 | // If obj.hasOwnProperty has been overridden, then calling 428 | // obj.hasOwnProperty(prop) will break. 429 | // See: https://github.com/joyent/node/issues/1707 430 | function hasOwnProperty(obj, prop) { 431 | return Object.prototype.hasOwnProperty.call(obj, prop); 432 | } 433 | 434 | module.exports = function(qs, sep, eq, options) { 435 | sep = sep || '&'; 436 | eq = eq || '='; 437 | var obj = {}; 438 | 439 | if (typeof qs !== 'string' || qs.length === 0) { 440 | return obj; 441 | } 442 | 443 | var regexp = /\+/g; 444 | qs = qs.split(sep); 445 | 446 | var maxKeys = 1000; 447 | if (options && typeof options.maxKeys === 'number') { 448 | maxKeys = options.maxKeys; 449 | } 450 | 451 | var len = qs.length; 452 | // maxKeys <= 0 means that we should not limit keys count 453 | if (maxKeys > 0 && len > maxKeys) { 454 | len = maxKeys; 455 | } 456 | 457 | for (var i = 0; i < len; ++i) { 458 | var x = qs[i].replace(regexp, '%20'), 459 | idx = x.indexOf(eq), 460 | kstr, vstr, k, v; 461 | 462 | if (idx >= 0) { 463 | kstr = x.substr(0, idx); 464 | vstr = x.substr(idx + 1); 465 | } else { 466 | kstr = x; 467 | vstr = ''; 468 | } 469 | 470 | k = decodeURIComponent(kstr); 471 | v = decodeURIComponent(vstr); 472 | 473 | if (!hasOwnProperty(obj, k)) { 474 | obj[k] = v; 475 | } else if (isArray(obj[k])) { 476 | obj[k].push(v); 477 | } else { 478 | obj[k] = [obj[k], v]; 479 | } 480 | } 481 | 482 | return obj; 483 | }; 484 | 485 | var isArray = Array.isArray || function (xs) { 486 | return Object.prototype.toString.call(xs) === '[object Array]'; 487 | }; 488 | 489 | },{}],4:[function(require,module,exports){ 490 | // Copyright Joyent, Inc. and other Node contributors. 491 | // 492 | // Permission is hereby granted, free of charge, to any person obtaining a 493 | // copy of this software and associated documentation files (the 494 | // "Software"), to deal in the Software without restriction, including 495 | // without limitation the rights to use, copy, modify, merge, publish, 496 | // distribute, sublicense, and/or sell copies of the Software, and to permit 497 | // persons to whom the Software is furnished to do so, subject to the 498 | // following conditions: 499 | // 500 | // The above copyright notice and this permission notice shall be included 501 | // in all copies or substantial portions of the Software. 502 | // 503 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 504 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 505 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 506 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 507 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 508 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 509 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 510 | 511 | 'use strict'; 512 | 513 | var stringifyPrimitive = function(v) { 514 | switch (typeof v) { 515 | case 'string': 516 | return v; 517 | 518 | case 'boolean': 519 | return v ? 'true' : 'false'; 520 | 521 | case 'number': 522 | return isFinite(v) ? v : ''; 523 | 524 | default: 525 | return ''; 526 | } 527 | }; 528 | 529 | module.exports = function(obj, sep, eq, name) { 530 | sep = sep || '&'; 531 | eq = eq || '='; 532 | if (obj === null) { 533 | obj = undefined; 534 | } 535 | 536 | if (typeof obj === 'object') { 537 | return map(objectKeys(obj), function(k) { 538 | var ks = encodeURIComponent(stringifyPrimitive(k)) + eq; 539 | if (isArray(obj[k])) { 540 | return map(obj[k], function(v) { 541 | return ks + encodeURIComponent(stringifyPrimitive(v)); 542 | }).join(sep); 543 | } else { 544 | return ks + encodeURIComponent(stringifyPrimitive(obj[k])); 545 | } 546 | }).join(sep); 547 | 548 | } 549 | 550 | if (!name) return ''; 551 | return encodeURIComponent(stringifyPrimitive(name)) + eq + 552 | encodeURIComponent(stringifyPrimitive(obj)); 553 | }; 554 | 555 | var isArray = Array.isArray || function (xs) { 556 | return Object.prototype.toString.call(xs) === '[object Array]'; 557 | }; 558 | 559 | function map (xs, f) { 560 | if (xs.map) return xs.map(f); 561 | var res = []; 562 | for (var i = 0; i < xs.length; i++) { 563 | res.push(f(xs[i], i)); 564 | } 565 | return res; 566 | } 567 | 568 | var objectKeys = Object.keys || function (obj) { 569 | var res = []; 570 | for (var key in obj) { 571 | if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key); 572 | } 573 | return res; 574 | }; 575 | 576 | },{}],5:[function(require,module,exports){ 577 | 'use strict'; 578 | 579 | exports.decode = exports.parse = require('./decode'); 580 | exports.encode = exports.stringify = require('./encode'); 581 | 582 | },{"./decode":3,"./encode":4}],6:[function(require,module,exports){ 583 | 'use strict'; 584 | 585 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 586 | 587 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 588 | 589 | Object.defineProperty(exports, "__esModule", { 590 | value: true 591 | }); 592 | exports.Client = undefined; 593 | 594 | var _utils = require('./utils'); 595 | 596 | var _rest = require('./rest'); 597 | 598 | var _rest2 = _interopRequireDefault(_rest); 599 | 600 | var _sockets = require('./sockets'); 601 | 602 | var _sockets2 = _interopRequireDefault(_sockets); 603 | 604 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 605 | 606 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 607 | 608 | var Client = exports.Client = (function () { 609 | function Client(base) { 610 | _classCallCheck(this, Client); 611 | 612 | this.base = base; 613 | this.services = {}; 614 | } 615 | 616 | _createClass(Client, [{ 617 | key: 'configure', 618 | value: function configure(cb) { 619 | cb.call(this); 620 | return this; 621 | } 622 | }, { 623 | key: 'service', 624 | value: function service(name) { 625 | name = (0, _utils.stripSlashes)(name); 626 | if (!this.services[name]) { 627 | this.services[name] = new this.Service(name, this); 628 | } 629 | return this.services[name]; 630 | } 631 | }]); 632 | 633 | return Client; 634 | })(); 635 | 636 | function client() { 637 | var base = arguments.length <= 0 || arguments[0] === undefined ? '/' : arguments[0]; 638 | 639 | return new Client(base); 640 | } 641 | 642 | _extends(client, _rest2.default, _sockets2.default); 643 | 644 | exports.default = module.exports = client; 645 | 646 | },{"./rest":9,"./sockets":14,"./utils":15}],7:[function(require,module,exports){ 647 | 'use strict'; 648 | 649 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 650 | 651 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 652 | 653 | Object.defineProperty(exports, "__esModule", { 654 | value: true 655 | }); 656 | exports.Base = undefined; 657 | 658 | var _querystring = require('querystring'); 659 | 660 | var _querystring2 = _interopRequireDefault(_querystring); 661 | 662 | var _utils = require('../utils'); 663 | 664 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 665 | 666 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 667 | 668 | function callbackify(promise, callback) { 669 | if (typeof callback === 'function') { 670 | promise.then(function (data) { 671 | return callback(null, data); 672 | }, callback); 673 | } 674 | return promise; 675 | } 676 | 677 | var Base = exports.Base = (function () { 678 | function Base(name, options) { 679 | _classCallCheck(this, Base); 680 | 681 | this.name = (0, _utils.stripSlashes)(name); 682 | this.options = _extends({}, options); 683 | this.connection = options.connection; 684 | this.base = options.base + '/' + this.name; 685 | delete this.options.base; 686 | 687 | (0, _utils.normalize)(this); 688 | (0, _utils.makeEmitting)(this); 689 | } 690 | 691 | _createClass(Base, [{ 692 | key: 'makeUrl', 693 | value: function makeUrl(params, id) { 694 | var url = this.base; 695 | 696 | if (typeof id !== 'undefined') { 697 | url += '/' + id; 698 | } 699 | 700 | if (Object.keys(params).length !== 0) { 701 | var queryString = _querystring2.default.stringify(params); 702 | 703 | url += '?' + queryString; 704 | } 705 | 706 | return url; 707 | } 708 | }, { 709 | key: 'find', 710 | value: function find(params, callback) { 711 | return callbackify(this.request({ 712 | url: this.makeUrl(params), 713 | method: 'GET' 714 | }), callback); 715 | } 716 | }, { 717 | key: 'get', 718 | value: function get(id, params, callback) { 719 | return callbackify(this.request({ 720 | url: this.makeUrl(params, id), 721 | method: 'GET' 722 | }), callback); 723 | } 724 | }, { 725 | key: 'create', 726 | value: function create(body, params, callback) { 727 | return callbackify(this.request({ 728 | url: this.makeUrl(params), 729 | body: body, 730 | method: 'POST' 731 | }), callback); 732 | } 733 | }, { 734 | key: 'update', 735 | value: function update(id, body, params, callback) { 736 | return callbackify(this.request({ 737 | url: this.makeUrl(params, id), 738 | body: body, 739 | method: 'PUT' 740 | }), callback); 741 | } 742 | }, { 743 | key: 'patch', 744 | value: function patch(id, body, params, callback) { 745 | return callbackify(this.request({ 746 | url: this.makeUrl(params, id), 747 | body: body, 748 | method: 'PATCH' 749 | }), callback); 750 | } 751 | }, { 752 | key: 'remove', 753 | value: function remove(id, params, callback) { 754 | return callbackify(this.request({ 755 | url: this.makeUrl(params, id), 756 | method: 'DELETE' 757 | }), callback); 758 | } 759 | }]); 760 | 761 | return Base; 762 | })(); 763 | 764 | },{"../utils":15,"querystring":5}],8:[function(require,module,exports){ 765 | 'use strict'; 766 | 767 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 768 | 769 | Object.defineProperty(exports, "__esModule", { 770 | value: true 771 | }); 772 | exports.Service = undefined; 773 | 774 | exports.default = function (fetch) { 775 | if (!fetch) { 776 | throw new Error('fetch needs to be provided'); 777 | } 778 | 779 | return function () { 780 | this.Service = Service; 781 | this.connection = fetch; 782 | }; 783 | }; 784 | 785 | var _base = require('./base'); 786 | 787 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 788 | 789 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 790 | 791 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 792 | 793 | var Service = exports.Service = (function (_Base) { 794 | _inherits(Service, _Base); 795 | 796 | function Service() { 797 | _classCallCheck(this, Service); 798 | 799 | return _possibleConstructorReturn(this, Object.getPrototypeOf(Service).apply(this, arguments)); 800 | } 801 | 802 | _createClass(Service, [{ 803 | key: 'request', 804 | value: function request(options) { 805 | var _this2 = this; 806 | 807 | var fetchOptions = { 808 | method: options.method, 809 | headers: { 810 | 'Accept': 'application/json' 811 | } 812 | }; 813 | 814 | return new Promise(function (resolve, reject) { 815 | if (options.body) { 816 | fetchOptions.body = JSON.stringify(options.body); 817 | fetchOptions.headers['Content-Type'] = 'application/json'; 818 | } 819 | _this2.connection(options.url, fetchOptions).then(function (response) { 820 | return response.json(); 821 | }).then(function (result) { 822 | resolve(result); 823 | }).catch(function (e) { 824 | reject(e); 825 | }); 826 | }); 827 | } 828 | }]); 829 | 830 | return Service; 831 | })(_base.Base); 832 | 833 | },{"./base":7}],9:[function(require,module,exports){ 834 | 'use strict'; 835 | 836 | Object.defineProperty(exports, "__esModule", { 837 | value: true 838 | }); 839 | 840 | var _jquery = require('./jquery'); 841 | 842 | var _jquery2 = _interopRequireDefault(_jquery); 843 | 844 | var _request = require('./request'); 845 | 846 | var _request2 = _interopRequireDefault(_request); 847 | 848 | var _superagent = require('./superagent'); 849 | 850 | var _superagent2 = _interopRequireDefault(_superagent); 851 | 852 | var _fetch = require('./fetch'); 853 | 854 | var _fetch2 = _interopRequireDefault(_fetch); 855 | 856 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 857 | 858 | exports.default = { jquery: _jquery2.default, request: _request2.default, superagent: _superagent2.default, fetch: _fetch2.default }; 859 | 860 | },{"./fetch":8,"./jquery":10,"./request":11,"./superagent":12}],10:[function(require,module,exports){ 861 | 'use strict'; 862 | 863 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 864 | 865 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 866 | 867 | Object.defineProperty(exports, "__esModule", { 868 | value: true 869 | }); 870 | exports.Service = undefined; 871 | 872 | exports.default = function (jQuery) { 873 | if (!jQuery && typeof window !== 'undefined') { 874 | jQuery = window.jQuery; 875 | } 876 | 877 | if (typeof jQuery !== 'function') { 878 | throw new Error('jQuery instance needs to be provided'); 879 | } 880 | 881 | return function () { 882 | this.Service = Service; 883 | this.connection = jQuery; 884 | }; 885 | }; 886 | 887 | var _base = require('./base'); 888 | 889 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 890 | 891 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 892 | 893 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 894 | 895 | var Service = exports.Service = (function (_Base) { 896 | _inherits(Service, _Base); 897 | 898 | function Service() { 899 | _classCallCheck(this, Service); 900 | 901 | return _possibleConstructorReturn(this, Object.getPrototypeOf(Service).apply(this, arguments)); 902 | } 903 | 904 | _createClass(Service, [{ 905 | key: 'request', 906 | value: function request(options) { 907 | var _this2 = this; 908 | 909 | var opts = _extends({ 910 | dataType: options.type || 'json' 911 | }, options); 912 | 913 | if (options.body) { 914 | opts.data = JSON.stringify(options.body); 915 | opts.contentType = 'application/json'; 916 | } 917 | 918 | delete opts.type; 919 | delete opts.body; 920 | 921 | return new Promise(function (resolve, reject) { 922 | return _this2.connection.ajax(opts).then(resolve, function (xhr) { 923 | var error = new Error(xhr.responseText); 924 | error.xhr = xhr; 925 | reject(error); 926 | }); 927 | }); 928 | } 929 | }]); 930 | 931 | return Service; 932 | })(_base.Base); 933 | 934 | },{"./base":7}],11:[function(require,module,exports){ 935 | 'use strict'; 936 | 937 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 938 | 939 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 940 | 941 | Object.defineProperty(exports, "__esModule", { 942 | value: true 943 | }); 944 | exports.Service = undefined; 945 | 946 | exports.default = function (request) { 947 | if (!request) { 948 | throw new Error('request instance needs to be provided'); 949 | } 950 | 951 | return function () { 952 | this.Service = Service; 953 | this.connection = request; 954 | }; 955 | }; 956 | 957 | var _base = require('./base'); 958 | 959 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 960 | 961 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 962 | 963 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 964 | 965 | var Service = exports.Service = (function (_Base) { 966 | _inherits(Service, _Base); 967 | 968 | function Service() { 969 | _classCallCheck(this, Service); 970 | 971 | return _possibleConstructorReturn(this, Object.getPrototypeOf(Service).apply(this, arguments)); 972 | } 973 | 974 | _createClass(Service, [{ 975 | key: 'request', 976 | value: function request(options) { 977 | var _this2 = this; 978 | 979 | return new Promise(function (resolve, reject) { 980 | _this2.connection(_extends({ 981 | json: true 982 | }, options), function (error, res, data) { 983 | if (!error && res.statusCode >= 400) { 984 | return reject(new Error(data)); 985 | } 986 | 987 | resolve(data); 988 | }); 989 | }); 990 | } 991 | }]); 992 | 993 | return Service; 994 | })(_base.Base); 995 | 996 | },{"./base":7}],12:[function(require,module,exports){ 997 | 'use strict'; 998 | 999 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 1000 | 1001 | Object.defineProperty(exports, "__esModule", { 1002 | value: true 1003 | }); 1004 | exports.Service = undefined; 1005 | 1006 | exports.default = function (superagent) { 1007 | if (!superagent) { 1008 | throw new Error('Superagent needs to be provided'); 1009 | } 1010 | 1011 | return function () { 1012 | this.Service = Service; 1013 | this.connection = superagent; 1014 | }; 1015 | }; 1016 | 1017 | var _base = require('./base'); 1018 | 1019 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 1020 | 1021 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 1022 | 1023 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 1024 | 1025 | var Service = exports.Service = (function (_Base) { 1026 | _inherits(Service, _Base); 1027 | 1028 | function Service() { 1029 | _classCallCheck(this, Service); 1030 | 1031 | return _possibleConstructorReturn(this, Object.getPrototypeOf(Service).apply(this, arguments)); 1032 | } 1033 | 1034 | _createClass(Service, [{ 1035 | key: 'request', 1036 | value: function request(options) { 1037 | var superagent = this.connection(options.method, options.url).type(options.type || 'json'); 1038 | 1039 | return new Promise(function (resolve, reject) { 1040 | if (options.body) { 1041 | superagent.send(options.body); 1042 | } 1043 | 1044 | superagent.end(function (error, res) { 1045 | if (error) { 1046 | return reject(error); 1047 | } 1048 | 1049 | resolve(res && res.body); 1050 | }); 1051 | }); 1052 | } 1053 | }]); 1054 | 1055 | return Service; 1056 | })(_base.Base); 1057 | 1058 | },{"./base":7}],13:[function(require,module,exports){ 1059 | 'use strict'; 1060 | 1061 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 1062 | 1063 | Object.defineProperty(exports, "__esModule", { 1064 | value: true 1065 | }); 1066 | exports.Service = undefined; 1067 | 1068 | var _utils = require('../utils'); 1069 | 1070 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 1071 | 1072 | var Service = exports.Service = (function () { 1073 | function Service(name, app) { 1074 | _classCallCheck(this, Service); 1075 | 1076 | this.events = _utils.events; 1077 | this.path = (0, _utils.stripSlashes)(name); 1078 | this.connection = app.connection; 1079 | this.method = this.connection && this.connection.io ? 'emit' : 'send'; 1080 | 1081 | (0, _utils.normalize)(this); 1082 | } 1083 | 1084 | _createClass(Service, [{ 1085 | key: 'emit', 1086 | value: function emit() { 1087 | var _connection; 1088 | 1089 | (_connection = this.connection)[this.method].apply(_connection, arguments); 1090 | } 1091 | }]); 1092 | 1093 | return Service; 1094 | })(); 1095 | 1096 | var emitterMethods = ['on', 'once', 'off']; 1097 | 1098 | emitterMethods.forEach(function (method) { 1099 | Service.prototype[method] = function (name, callback) { 1100 | this.connection[method](this.path + ' ' + name, callback); 1101 | }; 1102 | }); 1103 | 1104 | _utils.methods.forEach(function (method) { 1105 | Service.prototype[method] = function () { 1106 | var _this = this; 1107 | 1108 | for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { 1109 | args[_key] = arguments[_key]; 1110 | } 1111 | 1112 | var callback = null; 1113 | if (typeof args[args.length - 1] === 'function') { 1114 | callback = args.pop(); 1115 | } 1116 | 1117 | return new Promise(function (resolve, reject) { 1118 | var _connection2; 1119 | 1120 | args.unshift(_this.path + '::' + method); 1121 | args.push(function (error, data) { 1122 | if (callback) { 1123 | callback(error, data); 1124 | } 1125 | 1126 | return error ? reject(error) : resolve(data); 1127 | }); 1128 | 1129 | (_connection2 = _this.connection)[_this.method].apply(_connection2, args); 1130 | }); 1131 | }; 1132 | }); 1133 | 1134 | },{"../utils":15}],14:[function(require,module,exports){ 1135 | 'use strict'; 1136 | 1137 | Object.defineProperty(exports, "__esModule", { 1138 | value: true 1139 | }); 1140 | 1141 | var _base = require('./base'); 1142 | 1143 | function base(socket) { 1144 | if (!socket) { 1145 | throw new Error('No socket provided'); 1146 | } 1147 | 1148 | return function () { 1149 | this.Service = _base.Service; 1150 | this.connection = socket; 1151 | }; 1152 | } 1153 | 1154 | function socketio(socket) { 1155 | if (typeof window !== 'undefined' && window.io && typeof socket === 'string') { 1156 | socket = window.io(socket); 1157 | } 1158 | 1159 | return base(socket); 1160 | } 1161 | 1162 | exports.default = { 1163 | socketio: socketio, 1164 | primus: base 1165 | }; 1166 | 1167 | },{"./base":13}],15:[function(require,module,exports){ 1168 | 'use strict'; 1169 | 1170 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 1171 | 1172 | Object.defineProperty(exports, "__esModule", { 1173 | value: true 1174 | }); 1175 | exports.events = exports.eventMappings = exports.methods = undefined; 1176 | exports.stripSlashes = stripSlashes; 1177 | exports.makeEmitting = makeEmitting; 1178 | exports.normalize = normalize; 1179 | 1180 | var _events = require('events'); 1181 | 1182 | var _arguments = require('feathers-commons/lib/arguments'); 1183 | 1184 | var _arguments2 = _interopRequireDefault(_arguments); 1185 | 1186 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1187 | 1188 | function stripSlashes(name) { 1189 | return name.replace(/^\/|\/$/g, ''); 1190 | } 1191 | 1192 | var methods = exports.methods = ['find', 'get', 'create', 'update', 'patch', 'remove']; 1193 | 1194 | var eventMappings = exports.eventMappings = { 1195 | create: 'created', 1196 | update: 'updated', 1197 | patch: 'patched', 1198 | remove: 'removed' 1199 | }; 1200 | 1201 | var events = exports.events = Object.keys(eventMappings).map(function (method) { 1202 | return eventMappings[method]; 1203 | }); 1204 | 1205 | function makeEmitting(target) { 1206 | _extends(target, _events.EventEmitter.prototype); 1207 | Object.keys(eventMappings).forEach(function (method) { 1208 | var old = target[method]; 1209 | var eventName = eventMappings[method]; 1210 | 1211 | if (typeof old === 'function') { 1212 | target[method] = function () { 1213 | var _this = this; 1214 | 1215 | for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { 1216 | args[_key] = arguments[_key]; 1217 | } 1218 | 1219 | var result = old.apply(this, args); 1220 | return result.then(function (data) { 1221 | _this.emit(eventName, data); 1222 | return data; 1223 | }); 1224 | }; 1225 | } 1226 | }); 1227 | } 1228 | 1229 | function normalize(target) { 1230 | methods.forEach(function (method) { 1231 | var old = target[method]; 1232 | if (typeof old === 'function') { 1233 | target[method] = function () { 1234 | for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { 1235 | args[_key2] = arguments[_key2]; 1236 | } 1237 | 1238 | return old.apply(this, (0, _arguments2.default)(method, args)); 1239 | }; 1240 | } 1241 | }); 1242 | } 1243 | 1244 | },{"events":1,"feathers-commons/lib/arguments":2}]},{},[6])(6) 1245 | }); --------------------------------------------------------------------------------