startback 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0a7f631f93683bc9a9fe0705fc5e3f7df55fa782
4
+ data.tar.gz: 6335d0ff1b733355c96116ce19f9094adea45694
5
+ SHA512:
6
+ metadata.gz: b1bec4146b344fac7d8ef51b130e149fb823e6d10ab5a3050be9165c877585f8dcf38092fa2548c884a8974d97868f0f161d7871908da0117af06fc851e5aaa1
7
+ data.tar.gz: f7482b4b5446cc1557841302cade907c4b597ff704b88ff8017ebf652a92809cf44d5ca24d9c59d0af63dd68b579eed30afd71b5deebc516b0ae94214f6e2cb2
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "https://rubygems.org"
2
+ gemspec
data/README.md ADDED
@@ -0,0 +1,13 @@
1
+ # Startback - Got Your Ruby Back
2
+
3
+ Yet another ruby framework, I'm afraid. Here, we srongly seperate between:
4
+
5
+ 1. the web layer, in charge of a quality HTTP handling
6
+ 2. the operations layer, in charge of the high-level software operations
7
+ 3. the database layer, abstracted using the Relations As First Class Citizen pattern
8
+
9
+ Currently,
10
+
11
+ 1. is handled using extra support on top of Sinatra
12
+ 2. is handled using Startback specific classes
13
+ 3. is handled using Bmg
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ $:.unshift File.expand_path('../lib', __FILE__)
2
+
3
+ def shell(*cmds)
4
+ cmd = cmds.join("\n")
5
+ puts cmd
6
+ system cmd
7
+ end
8
+
9
+ #
10
+ # Install all tasks found in tasks folder
11
+ #
12
+ # See .rake files there for complete documentation.
13
+ #
14
+ Dir["tasks/*.rake"].each do |taskfile|
15
+ load taskfile
16
+ end
17
+
18
+ task :default => :test
data/lib/startback.rb ADDED
@@ -0,0 +1,37 @@
1
+ require 'sinatra'
2
+ require 'rack/robustness'
3
+ require 'finitio'
4
+ require 'logger'
5
+ # Provides a reusable backend framework for backend components written
6
+ # in ruby.
7
+ #
8
+ # The framework installs conventions regarding:
9
+ #
10
+ # - The exposition of web service APIs (Framework::Api, on top of Sinatra)
11
+ # - Operations (Framework::Operation)
12
+ # - Error handling (Framework::Errors) and their handling in web APIs
13
+ # (based on Rack::Robustness)
14
+ # - General code support (Framework::Support modules & classes).
15
+ #
16
+ # Please refer to the documentation of those main abstractions for details.
17
+ #
18
+ module Startback
19
+
20
+ # Simply checks that a path exists of raise an error
21
+ def self._!(path)
22
+ Path(path).tap do |p|
23
+ raise "Missing #{p.basename}." unless p.exists?
24
+ end
25
+ end
26
+
27
+ require_relative 'startback/ext'
28
+ require_relative 'startback/errors'
29
+ require_relative 'startback/support'
30
+ require_relative 'startback/context'
31
+ require_relative 'startback/operation'
32
+ require_relative 'startback/web'
33
+
34
+ # Logger instance to use for the application
35
+ LOGGER = ::Startback::Support::Logger.new
36
+
37
+ end # module Startback
@@ -0,0 +1,16 @@
1
+ module Startback
2
+ #
3
+ # Defines an execution context for Startback applications.
4
+ #
5
+ # This class is aimed at being subclassed for application required
6
+ # extension.
7
+ #
8
+ # In web application, an instance of a context can be set on the Rack
9
+ # environment, using Context::Middleware.
10
+ #
11
+ class Context
12
+ attr_accessor :original_rack_env
13
+
14
+ end # class Context
15
+ end # module Startback
16
+ require_relative 'context/middleware'
@@ -0,0 +1,53 @@
1
+ module Startback
2
+ class Context
3
+ #
4
+ # Rack middleware that installs a particular context instance
5
+ # on the Rack environment.
6
+ #
7
+ # Examples:
8
+ #
9
+ # # Use the default context class
10
+ # Rack::Builder.new do
11
+ # use Startback::Context::Middleware
12
+ #
13
+ # run ->(env){
14
+ # ctx = env[Startback::Context::Middleware::RACK_ENV_KEY]
15
+ # ctx.is_a?(Startback::Context) # => true
16
+ # }
17
+ # end
18
+ #
19
+ # # Use a user defined context class
20
+ # Rack::Builder.new do
21
+ # use Startback::Context::Middleware, context_class: MyContextClass
22
+ #
23
+ # run ->(env){
24
+ # ctx = env[Startback::Context::Middleware::RACK_ENV_KEY]
25
+ # ctx.is_a?(MyContextClass) # => true (your subclass)
26
+ # ctx.is_a?(Startback::Context) # => true (required!)
27
+ # }
28
+ # end
29
+ #
30
+ class Middleware
31
+
32
+ RACK_ENV_KEY = 'SAMBACK_CONTEXT'
33
+
34
+ DEFAULT_OPTIONS = {
35
+ context_class: Context
36
+ }
37
+
38
+ def initialize(app, options = {})
39
+ @app = app
40
+ @options = DEFAULT_OPTIONS.merge(options || {})
41
+ end
42
+ attr_reader :options
43
+
44
+ def call(env)
45
+ env[RACK_ENV_KEY] ||= options[:context_class].new.tap{|c|
46
+ c.original_rack_env = env.dup
47
+ }
48
+ @app.call(env)
49
+ end
50
+
51
+ end # class Middleware
52
+ end # class Context
53
+ end # module Startback
@@ -0,0 +1,91 @@
1
+ module Startback
2
+ module Errors
3
+
4
+ class Error < StandardError
5
+ class << self
6
+
7
+ def status(code = nil)
8
+ @code = code || @code
9
+ end
10
+
11
+ def keep_error(keep = nil)
12
+ @keep_error = keep unless keep.nil?
13
+ @keep_error
14
+ end
15
+ end
16
+
17
+ def message
18
+ msg = super
19
+ return msg unless msg == self.class.name
20
+ parts = self.class.name.split('::').last.gsub(/[A-Z]/){|x|
21
+ " #{x.downcase}"
22
+ }.strip.split(" ")
23
+ parts = parts[0...-1] unless self.class.keep_error
24
+ parts.join(" ").capitalize
25
+ end
26
+ end
27
+
28
+ class BadRequestError < Error
29
+ status 400
30
+ end
31
+
32
+ class UnauthorizedError < BadRequestError
33
+ status 401
34
+ end
35
+
36
+ class ForbiddenError < BadRequestError
37
+ status 403
38
+ end
39
+
40
+ class NotFoundError < BadRequestError
41
+ status 404
42
+ end
43
+
44
+ class MethodNotAllowedError < BadRequestError
45
+ status 405
46
+ end
47
+
48
+ class NotAcceptableError < BadRequestError
49
+ status 406
50
+ end
51
+
52
+ class ConflictError < BadRequestError
53
+ status 409
54
+ end
55
+
56
+ class GoneError < BadRequestError
57
+ status 410
58
+ end
59
+
60
+ class PreconditionFailedError < BadRequestError
61
+ status 412
62
+ end
63
+
64
+ class UnsupportedMediaTypeError < BadRequestError
65
+ status 415
66
+ end
67
+
68
+ class ExpectationFailedError < BadRequestError
69
+ status 417
70
+ end
71
+
72
+ class LockedError < BadRequestError
73
+ status 423
74
+ end
75
+
76
+ class PreconditionRequiredError < BadRequestError
77
+ status 428
78
+ end
79
+
80
+ class InternalServerError < Error
81
+ status 500
82
+ keep_error(true)
83
+ end
84
+
85
+ class NotImplementedError < InternalServerError
86
+ status 501
87
+ end
88
+
89
+ end # module Errors
90
+ include Errors
91
+ end # module Klaro
@@ -0,0 +1,2 @@
1
+ require_relative 'ext/date_time'
2
+ require_relative 'ext/time'
@@ -0,0 +1,9 @@
1
+ class DateTime
2
+
3
+ # Makes sure that DateTime are exported with ISO8601
4
+ # conventions when using to_json and to_csv
5
+ def to_s
6
+ iso8601
7
+ end
8
+
9
+ end
@@ -0,0 +1,9 @@
1
+ class Time
2
+
3
+ # Makes sure that Time are exported with ISO8601
4
+ # conventions when using to_json and to_csv
5
+ def to_s
6
+ iso8601
7
+ end
8
+
9
+ end
@@ -0,0 +1,31 @@
1
+ module Startback
2
+ class Operation
3
+ include Errors
4
+
5
+ attr_accessor :world
6
+
7
+ protected :world=
8
+
9
+ def bind(world)
10
+ return self unless world
11
+ dup.tap{|op|
12
+ op.world = world
13
+ }
14
+ end
15
+
16
+ def method_missing(name, *args, &bl)
17
+ return super unless args.empty? and bl.nil?
18
+ return super unless world
19
+ world.fetch(name){ super }
20
+ end
21
+
22
+ protected
23
+
24
+ def run(operation)
25
+ operation.bind(self.world).call
26
+ end
27
+
28
+ end # class Operation
29
+ end # module Startback
30
+ require_relative 'operation/error_operation'
31
+ require_relative 'operation/multi_operation'
@@ -0,0 +1,19 @@
1
+ module Startback
2
+ class Operation
3
+ class ErrorOperation < Operation
4
+
5
+ def initialize(details)
6
+ @details = details
7
+ end
8
+ attr_reader :details
9
+
10
+ def call
11
+ end
12
+
13
+ def bind(world)
14
+ self
15
+ end
16
+
17
+ end # class ErrorOperation
18
+ end # class Operation
19
+ end # module Startback
@@ -0,0 +1,28 @@
1
+ module Startback
2
+ class Operation
3
+ class MultiOperation
4
+
5
+ def initialize(ops = [])
6
+ @ops = ops
7
+ end
8
+ attr_reader :ops
9
+
10
+ def size
11
+ ops.size
12
+ end
13
+
14
+ def +(other)
15
+ MultiOperation.new(@ops + Array(other))
16
+ end
17
+
18
+ def bind(world)
19
+ MultiOperation.new(ops.map{|op| op.bind(world) })
20
+ end
21
+
22
+ def call
23
+ ops.map{|op| op.call }
24
+ end
25
+
26
+ end # class MultiOperation
27
+ end # class Operation
28
+ end # module Startback
@@ -0,0 +1,10 @@
1
+ module Startback
2
+ module Support
3
+
4
+ def logger
5
+ Startback::LOGGER
6
+ end
7
+
8
+ end # module Support
9
+ end # module Startback
10
+ require_relative 'support/logger'
@@ -0,0 +1,34 @@
1
+ module Startback
2
+ module Support
3
+ #
4
+ # A Logger extension that sends info and debug messages to STDOUT
5
+ # and other messages to STDERR. This is not configurable.
6
+ #
7
+ class Logger < ::Logger
8
+
9
+ def initialize
10
+ super(STDOUT)
11
+ @err_logger = ::Logger.new(STDERR)
12
+ end
13
+
14
+ def self.level=(level)
15
+ super.tap{
16
+ @err_logger.level = level
17
+ }
18
+ end
19
+
20
+ def warn(*args, &bl)
21
+ @err_logger.warn(*args, &bl)
22
+ end
23
+
24
+ def error(*args, &bl)
25
+ @err_logger.error(*args, &bl)
26
+ end
27
+
28
+ def fatal(*args, &bl)
29
+ @err_logger.fatal(*args, &bl)
30
+ end
31
+
32
+ end # class Logger
33
+ end # module Support
34
+ end # module Startback
@@ -0,0 +1,8 @@
1
+ module Startback
2
+ module Version
3
+ MAJOR = 0
4
+ MINOR = 2
5
+ TINY = 0
6
+ end
7
+ VERSION = "#{Version::MAJOR}.#{Version::MINOR}.#{Version::TINY}"
8
+ end
@@ -0,0 +1,4 @@
1
+ require_relative 'web/shield'
2
+ require_relative 'web/catch_all'
3
+ require_relative 'web/health_check'
4
+ require_relative 'web/api'
@@ -0,0 +1,74 @@
1
+ module Startback
2
+ module Web
3
+ class Api < Sinatra::Base
4
+ include Support
5
+ include Errors
6
+
7
+ set :raise_errors, true
8
+ set :show_exceptions, false
9
+
10
+ protected
11
+
12
+ ###
13
+ ### Facade over context
14
+ ###
15
+
16
+ def context
17
+ env[Startback::Context::Middleware::RACK_ENV_KEY]
18
+ end
19
+
20
+ ###
21
+ ### Facade over third party tools
22
+ ###
23
+
24
+ def run(operation)
25
+ operation
26
+ .bind({ context: context })
27
+ .call
28
+ end
29
+
30
+ ###
31
+ ### About the body / input
32
+ ###
33
+
34
+ def loaded_body
35
+ @loaded_body ||= case ctype = request.content_type
36
+ when /json/
37
+ json_body
38
+ when /multipart\/form-data/
39
+ file_body params[:file], Path(file[:filename]).extname
40
+ else
41
+ unsupported_content_type(ctype)
42
+ end
43
+ end
44
+
45
+ def json_body(body = request.body.read)
46
+ JSON.load(body)
47
+ end
48
+
49
+ def file_body(file, ctype)
50
+ raise UnsupportedMediaTypeError, "Unable to use `#{ctype}` as input data"
51
+ end
52
+
53
+ ###
54
+ ### Various reusable responses
55
+ ###
56
+
57
+ def serve_nothing
58
+ [ 204, {}, [] ]
59
+ end
60
+
61
+ def serve(entity_description, entity, ct = :json)
62
+ if entity.nil?
63
+ status 404
64
+ content_type :json
65
+ { description: "#{entity_description} not found" }.to_json
66
+ else
67
+ content_type ct
68
+ entity.to_json
69
+ end
70
+ end
71
+
72
+ end # class Api
73
+ end # module Web
74
+ end # module Startback
@@ -0,0 +1,36 @@
1
+ module Startback
2
+ module Web
3
+ #
4
+ # This Rack middleware catches all exceptions that are raised by sublayers
5
+ # in the Rack chain. It converts them to correct 500 Errors, with a generic
6
+ # exception message encoded in json.
7
+ #
8
+ # This class aims at being used as top level of a Rack chain. It is not
9
+ # aimed at being subclassed.
10
+ #
11
+ # Examples:
12
+ #
13
+ # Rack::Builder.new do
14
+ # use Startback::Web::CatchAll
15
+ # end
16
+ #
17
+ class CatchAll < Rack::Robustness
18
+ include Errors
19
+
20
+ FATAL_ERROR = {
21
+ code: "Gybr::Errors::ServerError",
22
+ description: "An error occured, sorry"
23
+ }.to_json
24
+
25
+ self.catch_all
26
+ self.status 500
27
+ self.content_type 'application/json'
28
+ self.body FATAL_ERROR.to_json
29
+
30
+ self.ensure(true) do |ex|
31
+ Startback::LOGGER.fatal(ex)
32
+ end
33
+
34
+ end # class CatchAll
35
+ end # class Web
36
+ end # module Startback
@@ -0,0 +1,49 @@
1
+ module Startback
2
+ module Web
3
+ #
4
+ # Can be used to easily implement a HealthCheck web service inside a Startback
5
+ # application.
6
+ #
7
+ # Examples:
8
+ #
9
+ # # Returns a 204 with no body
10
+ # run Startback::Web::HealthCheck.new
11
+ #
12
+ # # Returns a 204 with no body
13
+ # run Startback::Web::HealthCheck.new { nil }
14
+ #
15
+ # # Returns a 200 with Ok in plain text
16
+ # run Startback::Web::HealthCheck.new { "Ok" }
17
+ #
18
+ # # Re-raises the exception
19
+ # run Startback::Web::HealthCheck.new { raise "Something bad" }
20
+ #
21
+ # Please note that this rack app is not 100% Rack compliant, since it raises
22
+ # any error that the block itself raises. This class aims at being backed up
23
+ # by a Shield and/or CatchAll middleware.
24
+ #
25
+ # This class is not aimed at being subclassed.
26
+ #
27
+ class HealthCheck
28
+
29
+ def initialize(&bl)
30
+ @checker = bl
31
+ end
32
+
33
+ def call(env)
34
+ if debug_msg = check!(env)
35
+ [ 200, { "Content-Type" => "text/plain" }, debug_msg ]
36
+ else
37
+ [ 204, {}, "" ]
38
+ end
39
+ end
40
+
41
+ protected
42
+
43
+ def check!(env)
44
+ @checker.call if @checker
45
+ end
46
+
47
+ end # class HealthCheck
48
+ end # module Web
49
+ end # module Startback
@@ -0,0 +1,40 @@
1
+ module Startback
2
+ module Web
3
+ #
4
+ # This Rack middleware catches all known exceptions raised by sublayers
5
+ # in the Rack chain. Those exceptions are converted to proper HTTP error
6
+ # codes and friendly error messages encoded in json.
7
+ #
8
+ # Please check the Errors module about status codes used for each Startback
9
+ # error.
10
+ #
11
+ # This class aims at being used as top level of a Rack chain.
12
+ #
13
+ # Examples:
14
+ #
15
+ # Rack::Builder.new do
16
+ # use Startback::Web::Shield
17
+ # end
18
+ #
19
+ class Shield < Rack::Robustness
20
+ include Errors
21
+
22
+ self.no_catch_all
23
+ self.content_type 'application/json'
24
+
25
+ # Decoding errors from json and csv are considered user's fault
26
+ self.on(Finitio::TypeError) { 400 }
27
+
28
+ # Various other codes for the framework specific error classes
29
+ self.on(Startback::Errors::Error) {|ex| ex.class.status }
30
+
31
+ # A bit of logic to choose the best error message for the user
32
+ # according to the error class
33
+ self.body{|ex|
34
+ ex = ex.root_cause if ex.is_a?(Finitio::TypeError)
35
+ { code: ex.class.name, description: ex.message }.to_json
36
+ }
37
+
38
+ end # class Shield
39
+ end # module Web
40
+ end # module Startback
@@ -0,0 +1,10 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'startback'
3
+ require 'rack/test'
4
+
5
+ module SpecHelpers
6
+ end
7
+
8
+ RSpec.configure do |c|
9
+ c.include SpecHelpers
10
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ module Startback
4
+ class Context
5
+
6
+ class MyContextSubClass < Context
7
+ end
8
+
9
+ describe Middleware do
10
+ include Rack::Test::Methods
11
+
12
+ def app
13
+ opts = middleware_options
14
+ Rack::Builder.new do
15
+ use Middleware, opts
16
+ run ->(env){
17
+ ctx = env[Startback::Context::Middleware::RACK_ENV_KEY]
18
+ [200, {}, ctx.class.to_s]
19
+ }
20
+ end
21
+ end
22
+
23
+ context 'when used without option' do
24
+ let(:middleware_options){ nil }
25
+
26
+ it 'sets the default context class' do
27
+ get '/'
28
+ expect(last_response.status).to eql(200)
29
+ expect(last_response.body).to eql("Startback::Context")
30
+ end
31
+ end
32
+
33
+ context 'when specifying the context class' do
34
+ let(:middleware_options){{
35
+ context_class: MyContextSubClass
36
+ }}
37
+
38
+ it 'sets the default context class' do
39
+ get '/'
40
+ expect(last_response.status).to eql(200)
41
+ expect(last_response.body).to eql("Startback::Context::MyContextSubClass")
42
+ end
43
+ end
44
+
45
+ end
46
+ end # module Web
47
+ end # module Startback
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+
3
+ module Startback
4
+ describe Operation do
5
+
6
+ class FooOp < Operation
7
+
8
+ def initialize(foo = :bar)
9
+ @foo = foo
10
+ end
11
+ attr_accessor :foo
12
+
13
+ def call
14
+ @foo
15
+ end
16
+
17
+ end
18
+
19
+ it 'can be bound, which returns a new operation' do
20
+ foo1 = FooOp.new
21
+ foo1.foo = :bar1
22
+
23
+ foo2 = foo1.bind({ db: :bar })
24
+ expect(foo1 == foo2).to eql(false)
25
+ expect(foo2.foo).to eql(:bar1)
26
+
27
+ expect(->(){ foo1.db }).to raise_error(NoMethodError)
28
+ expect(foo2.db).to eql(:bar)
29
+ end
30
+
31
+ end
32
+
33
+ describe Operation::MultiOperation do
34
+
35
+ it 'lets chain with +' do
36
+ mop = Operation::MultiOperation.new
37
+ mop2 = (mop + FooOp.new)
38
+
39
+ expect(mop == mop2).to eql(false)
40
+ expect(mop.size).to eql(0)
41
+ expect(mop2.size).to eql(1)
42
+ end
43
+
44
+ it 'calls and collects the result on call' do
45
+ mop = Operation::MultiOperation.new + FooOp.new(:hello) + FooOp.new(:world)
46
+ expect(mop.call).to eql([:hello, :world])
47
+ end
48
+
49
+ it 'binds every sub operation recursively' do
50
+ mop = Operation::MultiOperation.new + FooOp.new(:hello) + FooOp.new(:world)
51
+ mop2 = mop.bind({requester: :bar})
52
+
53
+ expect(mop == mop2).to eql(false)
54
+ expect(mop2.ops.all?{|op| op.requester == :bar })
55
+ end
56
+
57
+ end
58
+ end # module Startback
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ module Startback
4
+ describe Support do
5
+ include Support
6
+
7
+ end
8
+ end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+
3
+ module Startback
4
+ module Web
5
+ describe HealthCheck do
6
+ include Rack::Test::Methods
7
+
8
+ context 'when used without a block and no failure' do
9
+ def app
10
+ HealthCheck.new
11
+ end
12
+
13
+ it 'returns a 204 when ok' do
14
+ get '/'
15
+ expect(last_response.status).to eql(204)
16
+ expect(last_response.body).to be_empty
17
+ end
18
+ end
19
+
20
+ context 'when used without a block a failure' do
21
+ def app
22
+ app = HealthCheck.new
23
+ def app.check!(env)
24
+ raise "Hello error"
25
+ end
26
+ app
27
+ end
28
+
29
+ it 'raises when ko' do
30
+ expect(->(){ get '/' }).to raise_error("Hello error")
31
+ end
32
+ end
33
+
34
+ context 'when used with a block returning a debug message' do
35
+ def app
36
+ HealthCheck.new{ "Hello world" }
37
+ end
38
+
39
+ it 'returns a 200 with plain text message' do
40
+ get '/'
41
+ expect(last_response.status).to eql(200)
42
+ expect(last_response.body).to eql("Hello world")
43
+ end
44
+ end
45
+
46
+ context 'when used with a block raising an exception' do
47
+ def app
48
+ HealthCheck.new{ raise("Hello error") }
49
+ end
50
+
51
+ it 're-raises it' do
52
+ expect(->(){ get '/' }).to raise_error("Hello error")
53
+ end
54
+ end
55
+
56
+ end
57
+ end # module Web
58
+ end # module Startback
data/tasks/gem.rake ADDED
@@ -0,0 +1,39 @@
1
+ require 'rubygems/package_task'
2
+
3
+ # Dynamically load the gem spec
4
+ gemspec_file = File.expand_path('../../startback.gemspec', __FILE__)
5
+ gemspec = Kernel.eval(File.read(gemspec_file))
6
+
7
+ Gem::PackageTask.new(gemspec) do |t|
8
+
9
+ # Name of the package
10
+ t.name = gemspec.name
11
+
12
+ # Version of the package
13
+ t.version = gemspec.version
14
+
15
+ # Directory used to store the package files
16
+ t.package_dir = "pkg"
17
+
18
+ # True if a gzipped tar file (tgz) should be produced
19
+ t.need_tar = false
20
+
21
+ # True if a gzipped tar file (tar.gz) should be produced
22
+ t.need_tar_gz = false
23
+
24
+ # True if a bzip2'd tar file (tar.bz2) should be produced
25
+ t.need_tar_bz2 = false
26
+
27
+ # True if a zip file should be produced (default is false)
28
+ t.need_zip = false
29
+
30
+ # List of files to be included in the package.
31
+ t.package_files = gemspec.files
32
+
33
+ # Tar command for gzipped or bzip2ed archives.
34
+ t.tar_command = "tar"
35
+
36
+ # Zip command for zipped archives.
37
+ t.zip_command = "zip"
38
+
39
+ end
data/tasks/test.rake ADDED
@@ -0,0 +1,17 @@
1
+ namespace :test do
2
+
3
+ desc "Run RSpec unit tests"
4
+ task :unit do
5
+ system("rspec -Ilib -Ispec --pattern 'spec/unit/**/test_*.rb' --color --backtrace --fail-fast")
6
+ end
7
+
8
+ desc "Run the tests in the examples folder"
9
+ task :example do
10
+ Bundler.with_original_env do
11
+ system("cd example && bundle exec rake")
12
+ end
13
+ end
14
+
15
+ task :all => [:unit, :example]
16
+ end
17
+ task :test => :'test:all'
metadata ADDED
@@ -0,0 +1,169 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: startback
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Bernard Lambeau
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-09-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sinatra
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rack-robustness
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.1'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: finitio
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.6'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.6'
83
+ - !ruby/object:Gem::Dependency
84
+ name: path
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '1.3'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '1.3'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rack-test
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Yet another ruby backend framework, I'm afraid
112
+ email: blambeau@gmail.com
113
+ executables: []
114
+ extensions: []
115
+ extra_rdoc_files: []
116
+ files:
117
+ - Gemfile
118
+ - README.md
119
+ - Rakefile
120
+ - lib/startback.rb
121
+ - lib/startback/context.rb
122
+ - lib/startback/context/middleware.rb
123
+ - lib/startback/errors.rb
124
+ - lib/startback/ext.rb
125
+ - lib/startback/ext/date_time.rb
126
+ - lib/startback/ext/time.rb
127
+ - lib/startback/operation.rb
128
+ - lib/startback/operation/error_operation.rb
129
+ - lib/startback/operation/multi_operation.rb
130
+ - lib/startback/support.rb
131
+ - lib/startback/support/logger.rb
132
+ - lib/startback/version.rb
133
+ - lib/startback/web.rb
134
+ - lib/startback/web/api.rb
135
+ - lib/startback/web/catch_all.rb
136
+ - lib/startback/web/health_check.rb
137
+ - lib/startback/web/shield.rb
138
+ - spec/spec_helper.rb
139
+ - spec/unit/context/test_middleware.rb
140
+ - spec/unit/test_operation.rb
141
+ - spec/unit/test_support.rb
142
+ - spec/unit/web/test_healthcheck.rb
143
+ - tasks/gem.rake
144
+ - tasks/test.rake
145
+ homepage: http://www.enspirit.be
146
+ licenses:
147
+ - MIT
148
+ metadata: {}
149
+ post_install_message:
150
+ rdoc_options: []
151
+ require_paths:
152
+ - lib
153
+ required_ruby_version: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ required_rubygems_version: !ruby/object:Gem::Requirement
159
+ requirements:
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ version: '0'
163
+ requirements: []
164
+ rubyforge_project:
165
+ rubygems_version: 2.6.11
166
+ signing_key:
167
+ specification_version: 4
168
+ summary: Got Your Ruby Back
169
+ test_files: []