diff --git a/lib/nack.rb b/lib/nack.rb index 68e28b5..b4b8ff1 100644 --- a/lib/nack.rb +++ b/lib/nack.rb @@ -1,8 +1,10 @@ # frozen_string_literal: true require_relative "nack/version" +require_relative "nack/component" require_relative "nack/error" require_relative "nack/headers" +require_relative "nack/middleware" require_relative "nack/mime" require_relative "nack/query_parser" require_relative "nack/request" diff --git a/lib/nack/component.rb b/lib/nack/component.rb new file mode 100644 index 0000000..9c879ca --- /dev/null +++ b/lib/nack/component.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Nack + class Component + def to_app + prepare_app + self + end + + private + + def prepare_app + end + end +end diff --git a/lib/nack/middleware.rb b/lib/nack/middleware.rb new file mode 100644 index 0000000..4a9edbe --- /dev/null +++ b/lib/nack/middleware.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Nack + class Middleware < Component + def call(request) + @app.call(request) + end + + def wrap(app) + middleware = clone(freeze: false) + middleware.app = app + middleware + end + + protected + + attr_writer :app + end +end diff --git a/test/spec_component.rb b/test/spec_component.rb new file mode 100644 index 0000000..15f0a5f --- /dev/null +++ b/test/spec_component.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require_relative "helper" + +describe Nack::Component do + it "returns itself as the app" do + component = Nack::Component.new + component.to_app.must_be_same_as component + end + + it "prepares itself as the app" do + component = Class.new(Nack::Component) do + attr_reader :prepared + + def prepare_app + @prepared = true + end + end.new + component.to_app.prepared.must_equal true + end +end diff --git a/test/spec_middleware.rb b/test/spec_middleware.rb new file mode 100644 index 0000000..ec3c3ef --- /dev/null +++ b/test/spec_middleware.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +require_relative "helper" + +describe Nack::Middleware do + it "wraps an app in a copy of a frozen instance" do + Nack::Middleware.new.freeze.wrap(->(request) { "#{request}b" }).call("a").must_equal "ab" + end + + it "wraps an app in a copy keeping its singleton methods" do + middleware = Nack::Middleware.new + def middleware.call(request) = "#{super}c" + middleware.wrap(->(request) { "#{request}b" }).call("a").must_equal "abc" + end +end