diff --git a/.c9/.nakignore b/.c9/.nakignore
new file mode 100644
index 0000000..6d30aa6
--- /dev/null
+++ b/.c9/.nakignore
@@ -0,0 +1,17 @@
+*~backup-*
+.c9revisions
+.c9
+.git
+.svn
+.DS_Store
+.bzr
+.cdv
+~.dep
+~.dot
+~.nib
+~.plst
+.hg
+.pc
+*.min.js
+.nakignore
+/dev
diff --git a/.c9/metadata/tab0 b/.c9/metadata/tab0
new file mode 100644
index 0000000..a8959a2
--- /dev/null
+++ b/.c9/metadata/tab0
@@ -0,0 +1 @@
+{"filter":false,"title":"bash - \"ziyasal-firesharp-1226383\"","tooltip":"bash - \"ziyasal-firesharp-1226383\"","undoManager":{"mark":0,"position":-1,"stack":[]},"terminal":{"id":"ziyasal@firesharp_829","cwd":"","width":916,"height":127,"scrollTop":899},"timestamp":1421695510688,"hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709"}
\ No newline at end of file
diff --git a/.c9/metadata/workspace/FireSharp.Tests/FiresharpTestBase.cs b/.c9/metadata/workspace/FireSharp.Tests/FiresharpTestBase.cs
new file mode 100644
index 0000000..01147ab
--- /dev/null
+++ b/.c9/metadata/workspace/FireSharp.Tests/FiresharpTestBase.cs
@@ -0,0 +1 @@
+{"filter":false,"title":"FiresharpTestBase.cs","tooltip":"/FireSharp.Tests/FiresharpTestBase.cs","undoManager":{"mark":-1,"position":-1,"stack":[]},"ace":{"folds":[],"scrolltop":0,"scrollleft":0,"selection":{"start":{"row":0,"column":0},"end":{"row":0,"column":0},"isBackwards":false},"options":{"guessTabSize":true,"useWrapMode":false,"wrapToView":true},"firstLineState":0},"timestamp":1421695821516,"hash":"7de76223c39d83ef93c4dbed4dc69d4d5d8d8674"}
\ No newline at end of file
diff --git a/.c9/metadata/workspace/build.sh b/.c9/metadata/workspace/build.sh
new file mode 100644
index 0000000..eb540f9
--- /dev/null
+++ b/.c9/metadata/workspace/build.sh
@@ -0,0 +1 @@
+{"filter":false,"title":"build.sh","tooltip":"/build.sh","undoManager":{"mark":1,"position":1,"stack":[[{"group":"doc","deltas":[{"start":{"row":0,"column":0},"end":{"row":835,"column":0},"action":"remove","lines":["","","","","","","
"," "," "," "," "," "," InfluxDB.Net/build.sh at master · ziyasal/InfluxDB.Net · GitHub"," "," "," "," "," "," "," ",""," ","",""," "," "," "," "," "," ",""," "," "," "," ",""," "," "," ",""," "," "," ","",""," ","",""," "," "," "," ","",""," ",""," "," "," ",""," "," ",""," ","",""," "," Skip to content"," "," "," "," "," ","",""," "," ","","","","
","
","
"," ","
","
","
"," ","
","",""," - "," "," "," Star"," ",""," "," 14"," ","","
",""," - "," "," "," Fork"," "," "," 3"," ","
","
","","
","
","
","","
","
","","","
",""," "," ","
","",""," ","","",""," ","
","
"," Something went wrong with that request. Please try again.","
","",""," "," "," "," "," ","","",""]},{"start":{"row":0,"column":0},"end":{"row":75,"column":15},"action":"insert","lines":["build() {"," mono .nuget/NuGet.exe install NUnit.Runners"," mono .nuget/NuGet.exe restore InfluxDB.Net.sln",""," xbuild /t:Rebuild InfluxDB.Net.sln",""," if [[ $? != 0 ]] ; then"," build_failed"," else"," build_succeeded"," fi","}","","build_failed() {"," print_status \"BUILD FAILED\""," return 1","}","","build_succeeded() {"," print_status \"BUILD SUCCEEDED\""," run_tests","}","","run_tests() {"," print_status \"RUNNING TESTS\"",""," if [ -z \"$USE_SYSTEM_NUNIT_CONSOLE\" ]; then"," RUNNER_PATH=\"packages/NUnit.Runners.2.6.4/tools\""," else"," RUNNER_PATH=\"/usr/lib/nunit\""," fi"," NUNIT_ADDT_ARGS=\"\"",""," if [[ $NUNIT_RUN != \"\" ]]; then"," NUNIT_RUN_CSV=\"\""," for RUN in $NUNIT_RUN"," do"," NUNIT_RUN_CSV=\"$NUNIT_RUN_CSV,$RUN\""," done"," NUNIT_ADDT_ARGS=\"$NUNIT_ADDT_ARGS -run $NUNIT_RUN_CSV\""," fi",""," mono ${RUNNER_PATH}/nunit-console.exe \\"," InfluxDB.Net.Tests/bin/Debug/InfluxDB.Net.Tests.dll \\"," $NUNIT_ADDT_ARGS",""," local test_result=$?"," "," if [[ \"${test_result}\" != 0 ]] ; then"," tests_failed"," else"," tests_passed"," fi","}","","tests_failed() {"," print_status \"TESTS FAILED\""," return 2","}","","tests_passed() {"," print_status \"TESTS PASSED\"","}","","print_status() {"," echo \"\""," echo \"*** $1 ***\""," echo \"\"","}","","NUNIT_RUN=$*","build","","EXIT_CODE=$?","echo \"Exit [$EXIT_CODE]\"","exit $EXIT_CODE"]}]}],[{"group":"doc","deltas":[{"start":{"row":2,"column":34},"end":{"row":2,"column":46},"action":"remove","lines":["InfluxDB.Net"]},{"start":{"row":2,"column":34},"end":{"row":2,"column":43},"action":"insert","lines":["FireSharp"]},{"start":{"row":4,"column":22},"end":{"row":4,"column":34},"action":"remove","lines":["InfluxDB.Net"]},{"start":{"row":4,"column":22},"end":{"row":4,"column":31},"action":"insert","lines":["FireSharp"]},{"start":{"row":43,"column":8},"end":{"row":43,"column":20},"action":"remove","lines":["InfluxDB.Net"]},{"start":{"row":43,"column":8},"end":{"row":43,"column":17},"action":"insert","lines":["FireSharp"]},{"start":{"row":43,"column":34},"end":{"row":43,"column":46},"action":"remove","lines":["InfluxDB.Net"]},{"start":{"row":43,"column":34},"end":{"row":43,"column":43},"action":"insert","lines":["FireSharp"]}]}]]},"ace":{"folds":[],"scrolltop":0,"scrollleft":0,"selection":{"start":{"row":7,"column":20},"end":{"row":7,"column":20},"isBackwards":false},"options":{"guessTabSize":true,"useWrapMode":false,"wrapToView":true},"firstLineState":0},"timestamp":1421695754586,"hash":"35e85b59a73cab0f0af53c37ca2f396867ead2fb"}
\ No newline at end of file
diff --git a/.c9/metadata/workspace/circle.yml b/.c9/metadata/workspace/circle.yml
new file mode 100644
index 0000000..1f4f0c8
--- /dev/null
+++ b/.c9/metadata/workspace/circle.yml
@@ -0,0 +1 @@
+{"filter":false,"title":"circle.yml","tooltip":"/circle.yml","undoManager":{"mark":4,"position":4,"stack":[[{"group":"doc","deltas":[{"start":{"row":0,"column":0},"end":{"row":607,"column":0},"action":"remove","lines":["","","","","",""," "," "," "," "," "," "," InfluxDB.Net/circle.yml at master · ziyasal/InfluxDB.Net · GitHub"," "," "," "," "," "," "," ",""," ","",""," "," "," "," "," "," ",""," "," "," "," ",""," "," "," ",""," "," "," ","",""," ","",""," "," "," "," ","",""," ",""," "," "," ",""," "," ",""," ","",""," "," Skip to content"," "," "," "," "," ","",""," "," ","","","","
","
","
"," ","
","
","
"," ","
","",""," - "," "," "," Star"," ",""," "," 14"," ","","
",""," - "," "," "," Fork"," "," "," 3"," ","
","
","","
","
","
","","
","
","","","
",""," "," ","
","",""," ","","",""," ","
","
"," Something went wrong with that request. Please try again.","
","",""," "," "," "," "," ","","",""]}]}],[{"group":"doc","deltas":[{"start":{"row":0,"column":0},"end":{"row":21,"column":16},"action":"insert","lines":["machine:"," environment:"," USE_SYSTEM_NUNIT_CONSOLE: 1","","dependencies:"," pre:"," - wget https://s3.amazonaws.com/influxdb/influxdb_0.8.7_amd64.deb"," - sudo dpkg -i influxdb_0.8.7_amd64.deb"," - sudo /etc/init.d/influxdb start"," - sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF"," - echo \"deb http://download.mono-project.com/repo/debian wheezy main\" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list"," - sudo apt-get update"," - sudo apt-get install mono-devel"," - sudo apt-get install mono-complete"," - sudo apt-get install referenceassemblies-pcl"," - mozroots --import --sync"," - mono .nuget/NuGet.exe restore InfluxDB.Net.sln"," - sudo chmod +x build.sh","","test:"," override:"," - ./build.sh"]}]}],[{"group":"doc","deltas":[{"start":{"row":6,"column":0},"end":{"row":8,"column":37},"action":"remove","lines":[" - wget https://s3.amazonaws.com/influxdb/influxdb_0.8.7_amd64.deb"," - sudo dpkg -i influxdb_0.8.7_amd64.deb"," - sudo /etc/init.d/influxdb start"]}]}],[{"group":"doc","deltas":[{"start":{"row":5,"column":6},"end":{"row":6,"column":0},"action":"remove","lines":["",""]}]}],[{"group":"doc","deltas":[{"start":{"row":13,"column":36},"end":{"row":13,"column":48},"action":"remove","lines":["InfluxDB.Net"]},{"start":{"row":13,"column":36},"end":{"row":13,"column":45},"action":"insert","lines":["FireSharp"]}]}]]},"ace":{"folds":[],"scrolltop":0,"scrollleft":0,"selection":{"start":{"row":10,"column":41},"end":{"row":10,"column":41},"isBackwards":false},"options":{"guessTabSize":true,"useWrapMode":false,"wrapToView":true},"firstLineState":0},"timestamp":1421695836866,"hash":"5d0a846e1d6f78599ebebc4cfe8ad7128403b808"}
\ No newline at end of file
diff --git a/.c9/project.settings b/.c9/project.settings
new file mode 100644
index 0000000..e773fe8
--- /dev/null
+++ b/.c9/project.settings
@@ -0,0 +1,35 @@
+{
+ "ace": {
+ "@guessTabSize": "true",
+ "@newLineMode": "unix",
+ "@tabSize": "4",
+ "@useSoftTabs": "true"
+ },
+ "build": {
+ "@builder": "auto",
+ "@path": "/.c9/builders",
+ "@saveall": "true"
+ },
+ "find.nak": {
+ "@searchLimit": 100
+ },
+ "language": {
+ "@instanceHighlight": "true",
+ "@semi": "true",
+ "@undeclaredVars": "true",
+ "@unusedFunctionArgs": "false",
+ "@warnLevel": "info"
+ },
+ "run": {
+ "@path": "/.c9/runners",
+ "configs": {
+ "@inited": "true",
+ "json()": {}
+ }
+ },
+ "share": {
+ "@app": false,
+ "@preview": false,
+ "@useOwnerSettings": false
+ }
+}
\ No newline at end of file
diff --git a/FireSharp.Test.Console/App.config b/FireSharp.Test.Console/App.config
new file mode 100644
index 0000000..9c05822
--- /dev/null
+++ b/FireSharp.Test.Console/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FireSharp.Test.Console/FireSharp.Test.Console.csproj b/FireSharp.Test.Console/FireSharp.Test.Console.csproj
new file mode 100644
index 0000000..6bf40a4
--- /dev/null
+++ b/FireSharp.Test.Console/FireSharp.Test.Console.csproj
@@ -0,0 +1,88 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {0DF0042E-769D-409B-A9F7-19449FD0AFD0}
+ Exe
+ Properties
+ FireSharp.Test.Console
+ FireSharp.Test.Console
+ v4.5.1
+ 512
+ true
+ ..\
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+ ..\packages\Microsoft.Net.Http.2.2.28\lib\net45\System.Net.Http.Extensions.dll
+
+
+ ..\packages\Microsoft.Net.Http.2.2.28\lib\net45\System.Net.Http.Primitives.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {7613B723-E81B-4C02-A3EC-54F8F02C60F6}
+ FireSharp
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FireSharp.Test.Console/Program.cs b/FireSharp.Test.Console/Program.cs
new file mode 100644
index 0000000..cb02bc5
--- /dev/null
+++ b/FireSharp.Test.Console/Program.cs
@@ -0,0 +1,28 @@
+using FireSharp.Config;
+
+namespace FireSharp.Test.Console
+{
+ public class Program
+ {
+ private static FirebaseClient _client;
+ protected const string BASE_PATH = "https://firesharp.firebaseio.com/";
+ protected const string FIREBASE_SECRET = "fubr9j2Kany9KU3SHCIHBLm142anWCzvlBs1D977";
+ static void Main()
+ {
+ IFirebaseConfig config = new FirebaseConfig
+ {
+ AuthSecret = FIREBASE_SECRET,
+ BasePath = BASE_PATH
+ };
+
+ _client = new FirebaseClient(config); //Uses RestSharp JsonSerializer as default
+
+ _client.Listen("chat", added: (sender, args) =>
+ {
+ System.Console.WriteLine(args.Data);
+ });
+
+ System.Console.Read();
+ }
+ }
+}
diff --git a/FireSharp.Test.Console/Properties/AssemblyInfo.cs b/FireSharp.Test.Console/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..bdd4097
--- /dev/null
+++ b/FireSharp.Test.Console/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("FireSharp.Test.Console")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("FireSharp.Test.Console")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("36e73638-c60a-48e8-a807-e705468013a1")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/FireSharp.Test.Console/packages.config b/FireSharp.Test.Console/packages.config
new file mode 100644
index 0000000..d94744a
--- /dev/null
+++ b/FireSharp.Test.Console/packages.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FireSharp.Tests/App.config b/FireSharp.Tests/App.config
new file mode 100644
index 0000000..839a7a4
--- /dev/null
+++ b/FireSharp.Tests/App.config
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FireSharp.Tests/FireSharp.Tests.csproj b/FireSharp.Tests/FireSharp.Tests.csproj
new file mode 100644
index 0000000..e93dda4
--- /dev/null
+++ b/FireSharp.Tests/FireSharp.Tests.csproj
@@ -0,0 +1,98 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {F7C691EB-249D-48D7-BE52-DF33C55B1F96}
+ Library
+ Properties
+ FireSharp.Tests
+ FireSharp.Tests
+ v4.5
+ 512
+ ..\
+ true
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ False
+ ..\packages\Moq.4.2.1408.0717\lib\net40\Moq.dll
+
+
+ ..\packages\NUnit.2.6.3\lib\nunit.framework.dll
+
+
+ False
+ ..\packages\AutoFixture.3.20.0\lib\net40\Ploeh.AutoFixture.dll
+
+
+
+
+
+ ..\packages\Microsoft.Net.Http.2.2.28\lib\net45\System.Net.Http.Extensions.dll
+
+
+ ..\packages\Microsoft.Net.Http.2.2.28\lib\net45\System.Net.Http.Primitives.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {7613B723-E81B-4C02-A3EC-54F8F02C60F6}
+ FireSharp
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FireSharp.Tests/FirebaseClientTests.async.cs b/FireSharp.Tests/FirebaseClientTests.async.cs
new file mode 100644
index 0000000..5814a29
--- /dev/null
+++ b/FireSharp.Tests/FirebaseClientTests.async.cs
@@ -0,0 +1,32 @@
+using FireSharp.Tests.Models;
+using NUnit.Framework;
+
+namespace FireSharp.Tests
+{
+ public partial class FiresharpTests
+ {
+ private const string TODOS_ASYNC_PATH = "todos/async";
+
+ [Test, Category("INTEGRATION_ASYNC")]
+ public async void PushAsyncTest()
+ {
+ var todo = new Todo
+ {
+ name = "Do your homework",
+ priority = 1
+ };
+
+ var response = await _client.PushTaskAsync(string.Format("{0}", TODOS_ASYNC_PATH), todo);
+ Assert.NotNull(response);
+ Assert.IsTrue(response.Body.Contains("name"));
+ }
+
+ [Test, Category("INTEGRATION_ASYNC")]
+ public async void PushChatAsyncTest()
+ {
+ var response = await _client.PushTaskAsync("chat", new {name = "ziyasal", text = "Hello there"});
+ Assert.NotNull(response);
+ Assert.IsTrue(response.Body.Contains("name"));
+ }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp.Tests/FirebaseClientTests.cs b/FireSharp.Tests/FirebaseClientTests.cs
new file mode 100644
index 0000000..ca98b9a
--- /dev/null
+++ b/FireSharp.Tests/FirebaseClientTests.cs
@@ -0,0 +1,88 @@
+using System.Net;
+using System.Net.Http;
+using System.Threading.Tasks;
+using FireSharp.Extensions;
+using FireSharp.Interfaces;
+using FireSharp.Tests.Models;
+using Moq;
+using NUnit.Framework;
+using Ploeh.AutoFixture;
+
+namespace FireSharp.Tests
+{
+ public class FirebaseClientTests : FiresharpTestBase
+ {
+ private Todo _expected;
+ private HttpResponseMessage _expectedResponse;
+ private IFirebaseClient _firebaseClient;
+ private Mock _firebaseRequestManagerMock;
+
+ protected override void FinalizeSetUp()
+ {
+ _expected = new Todo
+ {
+ name = "Do your homework!",
+ priority = 1
+ };
+
+ _firebaseRequestManagerMock = MockFor();
+
+ _expectedResponse = FixtureRepository.Build()
+ .With(response => response.Content, new StringContent(_expected.ToJson()))
+ .With(response => response.StatusCode, HttpStatusCode.OK)
+ /*Ignore request field because it has no public constructor, is an abstract or non-public type*/
+ .Create();
+
+ _firebaseClient = new FirebaseClient(_firebaseRequestManagerMock.Object);
+ }
+
+ [Test]
+ public void Push()
+ {
+ _firebaseRequestManagerMock.Setup(firebaseRequestManager => firebaseRequestManager.Post("todos", _expected))
+ .Returns(Task.FromResult(_expectedResponse));
+
+ var response = _firebaseClient.Push("todos", _expected);
+ Assert.NotNull(response);
+ Assert.AreEqual(response.Body, _expected.ToJson());
+ }
+
+ [Test]
+ public void Set()
+ {
+ _firebaseRequestManagerMock.Setup(firebaseRequestManager => firebaseRequestManager.Put("todos", _expected))
+ .Returns(Task.FromResult(_expectedResponse));
+
+ var response = _firebaseClient.Set("todos", _expected);
+ Assert.NotNull(response);
+ Assert.AreEqual(response.Body, _expected.ToJson());
+ }
+
+ [Test]
+ public void Get()
+ {
+ _firebaseRequestManagerMock.Setup(firebaseRequestManager => firebaseRequestManager.Get("todos"))
+ .Returns(Task.FromResult(_expectedResponse));
+
+ var firebaseResponse = _firebaseClient.Get("todos");
+ Assert.NotNull(firebaseResponse);
+ Assert.AreEqual(firebaseResponse.Body, _expected.ToJson());
+ }
+
+ [Test]
+ public void Delete()
+ {
+ _firebaseRequestManagerMock.Setup(firebaseRequestManager => firebaseRequestManager.Delete("todos"))
+ .Returns(Task.FromResult(_expectedResponse));
+
+ var response = _firebaseClient.Delete("todos");
+ Assert.NotNull(response);
+ Assert.AreEqual(response.Success, true);
+ }
+
+ [Test]
+ public void Added_Event_Stream()
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp.Tests/FiresharpTestBase.cs b/FireSharp.Tests/FiresharpTestBase.cs
new file mode 100644
index 0000000..e9ce4d0
--- /dev/null
+++ b/FireSharp.Tests/FiresharpTestBase.cs
@@ -0,0 +1,18 @@
+using FireSharp.Config;
+using FireSharp.Interfaces;
+using NUnit.Framework;
+
+namespace FireSharp.Tests
+{
+ [TestFixture]
+ public class FiresharpTestBase : TestBase
+ {
+ protected const string BASE_PATH = "https://firesharp.firebaseio.com/";
+ protected const string FIREBASE_SECRET = "fubr9j2Kany9KU3SHCIHBLm142anWCzvlBs1D977";
+
+ public IFirebaseClient GetClientWithSerializer(IFirebaseConfig config)
+ {
+ return new FirebaseClient(config);
+ }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp.Tests/FiresharpTests.cs b/FireSharp.Tests/FiresharpTests.cs
new file mode 100644
index 0000000..249edb2
--- /dev/null
+++ b/FireSharp.Tests/FiresharpTests.cs
@@ -0,0 +1,104 @@
+using System;
+using FireSharp.Config;
+using FireSharp.Interfaces;
+using FireSharp.Tests.Models;
+using NUnit.Framework;
+
+namespace FireSharp.Tests
+{
+ public partial class FiresharpTests : FiresharpTestBase
+ {
+ private IFirebaseClient _client;
+
+ protected override void FinalizeSetUp()
+ {
+ IFirebaseConfig config = new FirebaseConfig
+ {
+ AuthSecret = FIREBASE_SECRET,
+ BasePath = BASE_PATH
+ };
+ _client = new FirebaseClient(config); //Uses RestSharp JsonSerializer as default
+ _client.Delete("todos");
+ }
+
+ [Test, Category("INTEGRATION")]
+ public void Delete()
+ {
+ _client.Push("todos/push", new Todo
+ {
+ name = "Execute PUSH4GET",
+ priority = 2
+ });
+
+ var response = _client.Delete("todos");
+ Assert.NotNull(response);
+ Assert.IsTrue(response.Success);
+ }
+
+ [Test, Category("INTEGRATION")]
+ public void Set()
+ {
+ var todo = new Todo
+ {
+ name = "Execute SET",
+ priority = 2
+ };
+ var response = _client.Set("todos/set", todo);
+ var result = response.ResultAs();
+ Assert.NotNull(response);
+ Assert.AreEqual(todo.name, result.name);
+ }
+
+ [Test, Category("INTEGRATION")]
+ public void Push()
+ {
+ var todo = new Todo
+ {
+ name = "Execute PUSH4",
+ priority = 2
+ };
+
+ var response = _client.Push("todos/push", todo);
+ Assert.NotNull(response);
+ Assert.NotNull(response.Result);
+ Assert.NotNull(response.Result.Name); /*Returns pushed data name like -J8LR7PDCdz_i9H41kf7*/
+ Console.WriteLine(response.Result.Name);
+ }
+
+ [Test, Category("INTEGRATION")]
+ public void Get()
+ {
+ _client.Push("todos/push", new Todo
+ {
+ name = "Execute PUSH4GET",
+ priority = 2
+ });
+
+ var response = _client.Get("todos");
+ Assert.NotNull(response);
+ Assert.IsTrue(response.Body.Contains("name"));
+ }
+
+ [Test, Category("INTEGRATION")]
+ public void Update()
+ {
+ _client.Set("todos/set", new Todo
+ {
+ name = "Execute SET",
+ priority = 2
+ });
+
+ var todoToUpdate = new Todo
+ {
+ name = "Execute UPDATE!",
+ priority = 1
+ };
+
+ var response = _client.Update("todos/set", todoToUpdate);
+ Assert.NotNull(response);
+ var actual = response.ResultAs();
+ Assert.AreEqual(todoToUpdate.name, actual.name);
+ Assert.AreEqual(todoToUpdate.priority, actual.priority);
+ }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp.Tests/Models/Todo.cs b/FireSharp.Tests/Models/Todo.cs
new file mode 100644
index 0000000..5b66394
--- /dev/null
+++ b/FireSharp.Tests/Models/Todo.cs
@@ -0,0 +1,8 @@
+namespace FireSharp.Tests.Models
+{
+ public class Todo
+ {
+ public string name { get; set; }
+ public int priority { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp.Tests/MoqExtensions/MoqExtensions.cs b/FireSharp.Tests/MoqExtensions/MoqExtensions.cs
new file mode 100644
index 0000000..8686252
--- /dev/null
+++ b/FireSharp.Tests/MoqExtensions/MoqExtensions.cs
@@ -0,0 +1,16 @@
+using System.Threading.Tasks;
+using Moq.Language;
+using Moq.Language.Flow;
+
+namespace FireSharp.Tests.MoqExtensions
+{
+ public static class MoqExtensions
+ {
+ public static IReturnsResult ReturnsAsync(
+ this IReturns> setup, TResult value)
+ where TMock : class
+ {
+ return setup.Returns(Task.FromResult(value));
+ }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp.Tests/NunitExtensions/AssertExtensions.cs b/FireSharp.Tests/NunitExtensions/AssertExtensions.cs
new file mode 100644
index 0000000..1da5647
--- /dev/null
+++ b/FireSharp.Tests/NunitExtensions/AssertExtensions.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Threading.Tasks;
+using NUnit.Framework;
+
+namespace FireSharp.Tests.NunitExtensions
+{
+ public static class AssertExtensions
+ {
+ public static async Task ThrowsAsync(Func func) where TException : Exception
+ {
+ var expected = typeof (TException);
+ Type actual = null;
+
+ try
+ {
+ await func();
+ }
+ catch (TException exception)
+ {
+ actual = exception.GetType();
+ }
+
+ Assert.AreEqual(expected, actual);
+ }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp.Tests/Properties/AssemblyInfo.cs b/FireSharp.Tests/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..ef86063
--- /dev/null
+++ b/FireSharp.Tests/Properties/AssemblyInfo.cs
@@ -0,0 +1,41 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("FireSharp.Tests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("FireSharp.Tests")]
+[assembly: AssemblyCopyright("Copyright © 2013")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+
+[assembly: Guid("65b19ec5-532b-4516-8220-e5cd92bc6baa")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+
+[assembly: AssemblyVersion("1.1.0")]
+[assembly: AssemblyFileVersion("1.1.0")]
+[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
\ No newline at end of file
diff --git a/FireSharp.Tests/TestBase.cs b/FireSharp.Tests/TestBase.cs
new file mode 100644
index 0000000..16b7cbd
--- /dev/null
+++ b/FireSharp.Tests/TestBase.cs
@@ -0,0 +1,60 @@
+using Moq;
+using NUnit.Framework;
+using Ploeh.AutoFixture;
+
+namespace FireSharp.Tests
+{
+ [TestFixture]
+ public class TestBase
+ {
+ private MockRepository _mockRepository;
+ protected IFixture FixtureRepository { get; set; }
+ protected bool VerifyAll { get; set; }
+
+ [SetUp]
+ public void Setup()
+ {
+ _mockRepository = new MockRepository(MockBehavior.Strict);
+ FixtureRepository = new Fixture();
+ VerifyAll = true;
+ FinalizeSetUp();
+ }
+
+ [TearDown]
+ public void TearDown()
+ {
+ if (VerifyAll)
+ {
+ _mockRepository.VerifyAll();
+ }
+ else
+ {
+ _mockRepository.Verify();
+ }
+ FinalizeTearDown();
+ }
+
+ protected Mock MockFor() where T : class
+ {
+ return _mockRepository.Create();
+ }
+
+ protected Mock MockFor(params object[] @params) where T : class
+ {
+ return _mockRepository.Create(@params);
+ }
+
+ protected void EnableCustomization(ICustomization customization)
+ {
+ customization.Customize(FixtureRepository);
+ }
+
+ protected virtual void FinalizeTearDown()
+ {
+ }
+
+ protected virtual void FinalizeSetUp()
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp.Tests/packages.config b/FireSharp.Tests/packages.config
new file mode 100644
index 0000000..aa9c333
--- /dev/null
+++ b/FireSharp.Tests/packages.config
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FireSharp.WebApp/App_Start/Bootstrapper.cs b/FireSharp.WebApp/App_Start/Bootstrapper.cs
new file mode 100644
index 0000000..83ad5a3
--- /dev/null
+++ b/FireSharp.WebApp/App_Start/Bootstrapper.cs
@@ -0,0 +1,41 @@
+using System.Web.Mvc;
+using System.Web.Routing;
+using Autofac;
+using Autofac.Integration.Mvc;
+using FireSharp.Config;
+using FireSharp.Interfaces;
+using FireSharp.WebApp.App_Start;
+
+namespace FireSharp.WebApp
+{
+ public static class Bootstrapper
+ {
+ private const string BASE_PATH = "https://firesharp.firebaseio.com/";
+ private const string FIREBASE_SECRET = "fubr9j2Kany9KU3SHCIHBLm142anWCzvlBs1D977";
+
+ public static void Start()
+ {
+ AreaRegistration.RegisterAllAreas();
+
+ FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
+ RouteConfig.RegisterRoutes(RouteTable.Routes);
+
+ var builder = new ContainerBuilder();
+
+ // Register your MVC controllers.
+ builder.RegisterControllers(typeof (MvcApplication).Assembly);
+
+ builder.Register(context => new FirebaseConfig
+ {
+ BasePath = BASE_PATH,
+ AuthSecret = FIREBASE_SECRET
+ }).As().SingleInstance();
+
+ builder.RegisterType().As().SingleInstance();
+
+
+ var container = builder.Build();
+ DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
+ }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp.WebApp/App_Start/FilterConfig.cs b/FireSharp.WebApp/App_Start/FilterConfig.cs
new file mode 100644
index 0000000..1ce1690
--- /dev/null
+++ b/FireSharp.WebApp/App_Start/FilterConfig.cs
@@ -0,0 +1,12 @@
+using System.Web.Mvc;
+
+namespace FireSharp.WebApp.App_Start
+{
+ public class FilterConfig
+ {
+ public static void RegisterGlobalFilters(GlobalFilterCollection filters)
+ {
+ filters.Add(new HandleErrorAttribute());
+ }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp.WebApp/App_Start/RouteConfig.cs b/FireSharp.WebApp/App_Start/RouteConfig.cs
new file mode 100644
index 0000000..671e8f7
--- /dev/null
+++ b/FireSharp.WebApp/App_Start/RouteConfig.cs
@@ -0,0 +1,17 @@
+using System.Web.Mvc;
+using System.Web.Routing;
+
+namespace FireSharp.WebApp.App_Start
+{
+ public class RouteConfig
+ {
+ public static void RegisterRoutes(RouteCollection routes)
+ {
+ routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
+
+ routes.MapRoute("Default", "{controller}/{action}/{id}",
+ new {controller = "Home", action = "Index", id = UrlParameter.Optional}
+ );
+ }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp.WebApp/Controllers/HomeController.cs b/FireSharp.WebApp/Controllers/HomeController.cs
new file mode 100644
index 0000000..c04758b
--- /dev/null
+++ b/FireSharp.WebApp/Controllers/HomeController.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Web.Mvc;
+using FireSharp.Interfaces;
+
+namespace FireSharp.WebApp.Controllers
+{
+ public class HomeController : Controller
+ {
+ private readonly IFirebaseClient _firebaseClient;
+
+ public HomeController(IFirebaseClient firebaseClient)
+ {
+ _firebaseClient = firebaseClient;
+ }
+
+ public ActionResult Index()
+ {
+ return View();
+ }
+
+ public ActionResult CallFirebase()
+ {
+ _firebaseClient.Push("chat/", new
+ {
+ name = "someone",
+ text = "Hello from backend :" + DateTime.Now.ToString("f")
+ });
+
+ return RedirectToAction("Index");
+ }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp.WebApp/FireSharp.WebApp.csproj b/FireSharp.WebApp/FireSharp.WebApp.csproj
new file mode 100644
index 0000000..5679e27
--- /dev/null
+++ b/FireSharp.WebApp/FireSharp.WebApp.csproj
@@ -0,0 +1,181 @@
+
+
+
+
+ Debug
+ AnyCPU
+
+
+ 2.0
+ {36E7801E-AF0D-47F7-9C6C-7BE3DBB9DF30}
+ {E3E379DF-F4C6-4180-9B81-6769533ABE47};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}
+ Library
+ Properties
+ FireSharp.WebApp
+ FireSharp.WebApp
+ v4.5
+ false
+ true
+
+
+
+
+ ..\
+ true
+
+
+ true
+ full
+ false
+ bin\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Autofac.3.1.0\lib\net40\Autofac.dll
+
+
+ ..\packages\Autofac.Mvc4.3.1.0\lib\net40\Autofac.Integration.Mvc.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll
+
+
+ True
+ ..\packages\Microsoft.AspNet.Mvc.FixedDisplayModes.1.0.0\lib\net40\Microsoft.Web.Mvc.FixedDisplayModes.dll
+
+
+
+
+
+
+ True
+ ..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.Helpers.dll
+
+
+ True
+ ..\packages\Microsoft.AspNet.Mvc.4.0.20710.0\lib\net40\System.Web.Mvc.dll
+
+
+ True
+ ..\packages\Microsoft.AspNet.Razor.2.0.20715.0\lib\net40\System.Web.Razor.dll
+
+
+ True
+ ..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.dll
+
+
+ True
+ ..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Deployment.dll
+
+
+ True
+ ..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Razor.dll
+
+
+
+
+
+
+ Global.asax
+
+
+
+
+
+
+
+
+
+ Web.config
+
+
+ Web.config
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {7613B723-E81B-4C02-A3EC-54F8F02C60F6}
+ FireSharp
+
+
+
+ 10.0
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ 0
+ /
+ http://localhost:10432/
+ False
+ False
+
+
+ False
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FireSharp.WebApp/Global.asax b/FireSharp.WebApp/Global.asax
new file mode 100644
index 0000000..1be73d1
--- /dev/null
+++ b/FireSharp.WebApp/Global.asax
@@ -0,0 +1 @@
+<%@ Application Codebehind="Global.asax.cs" Inherits="FireSharp.WebApp.MvcApplication" Language="C#" %>
\ No newline at end of file
diff --git a/FireSharp.WebApp/Global.asax.cs b/FireSharp.WebApp/Global.asax.cs
new file mode 100644
index 0000000..d966e34
--- /dev/null
+++ b/FireSharp.WebApp/Global.asax.cs
@@ -0,0 +1,12 @@
+using System.Web;
+
+namespace FireSharp.WebApp
+{
+ public class MvcApplication : HttpApplication
+ {
+ protected void Application_Start()
+ {
+ Bootstrapper.Start();
+ }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp.WebApp/Properties/AssemblyInfo.cs b/FireSharp.WebApp/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..c476bda
--- /dev/null
+++ b/FireSharp.WebApp/Properties/AssemblyInfo.cs
@@ -0,0 +1,38 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("FireSharp.WebApp")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("FireSharp.WebApp")]
+[assembly: AssemblyCopyright("Copyright © 2013")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+
+[assembly: Guid("740c95ea-0885-4639-8f3a-571dfff81495")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
\ No newline at end of file
diff --git a/FireSharp.WebApp/Views/Home/Index.cshtml b/FireSharp.WebApp/Views/Home/Index.cshtml
new file mode 100644
index 0000000..885d348
--- /dev/null
+++ b/FireSharp.WebApp/Views/Home/Index.cshtml
@@ -0,0 +1,44 @@
+@{
+ ViewBag.Title = "Index";
+ Layout = "~/Views/Shared/_Layout.cshtml";
+}
+@section styles{
+
+}
+
+Send Message From Backed
+
+
+
+
+
+
+
+@section scripts {
+
+
+
+}
\ No newline at end of file
diff --git a/FireSharp.WebApp/Views/Shared/_Layout.cshtml b/FireSharp.WebApp/Views/Shared/_Layout.cshtml
new file mode 100644
index 0000000..4bc9a7c
--- /dev/null
+++ b/FireSharp.WebApp/Views/Shared/_Layout.cshtml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ @ViewBag.Title
+ @RenderSection("styles", false)
+
+
+
+ @RenderBody()
+
+@RenderSection("scripts", false)
+
+
\ No newline at end of file
diff --git a/FireSharp.WebApp/Views/Web.config b/FireSharp.WebApp/Views/Web.config
new file mode 100644
index 0000000..d00e42c
--- /dev/null
+++ b/FireSharp.WebApp/Views/Web.config
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FireSharp.WebApp/Web.Debug.config b/FireSharp.WebApp/Web.Debug.config
new file mode 100644
index 0000000..3e2a97c
--- /dev/null
+++ b/FireSharp.WebApp/Web.Debug.config
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FireSharp.WebApp/Web.Release.config b/FireSharp.WebApp/Web.Release.config
new file mode 100644
index 0000000..9fd481f
--- /dev/null
+++ b/FireSharp.WebApp/Web.Release.config
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FireSharp.WebApp/Web.config b/FireSharp.WebApp/Web.config
new file mode 100644
index 0000000..2fe3818
--- /dev/null
+++ b/FireSharp.WebApp/Web.config
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FireSharp.WebApp/packages.config b/FireSharp.WebApp/packages.config
new file mode 100644
index 0000000..91cc294
--- /dev/null
+++ b/FireSharp.WebApp/packages.config
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FireSharp.sln b/FireSharp.sln
new file mode 100644
index 0000000..de48e1c
--- /dev/null
+++ b/FireSharp.sln
@@ -0,0 +1,47 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FireSharp", "FireSharp\FireSharp.csproj", "{7613B723-E81B-4C02-A3EC-54F8F02C60F6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FireSharp.Tests", "FireSharp.Tests\FireSharp.Tests.csproj", "{F7C691EB-249D-48D7-BE52-DF33C55B1F96}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FireSharp.WebApp", "FireSharp.WebApp\FireSharp.WebApp.csproj", "{36E7801E-AF0D-47F7-9C6C-7BE3DBB9DF30}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{83537A83-211C-4D17-B2BC-7737600D6B29}"
+ ProjectSection(SolutionItems) = preProject
+ .nuget\NuGet.Config = .nuget\NuGet.Config
+ .nuget\NuGet.exe = .nuget\NuGet.exe
+ .nuget\NuGet.targets = .nuget\NuGet.targets
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FireSharp.Test.Console", "FireSharp.Test.Console\FireSharp.Test.Console.csproj", "{0DF0042E-769D-409B-A9F7-19449FD0AFD0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {7613B723-E81B-4C02-A3EC-54F8F02C60F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7613B723-E81B-4C02-A3EC-54F8F02C60F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7613B723-E81B-4C02-A3EC-54F8F02C60F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7613B723-E81B-4C02-A3EC-54F8F02C60F6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F7C691EB-249D-48D7-BE52-DF33C55B1F96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F7C691EB-249D-48D7-BE52-DF33C55B1F96}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F7C691EB-249D-48D7-BE52-DF33C55B1F96}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F7C691EB-249D-48D7-BE52-DF33C55B1F96}.Release|Any CPU.Build.0 = Release|Any CPU
+ {36E7801E-AF0D-47F7-9C6C-7BE3DBB9DF30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {36E7801E-AF0D-47F7-9C6C-7BE3DBB9DF30}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {36E7801E-AF0D-47F7-9C6C-7BE3DBB9DF30}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {36E7801E-AF0D-47F7-9C6C-7BE3DBB9DF30}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0DF0042E-769D-409B-A9F7-19449FD0AFD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0DF0042E-769D-409B-A9F7-19449FD0AFD0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0DF0042E-769D-409B-A9F7-19449FD0AFD0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0DF0042E-769D-409B-A9F7-19449FD0AFD0}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/FireSharp/Config/FirebaseConfig.cs b/FireSharp/Config/FirebaseConfig.cs
new file mode 100644
index 0000000..707d6db
--- /dev/null
+++ b/FireSharp/Config/FirebaseConfig.cs
@@ -0,0 +1,14 @@
+namespace FireSharp.Config
+{
+ public class FirebaseConfig : IFirebaseConfig
+ {
+ public FirebaseConfig()
+ {
+ TimeoutInMinute = 1;
+ }
+
+ public string BasePath { get; set; }
+ public string AuthSecret { get; set; }
+ public int TimeoutInMinute { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp/Config/IFirebaseConfig.cs b/FireSharp/Config/IFirebaseConfig.cs
new file mode 100644
index 0000000..6ee9127
--- /dev/null
+++ b/FireSharp/Config/IFirebaseConfig.cs
@@ -0,0 +1,9 @@
+namespace FireSharp.Config
+{
+ public interface IFirebaseConfig
+ {
+ string BasePath { get; set; }
+ string AuthSecret { get; set; }
+ int TimeoutInMinute { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp/EventStreaming/CacheItem.cs b/FireSharp/EventStreaming/CacheItem.cs
new file mode 100644
index 0000000..3118aee
--- /dev/null
+++ b/FireSharp/EventStreaming/CacheItem.cs
@@ -0,0 +1,18 @@
+using System.Collections.Generic;
+
+namespace FireSharp.EventStreaming
+{
+ internal class CacheItem
+ {
+ private List _children;
+ public string Name { get; set; }
+ public string Value { get; set; }
+ public CacheItem Parent { get; set; }
+ public bool Created { get; set; }
+
+ public List Children
+ {
+ get { return _children ?? (_children = new List()); }
+ }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp/EventStreaming/Delegates.cs b/FireSharp/EventStreaming/Delegates.cs
new file mode 100644
index 0000000..7ad4065
--- /dev/null
+++ b/FireSharp/EventStreaming/Delegates.cs
@@ -0,0 +1,8 @@
+namespace FireSharp.EventStreaming
+{
+ public delegate void ValueAddedEventHandler(object sender, ValueAddedEventArgs args);
+
+ public delegate void ValueChangedEventHandler(object sender, ValueChangedEventArgs args);
+
+ public delegate void ValueRemovedEventHandler(object sender, ValueRemovedEventArgs args);
+}
\ No newline at end of file
diff --git a/FireSharp/EventStreaming/TODO.md b/FireSharp/EventStreaming/TODO.md
new file mode 100644
index 0000000..a3f2103
--- /dev/null
+++ b/FireSharp/EventStreaming/TODO.md
@@ -0,0 +1,53 @@
+https://www.firebase.com/docs/rest-api.html
+
+Streaming from the REST API
+=============================
+
+Firebase REST endpoints support the EventSource / Server-Sent Events protocol as well. To stream changes to a single location in your Firebase, you will need to do a few things:
+
+Set the client's Accept header to "text/event-stream"
+Respect HTTP Redirects, in particular HTTP status code 307
+If the location requires permission to read, you must include the auth parameter (see above in Query Parameters)
+In return, the server will send named events as the state of the data at the requested URL changes. The structure of these messages conforms to the EventSource protocol:
+
+event: event name
+data: JSON encoded data payload
+The server may send the following events:
+
+put
+The JSON-encoded data will be an object with two keys: path and data
+The path points to a location relative to the request URL
+The client should replace all of the data at that location in its cache with the data given in the message
+
+patch
+The JSON-encoded data will be an object with two keys: path and data
+The path points to a location relative to the request URL
+For each key in the data, the client should replace the corresponding key in its cache with the data for that key in the message
+
+keep-alive
+The data for this event is null, no action is required
+
+cancel
+The data for this event is null
+This event will be sent if the security rules cause a read at the requested location to no longer be allowed
+
+auth_revoked
+The data for this event is a string indicating that a the credential has expired
+This event will be sent when the supplied auth parameter is no longer valid
+Here's an example set of events that the server may send:
+
+// Set your entire cache to {"a": 1, "b": 2}
+event: put
+data: {"path": "/", "data": {"a": 1, "b": 2}}
+
+
+// Put the new data in your cache under the key 'c', so that the complete cache now looks like:
+// {"a": 1, "b": 2, "c": {"foo": true, "bar": false}}
+event: put
+data: {"path": "/c", "data": {"foo": true, "bar": false}}
+
+
+// For each key in the data, update (or add) the corresponding key in your cache at path /c,
+// for a final cache of: {"a": 1, "b": 2, "c": {"foo": 3, "bar": false, "baz": 4}}
+event: patch
+data: {"path": "/c", "data": {"foo": 3, "baz": 4}}
\ No newline at end of file
diff --git a/FireSharp/EventStreaming/TemporaryCache.cs b/FireSharp/EventStreaming/TemporaryCache.cs
new file mode 100644
index 0000000..880bb90
--- /dev/null
+++ b/FireSharp/EventStreaming/TemporaryCache.cs
@@ -0,0 +1,199 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Newtonsoft.Json;
+
+namespace FireSharp.EventStreaming
+{
+ internal sealed class TemporaryCache
+ {
+ private readonly LinkedList _pathFromRootList = new LinkedList();
+ private readonly char[] _seperator = {'/'};
+ private readonly CacheItem _tree = new CacheItem();
+ private readonly object _treeLock = new object();
+
+ public TemporaryCache()
+ {
+ _tree.Name = string.Empty;
+ _tree.Created = false;
+ _tree.Parent = null;
+ _tree.Name = null;
+ }
+
+ internal CacheItem Root
+ {
+ get { return _tree; }
+ }
+
+ public void Replace(string path, JsonReader data)
+ {
+ lock (_treeLock)
+ {
+ var root = FindRoot(path);
+ Replace(root, data);
+ }
+ }
+
+ public void Update(string path, JsonReader data)
+ {
+ lock (_treeLock)
+ {
+ var root = FindRoot(path);
+ UpdateChildren(root, data);
+ }
+ }
+
+ private CacheItem FindRoot(string path)
+ {
+ var segments = path.Split(_seperator, StringSplitOptions.RemoveEmptyEntries);
+
+ return segments.Aggregate(_tree, GetNamedChild);
+ }
+
+ private static CacheItem GetNamedChild(CacheItem root, string segment)
+ {
+ var newRoot = root.Children.FirstOrDefault(c => c.Name == segment);
+
+ if (newRoot == null)
+ {
+ newRoot = new CacheItem {Name = segment, Parent = root, Created = true};
+ root.Children.Add(newRoot);
+ }
+
+ return newRoot;
+ }
+
+ private void Replace(CacheItem root, JsonReader reader)
+ {
+ UpdateChildren(root, reader, true);
+ }
+
+ private void UpdateChildren(CacheItem root, JsonReader reader, bool replace = false)
+ {
+ if (replace)
+ {
+ DeleteChild(root);
+
+ if (root.Parent != null)
+ {
+ root.Parent.Children.Add(root);
+ }
+ }
+
+ while (reader.Read())
+ {
+ switch (reader.TokenType)
+ {
+ case JsonToken.PropertyName:
+ UpdateChildren(GetNamedChild(root, reader.Value.ToString()), reader);
+ break;
+ case JsonToken.Boolean:
+ case JsonToken.Bytes:
+ case JsonToken.Date:
+ case JsonToken.Float:
+ case JsonToken.Integer:
+ case JsonToken.String:
+ if (root.Created)
+ {
+ root.Value = reader.Value.ToString();
+ OnAdded(new ValueAddedEventArgs(PathFromRoot(root), reader.Value.ToString()));
+ root.Created = false;
+ }
+ else
+ {
+ var oldData = root.Value;
+ root.Value = reader.Value.ToString();
+ OnUpdated(new ValueChangedEventArgs(PathFromRoot(root), root.Value, oldData));
+ }
+
+ return;
+ case JsonToken.Null:
+ DeleteChild(root);
+ return;
+ }
+ }
+ }
+
+ private void DeleteChild(CacheItem root)
+ {
+ if (root.Parent != null)
+ {
+ if (RemoveChildFromParent(root))
+ {
+ OnRemoved(new ValueRemovedEventArgs(PathFromRoot(root)));
+ }
+ }
+ else
+ {
+ foreach (var child in root.Children.ToArray())
+ {
+ RemoveChildFromParent(child);
+ OnRemoved(new ValueRemovedEventArgs(PathFromRoot(child)));
+ }
+ }
+ }
+
+ private bool RemoveChildFromParent(CacheItem child)
+ {
+ if (child.Parent != null)
+ {
+ return child.Parent.Children.Remove(child);
+ }
+
+ return false;
+ }
+
+ private string PathFromRoot(CacheItem root)
+ {
+ var size = 1;
+
+ while (root.Name != null)
+ {
+ size += root.Name.Length + 1;
+ _pathFromRootList.AddFirst(root);
+ root = root.Parent;
+ }
+
+ if (_pathFromRootList.Count == 0)
+ {
+ return "/";
+ }
+
+ var sb = new StringBuilder(size);
+ foreach (var d in _pathFromRootList)
+ {
+ sb.AppendFormat("/{0}", d.Name);
+ }
+
+ _pathFromRootList.Clear();
+
+ return sb.ToString();
+ }
+
+ private void OnAdded(ValueAddedEventArgs args)
+ {
+ var added = Added;
+ if (added == null) return;
+ added(this, args);
+ }
+
+ private void OnUpdated(ValueChangedEventArgs args)
+ {
+ var updated = Changed;
+ if (updated == null) return;
+ updated(this, args);
+ }
+
+ private void OnRemoved(ValueRemovedEventArgs args)
+ {
+ var removed = Removed;
+ if (removed == null) return;
+ removed(this, args);
+ }
+
+ public event ValueAddedEventHandler Added;
+ public event ValueChangedEventHandler Changed;
+ public event ValueRemovedEventHandler Removed;
+ }
+}
\ No newline at end of file
diff --git a/FireSharp/EventStreaming/ValueAddedEventArgs.cs b/FireSharp/EventStreaming/ValueAddedEventArgs.cs
new file mode 100644
index 0000000..53f9da3
--- /dev/null
+++ b/FireSharp/EventStreaming/ValueAddedEventArgs.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace FireSharp.EventStreaming
+{
+ public class ValueAddedEventArgs : EventArgs
+ {
+ public ValueAddedEventArgs(string path, string data)
+ {
+ Path = path;
+ Data = data;
+ }
+
+ public string Path { get; private set; }
+ public string Data { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp/EventStreaming/ValueChangedEventArgs.cs b/FireSharp/EventStreaming/ValueChangedEventArgs.cs
new file mode 100644
index 0000000..14016c4
--- /dev/null
+++ b/FireSharp/EventStreaming/ValueChangedEventArgs.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace FireSharp.EventStreaming
+{
+ public class ValueChangedEventArgs : EventArgs
+ {
+ public ValueChangedEventArgs(string path, string data, string oldData)
+ {
+ Path = path;
+ Data = data;
+ OldData = oldData;
+ }
+
+ public string Path { get; private set; }
+ public string Data { get; private set; }
+ public string OldData { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp/EventStreaming/ValueRemovedEventArgs.cs b/FireSharp/EventStreaming/ValueRemovedEventArgs.cs
new file mode 100644
index 0000000..ae132fa
--- /dev/null
+++ b/FireSharp/EventStreaming/ValueRemovedEventArgs.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace FireSharp.EventStreaming
+{
+ public class ValueRemovedEventArgs : EventArgs
+ {
+ public ValueRemovedEventArgs(string path)
+ {
+ Path = path;
+ }
+
+ public string Path { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp/Exceptions/FirebaseException.cs b/FireSharp/Exceptions/FirebaseException.cs
new file mode 100644
index 0000000..e29552d
--- /dev/null
+++ b/FireSharp/Exceptions/FirebaseException.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace FireSharp.Exceptions
+{
+ public class FirebaseException : Exception
+ {
+ public FirebaseException(string message)
+ : base(message)
+ {
+ }
+
+ public FirebaseException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp/Extensions/ObjectExtensions.cs b/FireSharp/Extensions/ObjectExtensions.cs
new file mode 100644
index 0000000..0429fa3
--- /dev/null
+++ b/FireSharp/Extensions/ObjectExtensions.cs
@@ -0,0 +1,19 @@
+using System.Net.Http;
+using Newtonsoft.Json;
+
+namespace FireSharp.Extensions
+{
+ public static class ObjectExtensions
+ {
+ public static string ToJson(this object @object)
+ {
+ return JsonConvert.SerializeObject(@object);
+ }
+
+ public static T ReadAs(this HttpResponseMessage response)
+ {
+ var task = response.Content.ReadAsStringAsync();
+ return JsonConvert.DeserializeObject(task.Result);
+ }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp/FireSharp.csproj b/FireSharp/FireSharp.csproj
new file mode 100644
index 0000000..c9e584c
--- /dev/null
+++ b/FireSharp/FireSharp.csproj
@@ -0,0 +1,97 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {7613B723-E81B-4C02-A3EC-54F8F02C60F6}
+ Library
+ Properties
+ FireSharp
+ FireSharp
+ v4.5
+ 512
+ ..\
+ true
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Newtonsoft.Json.6.0.7\lib\net45\Newtonsoft.Json.dll
+ True
+
+
+
+
+
+ ..\packages\Microsoft.Net.Http.2.2.28\lib\net45\System.Net.Http.Extensions.dll
+
+
+ ..\packages\Microsoft.Net.Http.2.2.28\lib\net45\System.Net.Http.Primitives.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FireSharp/FireSharp.nuspec b/FireSharp/FireSharp.nuspec
new file mode 100644
index 0000000..852a4f7
--- /dev/null
+++ b/FireSharp/FireSharp.nuspec
@@ -0,0 +1,24 @@
+
+
+
+
+ FireSharp
+ 2.0.0
+ Fire#
+ ziyasal
+ ziyasal
+ https://github.com/ziyasal/FireSharp/blob/master/LICENSE.md
+ https://github.com/ziyasal/FireSharp
+ false
+ .Net wrapper for Firebase backend API
+ en-US
+ firebase rest api client realtime
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FireSharp/FirebaseClient.cs b/FireSharp/FirebaseClient.cs
new file mode 100644
index 0000000..4184646
--- /dev/null
+++ b/FireSharp/FirebaseClient.cs
@@ -0,0 +1,198 @@
+using System;
+using System.Threading.Tasks;
+using FireSharp.Config;
+using FireSharp.EventStreaming;
+using FireSharp.Exceptions;
+using FireSharp.Interfaces;
+using FireSharp.Response;
+
+namespace FireSharp
+{
+ public class FirebaseClient : IFirebaseClient, IDisposable
+ {
+ private readonly IFirebaseRequestManager _requestManager;
+
+ public FirebaseClient(IFirebaseConfig config)
+ : this(new FirebaseRequestManager(config))
+ {
+ }
+
+ internal FirebaseClient(IFirebaseRequestManager requestManager)
+ {
+ _requestManager = requestManager;
+ }
+
+ public void Dispose()
+ {
+ }
+
+ public FirebaseResponse Get(string path)
+ {
+ FirebaseResponse response;
+ try
+ {
+ var task = _requestManager.Get(path);
+ response = new FirebaseResponse(task.Result);
+ }
+ catch (FirebaseException ex)
+ {
+ response = new FirebaseResponse {Exception = ex};
+ }
+ return response;
+ }
+
+ public SetResponse Set(string path, T data)
+ {
+ SetResponse response;
+ try
+ {
+ var task = _requestManager.Put(path, data);
+ response = new SetResponse(task.Result);
+ }
+ catch (FirebaseException ex)
+ {
+ response = new SetResponse {Exception = ex};
+ }
+ return response;
+ }
+
+ public PushResponse Push(string path, T data)
+ {
+ PushResponse response;
+ try
+ {
+ var task = _requestManager.Post(path, data);
+ response = new PushResponse(task.Result);
+ }
+ catch (FirebaseException ex)
+ {
+ response = new PushResponse {Exception = ex};
+ }
+ return response;
+ }
+
+ public DeleteResponse Delete(string path)
+ {
+ DeleteResponse response;
+ try
+ {
+ var task = _requestManager.Delete(path);
+ response = new DeleteResponse(task.Result);
+ }
+ catch (FirebaseException ex)
+ {
+ response = new DeleteResponse {Exception = ex};
+ }
+ return response;
+ }
+
+ public FirebaseResponse Update(string path, T data)
+ {
+ FirebaseResponse response;
+ try
+ {
+ var task = _requestManager.Patch(path, data);
+ response = new FirebaseResponse(task.Result);
+ }
+ catch (FirebaseException ex)
+ {
+ response = new FirebaseResponse {Exception = ex};
+ }
+ return response;
+ }
+
+ public FirebaseResponse Listen(string path, ValueAddedEventHandler added = null,
+ ValueChangedEventHandler changed = null,
+ ValueRemovedEventHandler removed = null)
+ {
+ return ListenAsync(path, added, changed, removed).Result;
+ }
+
+ public async Task GetTaskAsync(string path)
+ {
+ FirebaseResponse response;
+ try
+ {
+ response = new FirebaseResponse(await _requestManager.GetTaskAsync(path));
+ }
+ catch (FirebaseException ex)
+ {
+ response = new FirebaseResponse {Exception = ex};
+ }
+ return response;
+ }
+
+ public async Task SetTaskAsync(string path, T data)
+ {
+ SetResponse response;
+ try
+ {
+ response = new SetResponse(await _requestManager.PutTaskAsync(path, data));
+ }
+ catch (FirebaseException ex)
+ {
+ response = new SetResponse {Exception = ex};
+ }
+ return response;
+ }
+
+ public async Task PushTaskAsync(string path, T data)
+ {
+ PushResponse response;
+ try
+ {
+ response = new PushResponse(await _requestManager.PostTaskAsync(path, data));
+ }
+ catch (FirebaseException ex)
+ {
+ response = new PushResponse {Exception = ex};
+ }
+ return response;
+ }
+
+ public async Task DeleteTaskAsync(string path)
+ {
+ DeleteResponse response;
+ try
+ {
+ response = new DeleteResponse(await _requestManager.DeleteTaskAsync(path));
+ }
+ catch (FirebaseException ex)
+ {
+ response = new DeleteResponse {Exception = ex};
+ }
+ return response;
+ }
+
+ public async Task UpdateTaskAsync(string path, T data)
+ {
+ FirebaseResponse response;
+ try
+ {
+ response = new FirebaseResponse(await _requestManager.PatchTaskAsync(path, data));
+ }
+ catch (FirebaseException ex)
+ {
+ response = new FirebaseResponse {Exception = ex};
+ }
+ return response;
+ }
+
+ public async Task ListenAsync(string path, ValueAddedEventHandler added = null,
+ ValueChangedEventHandler changed = null,
+ ValueRemovedEventHandler removed = null)
+ {
+ FirebaseResponse response;
+ try
+ {
+ response = new FirebaseResponse(await _requestManager.Listen(path), added, changed, removed);
+ }
+ catch (FirebaseException ex)
+ {
+ response = new FirebaseResponse {Exception = ex};
+ }
+
+ return response;
+ }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp/FirebaseRequestManager.cs b/FireSharp/FirebaseRequestManager.cs
new file mode 100644
index 0000000..34d80d4
--- /dev/null
+++ b/FireSharp/FirebaseRequestManager.cs
@@ -0,0 +1,136 @@
+using System;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Threading.Tasks;
+using FireSharp.Config;
+using FireSharp.Exceptions;
+using FireSharp.Interfaces;
+using Newtonsoft.Json;
+
+namespace FireSharp
+{
+ internal class FirebaseRequestManager : IFirebaseRequestManager, IDisposable
+ {
+ private readonly HttpClient _client;
+ private readonly IFirebaseConfig _config;
+
+ internal FirebaseRequestManager(IFirebaseConfig config)
+ {
+ _config = config;
+ var handler = new HttpClientHandler
+ {
+ AllowAutoRedirect = true
+ };
+
+ _client = new HttpClient(handler, true)
+ {
+ BaseAddress = new Uri(_config.BasePath),
+ Timeout = TimeSpan.FromMinutes(_config.TimeoutInMinute)
+ };
+ }
+
+ public void Dispose()
+ {
+ using (_client)
+ {
+ }
+ }
+
+ public Task Get(string path)
+ {
+ return ProcessRequest(HttpMethod.Get, path, null);
+ }
+
+ public Task Put(string path, T data)
+ {
+ return ProcessRequest(HttpMethod.Put, path, data);
+ }
+
+ public Task Post(string path, T data)
+ {
+ return ProcessRequest(HttpMethod.Post, path, data);
+ }
+
+ public Task Delete(string path)
+ {
+ return ProcessRequest(HttpMethod.Delete, path, null);
+ }
+
+ public Task Patch(string path, T data)
+ {
+ return ProcessRequest(new HttpMethod("PATCH"), path, data);
+ }
+
+ public async Task GetTaskAsync(string path)
+ {
+ return await ProcessRequest(HttpMethod.Get, path, null);
+ }
+
+ public async Task PutTaskAsync(string path, T data)
+ {
+ return await ProcessRequest(new HttpMethod("PATCH"), path, data);
+ }
+
+ public async Task PostTaskAsync(string path, T data)
+ {
+ return await ProcessRequest(HttpMethod.Post, path, data);
+ }
+
+ public async Task DeleteTaskAsync(string path)
+ {
+ return await ProcessRequest(HttpMethod.Delete, path, null);
+ }
+
+ public async Task PatchTaskAsync(string path, T data)
+ {
+ return await ProcessRequest(new HttpMethod("PATCH"), path, data);
+ }
+
+ public async Task Listen(string path)
+ {
+ var uri = PrepareUri(path);
+
+ var request = new HttpRequestMessage(HttpMethod.Get, uri);
+ request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/event-stream"));
+
+ var response = await _client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
+ response.EnsureSuccessStatusCode();
+
+ return response;
+ }
+
+ private Task ProcessRequest(HttpMethod method, string path, object payload)
+ {
+ try
+ {
+ var uri = PrepareUri(path);
+
+ var request = new HttpRequestMessage(method, uri);
+
+ if (payload != null)
+ {
+ var json = JsonConvert.SerializeObject(payload);
+ request.Content = new StringContent(json);
+ }
+
+ return _client.SendAsync(request, HttpCompletionOption.ResponseContentRead);
+ }
+ catch (Exception ex)
+ {
+ throw new FirebaseException(
+ string.Format("An error occured while execute request. Path : {0} , Method : {1}", path, method), ex);
+ }
+ }
+
+ private Uri PrepareUri(string path)
+ {
+ var authToken = !string.IsNullOrWhiteSpace(_config.AuthSecret)
+ ? string.Format("{0}.json?auth={1}", path, _config.AuthSecret)
+ : string.Format("{0}.json", path);
+
+ var url = string.Format("{0}{1}", _config.BasePath, authToken);
+
+ return new Uri(url);
+ }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp/Interfaces/IFirebaseClient.cs b/FireSharp/Interfaces/IFirebaseClient.cs
new file mode 100644
index 0000000..4cddeb8
--- /dev/null
+++ b/FireSharp/Interfaces/IFirebaseClient.cs
@@ -0,0 +1,31 @@
+using System.Threading.Tasks;
+using FireSharp.EventStreaming;
+using FireSharp.Response;
+
+namespace FireSharp.Interfaces
+{
+ public interface IFirebaseClient
+ {
+ FirebaseResponse Get(string path);
+ SetResponse Set(string path, T data);
+ PushResponse Push(string path, T data);
+ DeleteResponse Delete(string path);
+ FirebaseResponse Update(string path, T data);
+
+ FirebaseResponse Listen(string path,
+ ValueAddedEventHandler added = null,
+ ValueChangedEventHandler changed = null,
+ ValueRemovedEventHandler removed = null);
+
+ Task GetTaskAsync(string path);
+ Task SetTaskAsync(string path, T data);
+ Task PushTaskAsync(string path, T data);
+ Task DeleteTaskAsync(string path);
+ Task UpdateTaskAsync(string path, T data);
+
+ Task ListenAsync(string path,
+ ValueAddedEventHandler added = null,
+ ValueChangedEventHandler changed = null,
+ ValueRemovedEventHandler removed = null);
+ }
+}
\ No newline at end of file
diff --git a/FireSharp/Interfaces/IFirebaseRequestManager.cs b/FireSharp/Interfaces/IFirebaseRequestManager.cs
new file mode 100644
index 0000000..aee839c
--- /dev/null
+++ b/FireSharp/Interfaces/IFirebaseRequestManager.cs
@@ -0,0 +1,20 @@
+using System.Net.Http;
+using System.Threading.Tasks;
+
+namespace FireSharp.Interfaces
+{
+ internal interface IFirebaseRequestManager
+ {
+ Task Get(string path);
+ Task Put(string path, T data);
+ Task Post(string path, T data);
+ Task Delete(string path);
+ Task Patch(string path, T data);
+ Task Listen(string path);
+ Task GetTaskAsync(string path);
+ Task PutTaskAsync(string path, T data);
+ Task PostTaskAsync(string path, T data);
+ Task DeleteTaskAsync(string path);
+ Task PatchTaskAsync(string path, T data);
+ }
+}
\ No newline at end of file
diff --git a/FireSharp/Properties/AssemblyInfo.cs b/FireSharp/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..7a2e885
--- /dev/null
+++ b/FireSharp/Properties/AssemblyInfo.cs
@@ -0,0 +1,42 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("FireSharp")]
+[assembly: AssemblyDescription(".Net wrapper for Firebase backend API")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("FireSharp")]
+[assembly: AssemblyCopyright("Copyright © 2013")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+
+[assembly: Guid("2bdbf3c7-1dfe-4484-b328-35960b586953")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+
+[assembly: AssemblyVersion("1.1.0")]
+[assembly: AssemblyFileVersion("1.1.0")]
+[assembly: InternalsVisibleTo("FireSharp.Tests")]
+[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
\ No newline at end of file
diff --git a/FireSharp/Response/DeleteResponse.cs b/FireSharp/Response/DeleteResponse.cs
new file mode 100644
index 0000000..dcd07b0
--- /dev/null
+++ b/FireSharp/Response/DeleteResponse.cs
@@ -0,0 +1,26 @@
+using System.Net;
+using System.Net.Http;
+
+namespace FireSharp.Response
+{
+ public class DeleteResponse : FirebaseResponse
+ {
+ public DeleteResponse(HttpResponseMessage httpResponse)
+ : base(httpResponse)
+ {
+ }
+
+ public DeleteResponse()
+ {
+ }
+
+ public bool Success
+ {
+ get
+ {
+ return HttpResponse.StatusCode == HttpStatusCode.OK ||
+ HttpResponse.StatusCode == HttpStatusCode.NoContent;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp/Response/FirebaseResponse.cs b/FireSharp/Response/FirebaseResponse.cs
new file mode 100644
index 0000000..de542e2
--- /dev/null
+++ b/FireSharp/Response/FirebaseResponse.cs
@@ -0,0 +1,163 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+using FireSharp.EventStreaming;
+using FireSharp.Exceptions;
+using FireSharp.Extensions;
+using Newtonsoft.Json;
+
+namespace FireSharp.Response
+{
+ public class FirebaseResponse
+ {
+ protected HttpResponseMessage HttpResponse;
+ private readonly TemporaryCache _cache;
+ private readonly CancellationTokenSource _cancel;
+ private readonly Task _pollingTask;
+
+ public FirebaseResponse(HttpResponseMessage httpResponse)
+ {
+ HttpResponse = httpResponse;
+ }
+
+ public FirebaseResponse()
+ {
+ HttpResponse = null;
+ }
+
+ internal FirebaseResponse(HttpResponseMessage httpResponse,
+ ValueAddedEventHandler added = null,
+ ValueChangedEventHandler changed = null,
+ ValueRemovedEventHandler removed = null)
+ {
+ _cancel = new CancellationTokenSource();
+
+ _cache = new TemporaryCache();
+
+ if (added != null)
+ {
+ _cache.Added += added;
+ }
+ if (changed != null)
+ {
+ _cache.Changed += changed;
+ }
+ if (removed != null)
+ {
+ _cache.Removed += removed;
+ }
+
+ _pollingTask = ReadLoop(httpResponse, _cancel.Token);
+ }
+
+ public string Body
+ {
+ get { return HttpResponse.Content.ReadAsStringAsync().Result; }
+ }
+
+ public FirebaseException Exception { get; set; }
+
+ public virtual T ResultAs()
+ {
+ return HttpResponse.ReadAs();
+ }
+
+ public void Cancel()
+ {
+ _cancel.Cancel();
+ }
+
+ private async Task ReadLoop(HttpResponseMessage response, CancellationToken cancellationToken)
+ {
+ using (response)
+ using (var content = await response.Content.ReadAsStreamAsync())
+ using (var sr = new StreamReader(content))
+ {
+ string eventName = null;
+
+ while (true)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ // TODO: it really sucks that this does not take a cancellation token
+ var read = await sr.ReadLineAsync();
+
+ Debug.WriteLine(read);
+
+ if (read.StartsWith("event: "))
+ {
+ eventName = read.Substring(7);
+ continue;
+ }
+
+ if (read.StartsWith("data: "))
+ {
+ if (string.IsNullOrEmpty(eventName))
+ {
+ throw new InvalidOperationException(
+ "Payload data was received but an event did not preceed it.");
+ }
+
+ Update(eventName, read.Substring(6));
+ }
+
+ // start over
+ eventName = null;
+ }
+ }
+ }
+
+ private void Update(string eventName, string p)
+ {
+ switch (eventName)
+ {
+ case "put":
+ case "patch":
+ using (var r = new StringReader(p))
+ using (JsonReader reader = new JsonTextReader(r))
+ {
+ ReadToNamedPropertyValue(reader, "path");
+ reader.Read();
+ var path = reader.Value.ToString();
+
+ if (eventName == "put")
+ {
+ _cache.Replace(path, ReadToNamedPropertyValue(reader, "data"));
+ }
+ else
+ {
+ _cache.Update(path, ReadToNamedPropertyValue(reader, "data"));
+ }
+ }
+ break;
+ }
+ }
+
+ private JsonReader ReadToNamedPropertyValue(JsonReader reader, string property)
+ {
+ while (reader.Read() && reader.TokenType != JsonToken.PropertyName)
+ {
+ // skip the property
+ }
+
+ var prop = reader.Value.ToString();
+ if (property != prop)
+ {
+ throw new InvalidOperationException("Error parsing response. Expected json property named: " + property);
+ }
+
+ return reader;
+ }
+
+ public void Dispose()
+ {
+ Cancel();
+ using (_cancel)
+ {
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp/Response/PushResponse.cs b/FireSharp/Response/PushResponse.cs
new file mode 100644
index 0000000..09f2f13
--- /dev/null
+++ b/FireSharp/Response/PushResponse.cs
@@ -0,0 +1,26 @@
+using System.Net.Http;
+
+namespace FireSharp.Response
+{
+ public class PushResponse : FirebaseResponse
+ {
+ public PushResponse(HttpResponseMessage httpResponse)
+ : base(httpResponse)
+ {
+ }
+
+ public PushResponse()
+ {
+ }
+
+ public PushResult Result
+ {
+ get { return ResultAs(); }
+ }
+ }
+
+ public class PushResult
+ {
+ public string Name { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp/Response/SetResponse.cs b/FireSharp/Response/SetResponse.cs
new file mode 100644
index 0000000..b391f22
--- /dev/null
+++ b/FireSharp/Response/SetResponse.cs
@@ -0,0 +1,16 @@
+using System.Net.Http;
+
+namespace FireSharp.Response
+{
+ public class SetResponse : FirebaseResponse
+ {
+ public SetResponse(HttpResponseMessage httpResponse)
+ : base(httpResponse)
+ {
+ }
+
+ public SetResponse()
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/FireSharp/packages.config b/FireSharp/packages.config
new file mode 100644
index 0000000..04d7a82
--- /dev/null
+++ b/FireSharp/packages.config
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build.sh b/build.sh
new file mode 100644
index 0000000..73c8de1
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,76 @@
+build() {
+ mono .nuget/NuGet.exe install NUnit.Runners
+ mono .nuget/NuGet.exe restore FireSharp.sln
+
+ xbuild /t:Rebuild FireSharp.sln
+
+ if [[ $? != 0 ]] ; then
+ build_failed
+ else
+ build_succeeded
+ fi
+}
+
+build_failed() {
+ print_status "BUILD FAILED"
+ return 1
+}
+
+build_succeeded() {
+ print_status "BUILD SUCCEEDED"
+ run_tests
+}
+
+run_tests() {
+ print_status "RUNNING TESTS"
+
+ if [ -z "$USE_SYSTEM_NUNIT_CONSOLE" ]; then
+ RUNNER_PATH="packages/NUnit.Runners.2.6.4/tools"
+ else
+ RUNNER_PATH="/usr/lib/nunit"
+ fi
+ NUNIT_ADDT_ARGS=""
+
+ if [[ $NUNIT_RUN != "" ]]; then
+ NUNIT_RUN_CSV=""
+ for RUN in $NUNIT_RUN
+ do
+ NUNIT_RUN_CSV="$NUNIT_RUN_CSV,$RUN"
+ done
+ NUNIT_ADDT_ARGS="$NUNIT_ADDT_ARGS -run $NUNIT_RUN_CSV"
+ fi
+
+ mono ${RUNNER_PATH}/nunit-console.exe \
+ FireSharp.Tests/bin/Debug/FireSharp.Tests.dll \
+ $NUNIT_ADDT_ARGS
+
+ local test_result=$?
+
+ if [[ "${test_result}" != 0 ]] ; then
+ tests_failed
+ else
+ tests_passed
+ fi
+}
+
+tests_failed() {
+ print_status "TESTS FAILED"
+ return 2
+}
+
+tests_passed() {
+ print_status "TESTS PASSED"
+}
+
+print_status() {
+ echo ""
+ echo "*** $1 ***"
+ echo ""
+}
+
+NUNIT_RUN=$*
+build
+
+EXIT_CODE=$?
+echo "Exit [$EXIT_CODE]"
+exit $EXIT_CODE
\ No newline at end of file
diff --git a/circle.yml b/circle.yml
new file mode 100644
index 0000000..d63aee8
--- /dev/null
+++ b/circle.yml
@@ -0,0 +1,19 @@
+machine:
+ environment:
+ USE_SYSTEM_NUNIT_CONSOLE: 1
+
+dependencies:
+ pre:
+ - sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
+ - echo "deb http://download.mono-project.com/repo/debian wheezy main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list
+ - sudo apt-get update
+ - sudo apt-get install mono-devel
+ - sudo apt-get install mono-complete
+ - sudo apt-get install referenceassemblies-pcl
+ - mozroots --import --sync
+ - mono .nuget/NuGet.exe restore FireSharp.sln
+ - sudo chmod +x build.sh
+
+test:
+ override:
+ - ./build.sh
\ No newline at end of file