diff --git a/README.md b/README.md index f38c055..2a79a83 100755 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ # framer-Firebase The **Firebase module** allows your Framer prototype to **load**, **save** and **sync** data effortlessly between multiple sessions and devices. + +Updated to support Promises.
## Demo Projects @@ -27,8 +29,8 @@ These examples include access to a public demo database for the purpose of demon ## Getting started in under 5 minutes - Install with Framer Modules + Install with Framer Modules OR @@ -108,8 +110,8 @@ The required information is located at https://firebase.google.com → *Console* ```coffee firebase = new Firebase - projectID: ___________ # 1) ... Database → first part of URL - secret: ______________ # 2) ... Project Settings → Service Accounts → Database Secrets → Show (mouse-over) + projectID: ___________ # 1) ... Database → first part of URL + secret: ______________ # 2) ... Project Settings → Service Accounts → Database Secrets → Show (mouse-over) ``` @@ -134,8 +136,8 @@ If you wish not to use and share your database *secret* in your Framer project l ```json { "rules": { - ".read": "true", - ".write": "true" + ".read": "true", + ".write": "true" } } ``` @@ -196,20 +198,34 @@ Retrieves data from the database. ```coffee # Simple 1, expecting single value firebase.get "/value", (value) -> - print value + print value + +# Promise +firebase.get "/value" +.then (value) -> print value # Simple 2, expecting dataset firebase.get "/names", (names) -> - namesArray = _.toArray(names) # converts JSON to array - print name for name in namesArray + namesArray = _.toArray(names) # converts JSON to array + print name for name in namesArray + +# Promise +firebase.get "/names" +.then (names) -> + namesArray = _.toArray(names) # converts JSON to array + print name for name in namesArray # Advanced response = (names) -> - namesArray = _.toArray(names) - print name for name in namesArray + namesArray = _.toArray(names) + print name for name in namesArray firebase.get("/names",response,{orderBy: "$key", limitToFirst: 5}) +# Promise +firebase.get("/names",{orderBy: "$key", limitToFirst: 5}) +.then(response) + ```
@@ -232,10 +248,13 @@ firebase.put("/value", true) # Advanced response = (confirmation) -> - print confirmation + print confirmation firebase.put("/values", {"foo": true, "bar": false}, response) +# Promise +firebase.put("/values", {"foo": true, "bar": false}) +.then(response) ```
@@ -258,19 +277,19 @@ firebase.post("/value", true) # Advanced firebase.post("/addressBook", { # JSON encoded: - "name" : { - "forename" : "Jane", - "surename" : "Doe" - } + "name" : { + "forename" : "Jane", + "surename" : "Doe" + } - "birthday" : { - "day" : 4, - "month": 7, - "year" : 1976 - } + "birthday" : { + "day" : 4, + "month": 7, + "year" : 1976 + } - "tel" : "202-555-0101" - }) + "tel" : "202-555-0101" + }) ```
@@ -313,14 +332,14 @@ Fires, when the Framer project is loaded (returns all current data of the path) # Simple firebase.onChange "/values", (value) -> - print value + print value # Advanced response = (data, method, path, breadcrumbs) -> - # method returns either `put´ or `patch´, depending on what method changed the data - # path returns the path that was changed - # breadcrumbs returns the path as segments (array) - print "received #{data} via #{method}" + # method returns either `put´ or `patch´, depending on what method changed the data + # path returns the path that was changed + # breadcrumbs returns the path as segments (array) + print "received #{data} via #{method}" firebase.onChange("/values", response) @@ -336,8 +355,8 @@ Fires, whenever the connection status to Firebase has changed. ```coffee firebase.onChange "connection", (status) -> - # status is either `connected´ or `disconnected´ - print "Hooray, we're connected to Firebase" if status is "connected" + # status is either `connected´ or `disconnected´ + print "Hooray, we're connected to Firebase" if status is "connected" # Or @@ -376,11 +395,11 @@ For further information on how to order or limit requests please refer to [Fireb ```JSON { - "rules": { - ".read": "auth != null", - ".write": "auth != null", - "routes": {".indexOn": ["distance"]} - } + "rules": { + ".read": "auth != null", + ".write": "auth != null", + "routes": {".indexOn": ["distance"]} + } } ``` diff --git a/firebase.coffee b/firebase.coffee index b46ea64..e5dd3a3 100644 --- a/firebase.coffee +++ b/firebase.coffee @@ -1,5 +1,3 @@ - - # Documentation of this Module: https://github.com/marckrenn/framer-Firebase # ------ : ------- Firebase REST API: https://firebase.google.com/docs/reference/rest/database/ @@ -23,13 +21,11 @@ class exports.Firebase extends Framer.BaseClass console.log "Firebase: Connecting to Firebase Project '#{@projectID}' ... \n URL: 'https://#{@projectID}.firebaseio.com'" if @debug @.onChange "connection" - request = (project, secret, path, callback, method, data, parameters, debug) -> url = "https://#{project}.firebaseio.com#{path}.json#{secret}" - - unless parameters is undefined + if parameters? if parameters.shallow then url += "&shallow=true" if parameters.format is "export" then url += "&format=export" @@ -47,45 +43,40 @@ class exports.Firebase extends Framer.BaseClass url += "&startAt=#{parameters.startAt}" if typeof parameters.startAt is "number" url += "&endAt=#{parameters.endAt}" if typeof parameters.endAt is "number" url += "&equalTo=#{parameters.equalTo}" if typeof parameters.equalTo is "number" - - xhttp = new XMLHttpRequest + console.log "Firebase: New '#{method}'-request with data: '#{JSON.stringify(data)}' \n URL: '#{url}'" if debug - xhttp.onreadystatechange = => - - unless parameters is undefined - if parameters.print is "silent" or typeof parameters.download is "string" then return # ugh - - switch xhttp.readyState - when 0 then console.log "Firebase: Request not initialized \n URL: '#{url}'" if debug - when 1 then console.log "Firebase: Server connection established \n URL: '#{url}'" if debug - when 2 then console.log "Firebase: Request received \n URL: '#{url}'" if debug - when 3 then console.log "Firebase: Processing request \n URL: '#{url}'" if debug - when 4 - if xhttp.responseText? - callback(JSON.parse(xhttp.responseText)) if callback? - console.log "Firebase: Request finished, response: '#{JSON.parse(xhttp.responseText)}' \n URL: '#{url}'" if debug - else - console.log "Lost connection to Firebase." if debug - - - if xhttp.status is "404" - console.warn "Firebase: Invalid request, page not found \n URL: '#{url}'" if debug - - - xhttp.open(method, url, true) - xhttp.setRequestHeader("Content-type", "application/json; charset=utf-8") - xhttp.send(data = "#{JSON.stringify(data)}") - - + + options = if data? + body: JSON.stringify(data) + method: method + headers: + 'content-type': 'application/json; charset=utf-8' + + r = fetch url, (options ? {}) + .then (res) -> + if !res.ok then throw Error(res.statusText) + json = res.json() + json.then callback + return json + .catch (error) => console.warn(error) + + return r + + # Third argument can also accept options, rather than callback + parseArgs = (l, args..., cb) -> + if typeof args[l-1] is "object" + args[l] = args[l-1] + args[l-1] = null + + return cb.apply(null, args) # Available methods - get: (path, callback, parameters) -> request(@projectID, @secretEndPoint, path, callback, "GET", null, parameters, @debug) - put: (path, data, callback, parameters) -> request(@projectID, @secretEndPoint, path, callback, "PUT", data, parameters, @debug) - post: (path, data, callback, parameters) -> request(@projectID, @secretEndPoint, path, callback, "POST", data, parameters, @debug) - patch: (path, data, callback, parameters) -> request(@projectID, @secretEndPoint, path, callback, "PATCH", data, parameters, @debug) - delete: (path, callback, parameters) -> request(@projectID, @secretEndPoint, path, callback, "DELETE", null, parameters, @debug) - + get: (args...) -> parseArgs 2, args..., (path, callback, parameters) => request(@projectID, @secretEndPoint, path, callback, "GET", null, parameters, @debug) + put: (args...) -> parseArgs 3, args..., (path, data, callback, parameters) => request(@projectID, @secretEndPoint, path, callback, "PUT", data, parameters, @debug) + post: (args...) -> parseArgs 3, args..., (path, data, callback, parameters) => request(@projectID, @secretEndPoint, path, callback, "POST", data, parameters, @debug) + patch: (args...) -> parseArgs 3, args..., (path, data, callback, parameters) => request(@projectID, @secretEndPoint, path, callback, "PATCH", data, parameters, @debug) + delete: (args...) -> parseArgs 2, args..., (path, callback, parameters) => request(@projectID, @secretEndPoint, path, callback, "DELETE", null, parameters, @debug) onChange: (path, callback) -> @@ -111,17 +102,16 @@ class exports.Firebase extends Framer.BaseClass console.warn "Firebase: Connection to Firebase Project '#{@projectID}' closed" if @debug currentStatus = "disconnected" + return - else - - url = "https://#{@projectID}.firebaseio.com#{path}.json#{@secretEndPoint}" - source = new EventSource(url) - console.log "Firebase: Listening to changes made to '#{path}' \n URL: '#{url}'" if @debug + url = "https://#{@projectID}.firebaseio.com#{path}.json#{@secretEndPoint}" + source = new EventSource(url) + console.log "Firebase: Listening to changes made to '#{path}' \n URL: '#{url}'" if @debug - source.addEventListener "put", (ev) => - callback(JSON.parse(ev.data).data, "put", JSON.parse(ev.data).path, _.tail(JSON.parse(ev.data).path.split("/"),1)) if callback? - console.log "Firebase: Received changes made to '#{path}' via 'PUT': #{JSON.parse(ev.data).data} \n URL: '#{url}'" if @debug + source.addEventListener "put", (ev) => + callback(JSON.parse(ev.data).data, "put", JSON.parse(ev.data).path, _.tail(JSON.parse(ev.data).path.split("/"),1)) if callback? + console.log "Firebase: Received changes made to '#{path}' via 'PUT': #{JSON.parse(ev.data).data} \n URL: '#{url}'" if @debug - source.addEventListener "patch", (ev) => - callback(JSON.parse(ev.data).data, "patch", JSON.parse(ev.data).path, _.tail(JSON.parse(ev.data).path.split("/"),1)) if callback? - console.log "Firebase: Received changes made to '#{path}' via 'PATCH': #{JSON.parse(ev.data).data} \n URL: '#{url}'" if @debug + source.addEventListener "patch", (ev) => + callback(JSON.parse(ev.data).data, "patch", JSON.parse(ev.data).path, _.tail(JSON.parse(ev.data).path.split("/"),1)) if callback? + console.log "Firebase: Received changes made to '#{path}' via 'PATCH': #{JSON.parse(ev.data).data} \n URL: '#{url}'" if @debug