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","
"," "," "," "," ","",""," ","
","
",""," "," "," ","","
"," Sign up"," Sign in","
",""," ",""," ","","
","
","","","","
","
","
"," ","
","
","
"," ","","","

"," "," ziyasal/InfluxDB.Net",""," "," \"\""," ","","

","
","
","","
","
","
"," ","","","
"," "," ","
","

HTTPS clone URL

","
"," "," "," "," ","
","
",""," ","
","

Subversion checkout URL

","
"," "," "," "," ","
","
","","","","

You can clone with"," HTTPS or Subversion."," "," "," ","

","","",""," "," "," Download ZIP"," ","
","
","","
"," ","","Permalink","","","","
"," ","
"," "," "," branch:"," master"," ","","
","","
","
"," Switch branches/tags"," ","
","","
","
"," ","
","
"," ","
","
","","
","","
","","","
"," "," master","
","
","","
Nothing to show
","
","","
","
","","","
","","
Nothing to show
","
","","
","
","
","","
"," "," "," "," ","
","","
"," InfluxDB.Net/build.sh","
","
","","","
","
"," \"Ziya"," ziyasal"," "," ","
","","
","

"," "," 1"," contributor"," ","

"," ","
","
","

Users who have contributed to this file

"," ","
","
","","
","
","
","
"," 77 lines (61 sloc)"," "," 1.365 kb","
","
","
"," Raw"," Blame"," History","
","",""," ",""," "," "," ","
","
"," ","","
"," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," ","
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
","","
","","
","
","","Jump to Line","
","
"," "," ","
","
","","
","","
","
","
","
","","","
","","
","
"," ",""," "," "," ",""," ","
","
","","","
","
","
"," ","
","
","
","
","
","
"," "," "," "," "," "," ","
","
","","","","
"," "," "," 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","
"," "," "," "," ","",""," ","
","
",""," "," "," ","","
"," Sign up"," Sign in","
",""," ",""," ","","
","
","","","","
","
","
"," ","
","
","
"," ","","","

"," "," ziyasal/InfluxDB.Net",""," "," \"\""," ","","

","
","
","","
","
","
"," ","","","
"," "," ","
","

HTTPS clone URL

","
"," "," "," "," ","
","
",""," ","
","

Subversion checkout URL

","
"," "," "," "," ","
","
","","","","

You can clone with"," HTTPS or Subversion."," "," "," ","

","","",""," "," "," Download ZIP"," ","
","
","","
"," ","","Permalink","","","","
"," ","
"," "," "," branch:"," master"," ","","
","","
","
"," Switch branches/tags"," ","
","","
","
"," ","
","
"," ","
","
","","
","","
","","","
"," "," master","
","
","","
Nothing to show
","
","","
","
","","","
","","
Nothing to show
","
","","
","
","
","","
"," "," "," "," ","
","","
"," InfluxDB.Net/circle.yml","
","
","","","
","
"," \"Ziya"," ziyasal"," "," ","
","","
","

"," "," 1"," contributor"," ","

"," ","
","
","

Users who have contributed to this file

"," ","
","
","","
","
","
","
"," 23 lines (20 sloc)"," "," 0.774 kb","
","
","
"," Raw"," Blame"," History","
","",""," ",""," "," "," ","
","
"," ","","
"," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," ","
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
","","
","","
","
","","Jump to Line","
","
"," "," ","
","
","","
","","
","
","
","
","","","
","","
","
"," ",""," "," "," ",""," ","
","
","","","
","
","
"," ","
","
","
","
","
","
"," "," "," "," "," "," ","
","
","","","","
"," "," "," 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