diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..163eb75 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*.cr] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0bbd4a9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +/docs/ +/lib/ +/bin/ +/.shards/ +*.dwarf + +# Libraries don't need dependency lock +# Dependencies will be locked in applications that use them +/shard.lock diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..765f0e9 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,6 @@ +language: crystal + +# Uncomment the following if you'd like Travis to run specs and check code formatting +# script: +# - crystal spec +# - crystal tool format --check diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8637df9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2021 creadone + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..1c3ba62 --- /dev/null +++ b/README.md @@ -0,0 +1,51 @@ +# Cocoon + +Helper for wrap third-party API calls + +## Installation + +1. Add the dependency to your `shard.yml`: + +```yaml +dependencies: + cocoon: + github: creadone/cocoon +``` + +2. Run `shards install` + +## Usage + +```crystal +require "json" +require "cocoon" +require "http/client" + +alias Response = HTTP::Client::Response +cocoon = Cocoon::Wrapper(Response).new + +channel = cocoon.wrap do + headers = HTTP::Headers{ "Accept" => "application/vnd.github.v3+json" } + HTTP::Client.get "https://api.github.com/networks/crystal-lang/crystal/events", headers: headers +end + +if resp = channel.receive + if resp.is_a?(Response) && resp.success? + pp JSON.parse(resp.body) + elsif resp.is_a?(Exception) + # log it and raise resp + end +end +``` + +## Contributing + +1. Fork it () +2. Create your feature branch (`git checkout -b my-new-feature`) +3. Commit your changes (`git commit -am 'Add some feature'`) +4. Push to the branch (`git push origin my-new-feature`) +5. Create a new Pull Request + +## Contributors + +- [creadone](https://github.com/creadone) - creator and maintainer diff --git a/example/base.cr b/example/base.cr new file mode 100644 index 0000000..0414672 --- /dev/null +++ b/example/base.cr @@ -0,0 +1,19 @@ +require "json" +require "../src/cocoon" +require "http/client" + +alias Response = HTTP::Client::Response +cocoon = Cocoon::Wrapper(Response).new + +channel = cocoon.wrap do + headers = HTTP::Headers{ "Accept" => "application/vnd.github.v3+json" } + HTTP::Client.get "https://api.github.com/networks/crystal-lang/crystal/events", headers: headers +end + +if resp = channel.receive + if resp.is_a?(Response) && resp.success? + pp JSON.parse(resp.body) + elsif resp.is_a?(Exception) + # log it and raise resp + end +end \ No newline at end of file diff --git a/shard.yml b/shard.yml new file mode 100644 index 0000000..d59780c --- /dev/null +++ b/shard.yml @@ -0,0 +1,12 @@ +name: cocoon +version: 0.1.0 + +authors: + - Sergey Fedorov + +description: | + Helper for wrap third-party API calls + +crystal: 0.36.1 + +license: MIT diff --git a/spec/cocoon_spec.cr b/spec/cocoon_spec.cr new file mode 100644 index 0000000..e95d4cc --- /dev/null +++ b/spec/cocoon_spec.cr @@ -0,0 +1,13 @@ +require "./spec_helper" + +describe Cocoon do + describe "Wrapper" do + cocoon = Cocoon::Wrapper(Int32).new + + it "should return sum of integers" do + if result = cocoon.wrap{ 1 + 3 }.receive + result.should eq(4) + end + end + end +end diff --git a/spec/spec_helper.cr b/spec/spec_helper.cr new file mode 100644 index 0000000..cb3801d --- /dev/null +++ b/spec/spec_helper.cr @@ -0,0 +1,2 @@ +require "spec" +require "../src/cocoon" diff --git a/src/cocoon.cr b/src/cocoon.cr new file mode 100644 index 0000000..d62ef93 --- /dev/null +++ b/src/cocoon.cr @@ -0,0 +1,31 @@ +require "http/client" + +module Cocoon + VERSION = `shards version` + + class Wrapper(T) + def initialize( + @result = Channel(T | Exception).new, + @output = Channel(T | Exception).new + ) + end + + def wrap(&block : -> T) forall T + spawn(name: "executor") do + @result.send block.call + rescue ex + @result.send ex + end + + Fiber.yield + + spawn(name: "receiver") do + select + when data = @result.receive + @output.send data + end + end + @output + end + end +end