-
Notifications
You must be signed in to change notification settings - Fork 5
Core implementation
This needs cleanup and updating.
Release 5, target 30 June 2013
- Code structure
- URL path scheme
- Core module API
- JS model schema
- Neo4j schema
- Gateway module API
- REST API
Note: Module APIs are what is exposed through Node require();
- scrollback/
- scrollback.js - requires and initializes everything (parts of app.js)
- core/
- queries/ - cypher queries
- room.get.cypher
- room.create.cypher
- (other cypher files)
- core.js - formerly warehouse.js; brings other core APIs together
- room/
- room.js - new file, combines and simplified topic and discussion
- user/
- user.js - parts of existing user.js
- message/
- message.js - new file, parts of discussion.js
- account/
- account.js - new file, parts of user.js
- queries/ - cypher queries
- gateways/
- http/
- http.js - new file which initializes express (parts of app.js)
- session.js - session related stuff from sdk.js and api.js
- auth.js - authentication related stuff.
- api.js - the rest of api.js
- wdg.js - formerly wdg.js
- socket.js - formerly gateway/web.js
- img/ - image files go here
- sdk/ - currently js/sdk
- lib/
- sdk.js
- sdk.min.js - autogenerated file
- js/ - currently js/
- jade/
- layout.jade - currently known as widget.jade
- room.jade - enhanced version of discuss.jade
- (other jade files)
- css/
- res/ - other static resources go here
- email/
- email.js - new file
- xmpp/
- xmpp.js - formerly xmpp.js
- irc/
- irc.js - new file
- apn/
- apn.js - apple push notification service
- gcm/
- gcm.js - google cloud messaging for android
- wns/
- wns.js - windows notification service
- http/
- apps/
- wordpress/
- joomla/
- drupal/
- magento/
- phonegap/
- chrome/
- firefox/
- lib/
- log/
- tools/ - currently init
- tests/
- /a/ - APIs
- /w/ - Widgets
- /j/ - Client-side JS files
- /i/ - Images
- /s/ - Static resources
- / - rotates beteen landing pages in /s/landing
- /me - user's "inbox" (using Room Widget)
- /me/edit - edit own profiles, add/remove accounts
- /:id - Room widget or User profile widget; If it doesn't exist, create a room with no owner.
- /:id/edit - edit rooms (owned by current user) If the room has no owner, allow editing and make the current user owner on save.
In any file, you get a "core" object during initialization, which contains "builder" functions for room, user, message and account. Use these functions to access model objects.
For example, to load a single room with id "sandbox", call:
core.room('sandbox').then(function(sandbox) {
...
});
while to search for
and to create a new room
core.room({id: 'sandbox', name: 'Sandbox', owner: 'aravind', ...}).
then(function(sandbox) {
...
});
Where an object has references to other objects, for example room.owner above, the string ID of an existing user can be provided to the function. The returned sandbox object will have the actual user object loaded from the database.
Resource objects also have some common properties and methods:
- saved - Boolean property indicating whether the object exists in the DB.
- save() - method that saves the current state of the object to the DB.
- delete()
This would be used like:
sandbox.name = 'Alternate Sandbox';
sandbox.save();
Similarly, for every resource (room, user, message, account) there are common cypher files (parameters supplied to the query at execution time are given in parantheses):
queries/<res>.get.cypher (id: String)
queries/<res>.list.cypher (<params>)
queries/<res>.create.cypher (<writeable properties>)
queries/<res>.udpate.cypher (<writeable properties>)
queries/<res>.delete.cypher (id: String)
As these are common, they are not listed in the schemas below.
The .get.cypher query returns the properties of the object listed here. Some of them (e.g. room#owner) is not a property in Neo4j but a separate node that is linked through a relationship. The get.cypher will traverse and get those as well.
.list.cypher takes a 'params' object like:
{ "where": { "key1": "value", "key2": ["values", "values"], "key3": {"lt": 45} },
"order": {"key1": "asc", "key2": "desc"},
"limit": [0, 100] }
Read/write properties
id String // Room ID's cannot be less than 4 characters long.
name String
type String // topic, discussion, user
picture String
description String
owner User // loaded up from a Neo4j relationship.
web.allowedUrls String // regex that matches allowed referrer URLs
Read-only properties
present Boolean // am i present? (do i have at least 1 present listener)?
listenerCount Integer // rooms listening to me
announcerCount Integer // rooms i'm listening to
presentCount Integer // number of listeners who are "present"
messageCount Integer
createdAt Timestamp
lastMessageAt Timestamp
Getter methods
getListeners() (params)->[Room] // room.getListeners.cypher
getAnnouncers() (params)->[Room] // room.getSpeakers.cypher
getMessages() (params)->[Message] // room.getMessagess.cypher
Setter methods
startListening() (toId)->null // room.startListening.cypher
stopListening() (toId)->null // room.stopListening.cypher
User is a subclass of room and inherits all its properties. In addition, it has the getter methods:
getOwnRooms() (params)->[Room]
getOwnAccounts() (params)->[Account]
Note: All the routing magic happens when save() is called on a message object. It is implemented in message.save.cypher. It creates new 'reaches' relationships between the message and all the rooms and accounts that the message "has reached", starting with its from and to.
All properties are read-write.
id String // auto-generated GUID
type String // text, invite, join, part, away, back
text Text
time Timestamp
from Room
to Room
account Account // from which this message was sent
resource String // account-specific resource identifier
about String // optional: id of room invitation is for
getRooms() (params)->[Room] // rooms this has been sent to.
getAccounts() (params)->[Account] // message.getAccounts.cypher
All properties are read-write.
id String // auto-generated GUID
belongs User
listens Room
gateway String
identifier String
present Boolean // account available in real time?
params Text/Json
All nodes are indexed on 'id'. There are no relationship indexes. The properties of each node are listed.
id String
name String
type String
picture String
description String
allowedUrls String
id String
gateway String
identifier String
present Boolean
params Text/Json
id String
type String
text Text
time Timestamp
fromResource String
about String
listener -> announcer
Room -> Room
Account -> Room
object -> owner
Room -> Room[type=user]
Account -> Room[type=user]
Message -[:from]-> Account
Message -[:from]-> Room
Message -[:to]-> Room
Message -[:reaches]-> Room
Message -[:reaches]-> Account
All the methods are optional.
init(core, config)
Initialize the gateway. Make a local reference to the core object.
send({id, type, text, time, from, to}, [identifier]) -> ..Boolean
"From" is the room of the user the message was sent from; "To" is the room it was sent to; "Type" is text, away/back, invite, join/part This function should only be called ONCE per message per gateway, with all the recipients' account objects in the second parameter.
Returns a promise that resolves true or false depending on sending success.
auth(identifier, token) -> ..Boolean
Returns a promise which resolves to a boolean to indicate if the token correctly authenticates the account. For example, if an fb account and access token are passed, it will verify it with fb and resolve to true or false.
getProfile(identifier) -> ..String
For gateways like facebook, returns a URL with the profile page of the user on that network.
getPicture(identifier) -> ..String
For gateways like facebook, returns a URL with the picture/avatar of the user on that network.
room.get
room.create
room.update
room.delete
room.getListeners
room.getAnnouncers
room.getMessages
room.startListening
room.stopListening
user.getOwnRooms
user.getOwnAccounts
message.get
message.create
message.update
message.delete
message.getRooms
message.getAccounts
account.get
account.create
account.update
account.delete