diff --git a/compiled/index.js b/compiled/index.js new file mode 100644 index 0000000..d4f094b --- /dev/null +++ b/compiled/index.js @@ -0,0 +1,284 @@ +// Generated by CoffeeScript 1.4.0 +(function() { + var ss, path, RequestIO, RoomIO, async, connect, express, http, https, initRoutes, io, key, listen, middleware, session, sessionConfig, value, _; + + connect = require('express/node_modules/connect'); + + express = require('express'); + + io = require('socket.io'); + + http = require('http'); + + var Grid = require('gridfs-stream'); + + https = require('https'); + + async = require('async'); + + middleware = require('./middleware'); + + _ = require('underscore'); + + RequestIO = require('./request').RequestIO; + + RoomIO = require('./room').RoomIO; + + ss = require('socket.io-stream'); + + path = require('path'); + + express.io = io; + + express.io.routeForward = middleware.routeForward; + + session = express.session; + + delete express.session; + + sessionConfig = new Object; + console.log("Starting Express.io app!"); + express.session = function(options) { + var _ref, _ref1, _ref2; + if (options == null) { + options = new Object; + } + if ((_ref = options.key) == null) { + options.key = 'connect.sid'; + } + if ((_ref1 = options.store) == null) { + options.store = new session.MemoryStore; + } + if ((_ref2 = options.cookie) == null) { + options.cookie = new Object; + } + sessionConfig = options; + return session(options); + }; + + for (key in session) { + value = session[key]; + express.session[key] = value; + } + + express.application.http = function() { + this.server = http.createServer(this); + return this; + }; + + express.application.https = function(options) { + this.server = https.createServer(options, this); + return this; + }; + + express.application.io = function(options) { + var defaultOptions, + _this = this; + if (options == null) { + options = new Object; + } + defaultOptions = { + log: false + }; + _.extend(options, defaultOptions); + this.io = io.listen(this.server, options); + this.io.router = new Object; + this.io.middleware = []; + this.io.route = function(route, next, options) { + var split, _results; + if ((options != null ? options.trigger : void 0) === true) { + if (route.indexOf(':' === -1)) { + this.router[route](next); + } else { + split = route.split(':'); + this.router[split[0]][split[1]](next); + } + } + if (_.isFunction(next)) { + return this.router[route] = next; + } else { + _results = []; + for (key in next) { + value = next[key]; + _results.push(this.router["" + route + ":" + key] = value); + } + return _results; + } + }; + this.io.configure(function() { + return _this.io.set('authorization', function(data, next) { + var cookieParser; + if (sessionConfig.store == null) { + return async.forEachSeries(_this.io.middleware, function(callback, next) { + return callback(data, next); + }, function(error) { + if (error != null) { + return next(error); + } + return next(null, true); + }); + } + cookieParser = express.cookieParser(); + return cookieParser(data, null, function(error) { + var rawCookie, request, sessionId; + if (error != null) { + return next(error); + } + rawCookie = data.cookies[sessionConfig.key]; + if (rawCookie == null) { + request = { + headers: { + cookie: data.query.cookie + } + }; + return cookieParser(request, null, function(error) { + var sessionId; + data.cookies = request.cookies; + rawCookie = data.cookies[sessionConfig.key]; + if (rawCookie == null) { + return next("No cookie present", false); + } + sessionId = connect.utils.parseSignedCookie(rawCookie, sessionConfig.secret); + data.sessionID = sessionId; + return sessionConfig.store.get(sessionId, function(error, session) { + if (error != null) { + return next(error); + } + data.session = new connect.session.Session(data, session); + return next(null, true); + }); + }); + } + sessionId = connect.utils.parseSignedCookie(rawCookie, sessionConfig.secret); + data.sessionID = sessionId; + return sessionConfig.store.get(sessionId, function(error, session) { + if (error != null) { + return next(error); + } + data.session = new connect.session.Session(data, session); + return next(null, true); + }); + }); + }); + }); + this.io.use = function(callback) { + return _this.io.middleware.push(callback); + }; + this.io.sockets.on('connection', function(socket) { + return initRoutes(socket, _this.io); + }); + this.io.broadcast = function() { + var args; + args = Array.prototype.slice.call(arguments, 0); + return _this.io.sockets.emit.apply(_this.io.sockets, args); + }; + this.io.room = function(room) { + return new RoomIO(room, _this.io.sockets); + }; + this.stack.push({ + route: '', + handle: function(request, response, next) { + request.io = { + route: function(route) { + var ioRequest; + ioRequest = new Object; + for (key in request) { + value = request[key]; + ioRequest[key] = value; + } + ioRequest.io = { + broadcast: _this.io.broadcast, + respond: function() { + var args; + args = Array.prototype.slice.call(arguments, 0); + return response.json.apply(response, args); + }, + route: function(route) { + return _this.io.route(route, ioRequest, { + trigger: true + }); + }, + data: request.body + }; + return _this.io.route(route, ioRequest, { + trigger: true + }); + }, + broadcast: _this.io.broadcast + }; + return next(); + } + }); + return this; + }; + + listen = express.application.listen; + + express.application.listen = function() { + var args; + args = Array.prototype.slice.call(arguments, 0); + if (this.server != null) { + return this.server.listen.apply(this.server, args); + } else { + return listen.apply(this, args); + } + }; + + initRoutes = function(socket, io) { + var setRoute, _ref, _results; + + console.log("Initializing express.io"); + + var delivery = ss(socket); + setRoute = function(key, callback) { + /* + if (key.indexOf('stream/') !== -1) { + key = key.replace('stream/', ''); + return ss(socket).on(key.replace('stream/', ''), function(stream, data) { + return callback(stream, data, socket); + }); + } + */ + return socket.on(key, function(data, respond) { + var request, _base, _ref; + if (typeof data === 'function') { + respond = data; + data = void 0; + } + request = { + data: data, + session: socket.handshake.session, + sessionID: socket.handshake.sessionID, + sessionStore: sessionConfig.store, + socket: socket, + headers: socket.handshake.headers, + cookies: socket.handshake.cookies, + handshake: socket.handshake + }; + session = socket.handshake.session; + if (session != null) { + request.session = new connect.session.Session(request, session); + } + socket.handshake.session = request.session; + request.io = new RequestIO(socket, request, io); + request.io.respond = respond; + if ((_ref = (_base = request.io).respond) == null) { + _base.respond = function() {}; + } + return callback(request, delivery); + }); + + }; + + _ref = io.router; + _results = []; + for (key in _ref) { + value = _ref[key]; + _results.push(setRoute(key, value)); + } + return _results; + }; + + module.exports = express; + +}).call(this); diff --git a/compiled/middleware.js b/compiled/middleware.js new file mode 100644 index 0000000..2cdbdd1 --- /dev/null +++ b/compiled/middleware.js @@ -0,0 +1,101 @@ +// Generated by CoffeeScript 1.4.0 +(function() { + var configs, regex, _; + + _ = require('underscore'); + + regex = { + single: /\/([^\/]+)\/?/, + doubleOptional: /\/([^\/]+)(?:\/([^\/]+)\/?)?/, + double: /\/([^\/]+)\/([^\/]+)\/?/ + }; + + configs = { + backbone: { + create: { + method: 'post', + regex: regex.single + }, + read: { + method: 'get', + regex: regex.doubleOptional, + variables: ['id'] + }, + update: { + method: 'put', + regex: regex.double, + variables: ['id'] + }, + "delete": { + method: 'delete', + regex: regex.double, + variables: ['id'] + } + }, + angular: { + list: { + method: 'get', + regex: regex.single + }, + create: { + method: 'post', + regex: regex.single + }, + read: { + method: 'get', + regex: regex.double, + variables: ['id'] + }, + update: { + method: 'put', + regex: regex.double, + variables: ['id'] + }, + "delete": { + method: 'delete', + regex: regex.double, + variables: ['id'] + } + } + }; + + configs.backbonjs = configs.backbone; + + configs.angularjs = configs.angular; + + exports.routeForward = function(options) { + if (!_.isObject(options.config)) { + options.type = options.config; + options.config = configs[options.type]; + if (options.config == null) { + throw new Error("RouteForwardError: No config for " + options.type); + } + } + return function(request, response, next) { + var index, match, meta, route, variable, _ref, _ref1, _ref2, _ref3; + _ref = options.config; + for (route in _ref) { + meta = _ref[route]; + if (meta.method === request.method.toLowerCase()) { + match = meta.regex.exec(request.url); + if (match != null) { + if ((_ref1 = meta.variables) == null) { + meta.variables = []; + } + if ((_ref2 = request.params) == null) { + request.params = {}; + } + _ref3 = meta.variables; + for (index in _ref3) { + variable = _ref3[index]; + request.params[variable] = match[2 + parseInt(index)]; + } + return request.io.route("" + match[1] + ":" + route); + } + } + } + return next(); + }; + }; + +}).call(this); diff --git a/compiled/request.js b/compiled/request.js new file mode 100644 index 0000000..95800fb --- /dev/null +++ b/compiled/request.js @@ -0,0 +1,55 @@ +// Generated by CoffeeScript 1.4.0 +(function() { + var RoomIO; + + RoomIO = require('./room').RoomIO; + + exports.RequestIO = (function() { + + function RequestIO(socket, request, io) { + this.socket = socket; + this.request = request; + this.manager = io; + } + + RequestIO.prototype.broadcast = function(event, message) { + return this.socket.broadcast.emit(event, message); + }; + + RequestIO.prototype.emit = function(event, message) { + return this.socket.emit(event, message); + }; + + RequestIO.prototype.room = function(room) { + return new RoomIO(room, this.socket); + }; + + RequestIO.prototype.join = function(room) { + return this.socket.join(room); + }; + + RequestIO.prototype.route = function(route) { + return this.manager.route(route, this.request, { + trigger: true + }); + }; + + RequestIO.prototype.leave = function(room) { + return this.socket.leave(room); + }; + + RequestIO.prototype.on = function() { + var args; + args = Array.prototype.slice.call(arguments, 0); + return this.sockets.on.apply(this.socket, args); + }; + + RequestIO.prototype.disconnect = function(callback) { + return this.socket.disconnect(callback); + }; + + return RequestIO; + + })(); + +}).call(this); diff --git a/compiled/room.js b/compiled/room.js new file mode 100644 index 0000000..f0b6393 --- /dev/null +++ b/compiled/room.js @@ -0,0 +1,23 @@ +// Generated by CoffeeScript 1.4.0 +(function() { + + exports.RoomIO = (function() { + + function RoomIO(name, socket) { + this.name = name; + this.socket = socket; + } + + RoomIO.prototype.broadcast = function(event, message) { + if (this.socket.broadcast != null) { + return this.socket.broadcast.to(this.name).emit(event, message); + } else { + return this.socket["in"](this.name).emit(event, message); + } + }; + + return RoomIO; + + })(); + +}).call(this); diff --git a/lib/README.md b/lib/README.md deleted file mode 100644 index 48b81c8..0000000 --- a/lib/README.md +++ /dev/null @@ -1,125 +0,0 @@ - -# API Reference - -This gives details on the new top level objects for __express.io__. - -## ExpressIO - -```js -express = require('express.io') -``` - -### Properties - -* `express()` - Creates a new app object. -* `express.io` - The socket.io object. - -## ExpressApp - -```js -app = require('express.io')() -``` - -### Properties - -* `app.http()` - starts an http server, returns `app` -* `app.https(options)` - starts an https server, returns `app` -* `app.io()` - starts an io server, returns `app` - -For a complete list of properties, please check the [docs](http://expressjs.com/api.html#app.set). - -## AppIO - -The io object for the entire app. Used for routing and broadcasting to clients. - -```js -app.io.broadcast('hey', {this: 'goes to everyone!'}) -app.io.room('hipster').broadcast('meh', {this: 'goes to all hipsters'}) -app.io.route('special', function(req) { - // do something with req -}) -``` - -You can also use the `AppIO` object to configure your io server. For available options, check [here](https://github.com/LearnBoost/Socket.IO/wiki/Configuring-Socket.IO). - -```js -app.io.configure(function() { - app.io.enable('browser client minification'); // send minified client - app.io.enable('browser client gzip'); // gzip the file - app.io.set('log level', 1); // reduce logging -}) -``` - -__Note__: You must call `app.io()` before using. - -### Properties - -* `app.io.brodcast(event, data)` - Broadcast the `event` and `data` to all clients. -* `app.io.room(room).broadcast(event, data)` - Broadcast the `event` and `data` only to clients in the `room`. -* `app.io.route(event, callback)` - Takes a `route` name and a `callback`. The callback passes `req`, which is a `SocketRequest` object. -* `app.io.set(property, value)` - Set a global io server property. -* `app.io.enable(property)` - Enable an io server feature. -* `app.io.configure(environment)` - Similar to the `app.configure` method for express. - -## SocketRequest - -This object is passed to the io routes. - -```js -app.io.route('hello', function(req) { - // do something with req -}) -``` - -### Properties - -* `req.data` - The `data` sent from the client request. -* `req.io` - The `RequestIO` object for the request. -* `req.headers` - `headers` from the initial web socket request. -* `req.session` - If you have sessions, then this is the express `session` object. -* `req.handshake` - This is the io `handshake` data. -* `req.socket` - The actual socket.io `socket`. Please use `req.io` instead. - -## RequestIO - -This object comes with the `SocketRequest`, and it gives you access to the request io. - -```js -app.io.route('example', function(req) { - req.io.emit('event', {this: 'is sent as an event to the client'}) - req.io.broadcast('shout-out', {this: 'goes to every client, except this one'}) - req.io.respond({sends: 'this data back to the client as an acknowledgment'}) - req.io.join('hipster') // joins the hipster room - req.io.leave('hipster') // leaves the hipster room - req.io.room('hipster').broadcast('hey', {this: 'goes to every hipster'}) - req.io.route('some-other-route') - -}) -``` - -### Properties - -* `req.io.emit(event, data)` - Send an `event` with `data` to this client. -* `req.io.respond(data)` - Sends the acknowledgment `data` back to the client. -* `req.io.broadcast(event, data)` - Broadcast to all clients except this one. -* `req.io.room(room).broadcast(event,data)` - Broadcast to the specified `room`, the `event` and `data`. Every client in the `room` except the one making the request, receives this `event`. -* `req.io.join(room)` - Make the client join the specified `room`. -* `req.io.leave(room)` - Make the client leave the specified `room`. -* `req.io.route(route)` - Forwards the `req` to the given `route`. - -### Reserved Events - -These events are reserved and should not be used with `app.io.route` or `req.io.on` unless you know what you are doing. - -* `connect` -* `connecting` -* `disconnect` -* `connect_failed` -* `error` -* `message` -* `reconnect_failed` -* `reconnect` -* `reconnecting` - -View the docs for [details on these events.](https://github.com/LearnBoost/socket.io/wiki/Exposed-events) - diff --git a/lib/index.coffee b/lib/index.coffee deleted file mode 100644 index eecfe2c..0000000 --- a/lib/index.coffee +++ /dev/null @@ -1,157 +0,0 @@ -connect = require 'express/node_modules/connect' -express = require 'express' -io = require 'socket.io' -http = require 'http' -https = require 'https' -async = require 'async' -middleware = require './middleware' -_ = require 'underscore' - -RequestIO = require('./request').RequestIO -RoomIO = require('./room').RoomIO - -express.io = io -express.io.routeForward = middleware.routeForward - -session = express.session -delete express.session -sessionConfig = new Object -express.session = (options) -> - options ?= new Object - options.key ?= 'connect.sid' - options.store ?= new session.MemoryStore - options.cookie ?= new Object - sessionConfig = options - return session options -for key, value of session - express.session[key] = value - -express.application.http = -> - @server = http.createServer this - return this - -express.application.https = (options) -> - @server = https.createServer options, this - return this - -express.application.io = (options) -> - options ?= new Object - defaultOptions = log:false - _.extend options, defaultOptions - @io = io.listen @server, options - @io.router = new Object - @io.middleware = [] - @io.route = (route, next, options) -> - if options?.trigger is true - if route.indexOf ':' is -1 - @router[route] next - else - split = route.split ':' - @router[split[0]][split[1]] next - if _.isFunction next - @router[route] = next - else - for key, value of next - @router["#{route}:#{key}"] = value - @io.configure => @io.set 'authorization', (data, next) => - unless sessionConfig.store? - return async.forEachSeries @io.middleware, (callback, next) -> - callback(data, next) - , (error) -> - return next error if error? - next null, true - cookieParser = express.cookieParser() - cookieParser data, null, (error) -> - return next error if error? - rawCookie = data.cookies[sessionConfig.key] - unless rawCookie? - request = headers: cookie: data.query.cookie - return cookieParser request, null, (error) -> - data.cookies = request.cookies - rawCookie = data.cookies[sessionConfig.key] - return next "No cookie present", false unless rawCookie? - sessionId = connect.utils.parseSignedCookie rawCookie, sessionConfig.secret - data.sessionID = sessionId - sessionConfig.store.get sessionId, (error, session) -> - return next error if error? - data.session = new connect.session.Session data, session - next null, true - - sessionId = connect.utils.parseSignedCookie rawCookie, sessionConfig.secret - data.sessionID = sessionId - sessionConfig.store.get sessionId, (error, session) -> - return next error if error? - data.session = new connect.session.Session data, session - next null, true - - @io.use = (callback) => - @io.middleware.push callback - - @io.sockets.on 'connection', (socket) => - initRoutes socket, @io - - @io.broadcast = => - args = Array.prototype.slice.call arguments, 0 - @io.sockets.emit.apply @io.sockets, args - - @io.room = (room) => - new RoomIO(room, @io.sockets) - - @stack.push - route: '' - handle: (request, response, next) => - request.io = - route: (route) => - ioRequest = new Object - for key, value of request - ioRequest[key] = value - ioRequest.io = - broadcast: @io.broadcast - respond: => - args = Array.prototype.slice.call arguments, 0 - response.json.apply response, args - route: (route) => - @io.route route, ioRequest, trigger: true - data: request.body - @io.route route, ioRequest, trigger: true - broadcast: @io.broadcast - next() - - return this - -listen = express.application.listen -express.application.listen = -> - args = Array.prototype.slice.call arguments, 0 - if @server? - @server.listen.apply @server, args - else - listen.apply this, args - - -initRoutes = (socket, io) -> - setRoute = (key, callback) -> - socket.on key, (data, respond) -> - if typeof data is 'function' - respond = data - data = undefined - request = - data: data - session: socket.handshake.session - sessionID: socket.handshake.sessionID - sessionStore: sessionConfig.store - socket: socket - headers: socket.handshake.headers - cookies: socket.handshake.cookies - handshake: socket.handshake - session = socket.handshake.session - request.session = new connect.session.Session request, session if session? - socket.handshake.session = request.session - request.io = new RequestIO(socket, request, io) - request.io.respond = respond - request.io.respond ?= -> - callback request - for key, value of io.router - setRoute(key, value) - - -module.exports = express diff --git a/lib/middleware.coffee b/lib/middleware.coffee deleted file mode 100644 index d2c5fa0..0000000 --- a/lib/middleware.coffee +++ /dev/null @@ -1,67 +0,0 @@ - -_ = require 'underscore' - -regex = - single: /\/([^\/]+)\/?/ - doubleOptional: /\/([^\/]+)(?:\/([^\/]+)\/?)?/ - double: /\/([^\/]+)\/([^\/]+)\/?/ - -configs = - backbone: - create: - method: 'post' - regex: regex.single - read: - method: 'get' - regex: regex.doubleOptional - variables: ['id'] - update: - method: 'put' - regex: regex.double - variables: ['id'] - delete: - method: 'delete' - regex: regex.double - variables: ['id'] - angular: - list: - method: 'get' - regex: regex.single - create: - method: 'post' - regex: regex.single - read: - method: 'get' - regex: regex.double - variables: ['id'] - update: - method: 'put' - regex: regex.double - variables: ['id'] - delete: - method: 'delete' - regex: regex.double - variables: ['id'] - -configs.backbonjs = configs.backbone -configs.angularjs = configs.angular - -exports.routeForward = (options) -> - unless _.isObject options.config - options.type = options.config - options.config = configs[options.type] - unless options.config? - throw new Error("RouteForwardError: No config for #{options.type}") - (request, response, next) -> - for route, meta of options.config - if meta.method is request.method.toLowerCase() - match = meta.regex.exec request.url - if match? - meta.variables ?= [] - request.params ?= {} - for index, variable of meta.variables - request.params[variable] = match[2 + parseInt(index)] - return request.io.route("#{match[1]}:#{route}") - next() - - diff --git a/lib/request.coffee b/lib/request.coffee deleted file mode 100644 index d025be6..0000000 --- a/lib/request.coffee +++ /dev/null @@ -1,33 +0,0 @@ - -RoomIO = require('./room').RoomIO - -class exports.RequestIO - constructor: (socket, request, io) -> - @socket = socket - @request = request - @manager = io - - broadcast: (event, message) -> - @socket.broadcast.emit(event, message) - - emit: (event, message) -> - @socket.emit(event, message) - - room: (room) -> - new RoomIO(room, @socket) - - join: (room) -> - @socket.join(room) - - route: (route) -> - @manager.route route, @request, trigger: true - - leave: (room) -> - @socket.leave(room) - - on: -> - args = Array.prototype.slice.call arguments, 0 - @sockets.on.apply @socket, args - - disconnect: (callback) -> - @socket.disconnect(callback) diff --git a/lib/room.coffee b/lib/room.coffee deleted file mode 100644 index 4504c0c..0000000 --- a/lib/room.coffee +++ /dev/null @@ -1,10 +0,0 @@ - -class exports.RoomIO - constructor: (name, socket) -> - @name = name - @socket = socket - broadcast: (event, message) -> - if @socket.broadcast? - @socket.broadcast.to(@name).emit event, message - else - @socket.in(@name).emit event, message diff --git a/package.json b/package.json index 6f12297..b57ed5c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "express.io", - "version": "1.1.12", + "version": "0.0.2", "description": "Realtime-web framework for nodejs", "keywords": ["realtime", "web", "framework", "express.io", "express", "socket.io", "badass"], "homepage": "http://express-io.org", @@ -24,11 +24,12 @@ "url": "https://github.com/pharcosyle" }], "dependencies": { - "express": "~3.1.0", + "express": "3.3.5", "socket.io": "~0.9.13", "async": "0.1.22", "underscore": "1.4.3", - "coffee-script": "1.4.0" + "coffee-script": "1.4.0", + "socket.io-stream": "0.3.1" }, "devDependencies": { "request": "*", diff --git a/switch.js b/switch.js index 243884c..4ce82bc 100644 --- a/switch.js +++ b/switch.js @@ -1,8 +1,2 @@ - -try { - module.exports = require('./compiled'); -} catch(error) { - require('./node_modules/coffee-script'); - module.exports = require('./lib'); -} +module.exports = require('./compiled');