lam 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +6 -0
  6. data/Gemfile.lock +107 -0
  7. data/Guardfile +22 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +37 -0
  10. data/Rakefile +6 -0
  11. data/bin/lam +14 -0
  12. data/lam.gemspec +32 -0
  13. data/lib/lam.rb +14 -0
  14. data/lib/lam/base_controller.rb +54 -0
  15. data/lib/lam/build.rb +43 -0
  16. data/lib/lam/build/handler_generator.rb +34 -0
  17. data/lib/lam/build/lambda_deducer.rb +47 -0
  18. data/lib/lam/build/templates/handler.js +156 -0
  19. data/lib/lam/build/traveling_ruby.rb +108 -0
  20. data/lib/lam/cli.rb +23 -0
  21. data/lib/lam/cli/help.rb +19 -0
  22. data/lib/lam/command.rb +25 -0
  23. data/lib/lam/process.rb +18 -0
  24. data/lib/lam/process/base_processor.rb +23 -0
  25. data/lib/lam/process/controller_processor.rb +36 -0
  26. data/lib/lam/process/help.rb +11 -0
  27. data/lib/lam/process/processor_deducer.rb +52 -0
  28. data/lib/lam/util.rb +13 -0
  29. data/lib/lam/version.rb +3 -0
  30. data/notes/design.md +43 -0
  31. data/notes/traveling-ruby-packaging-lam.md +26 -0
  32. data/notes/traveling-ruby-packaging.md +103 -0
  33. data/notes/traveling-ruby.md +82 -0
  34. data/spec/fixtures/project/.gitignore +3 -0
  35. data/spec/fixtures/project/.ruby-version +1 -0
  36. data/spec/fixtures/project/Gemfile +4 -0
  37. data/spec/fixtures/project/Gemfile.lock +35 -0
  38. data/spec/fixtures/project/app/controllers/application_controller.rb +2 -0
  39. data/spec/fixtures/project/app/controllers/posts_controller.rb +12 -0
  40. data/spec/fixtures/project/bin/lam +22 -0
  41. data/spec/fixtures/project/handlers/controllers/posts.js +156 -0
  42. data/spec/lib/cli_spec.rb +20 -0
  43. data/spec/lib/lam/base_controller_spec.rb +18 -0
  44. data/spec/lib/lam/build/lambda_deducer_spec.rb +20 -0
  45. data/spec/lib/lam/build_spec.rb +29 -0
  46. data/spec/lib/lam/process/controller_processor_spec.rb +22 -0
  47. data/spec/lib/lam/process/infer_spec.rb +24 -0
  48. data/spec/lib/lam/process_spec.rb +18 -0
  49. data/spec/spec_helper.rb +25 -0
  50. metadata +249 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8750fb4fa7f6b7ed46b29b8941bc055b48358769
4
+ data.tar.gz: f90803796010fce9b2038b9fdc12283bcc4c99a2
5
+ SHA512:
6
+ metadata.gz: 323ba3a836d5b22711cf6878ed3ae02499474469f3d5844ab4d6ac8754bebadfb1518ad43c05a5a4d69c427e8e28f88e1854c15fee0d7cde6ad5f40c7f7fb1d3
7
+ data.tar.gz: 6d1d7f35ee1cb7f75c8f47811ecd9ab0bdb01f1ddbd399edc8196e69d54a4ba2ba6809323ed8791e65f23309d335d4e8782d01535e07919f2566d22521801365
@@ -0,0 +1,16 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ InstalledFiles
7
+ _yardoc
8
+ coverage
9
+ doc/
10
+ lib/bundler/man
11
+ pkg
12
+ rdoc
13
+ spec/reports
14
+ test/tmp
15
+ test/version_tmp
16
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
@@ -0,0 +1 @@
1
+ 2.2.2
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem dependencies in lam.gemspec
4
+ gemspec
5
+
6
+ gem "codeclimate-test-reporter", group: :test, require: nil
@@ -0,0 +1,107 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ lam (0.0.1)
5
+ activesupport
6
+ colorize
7
+ hashie
8
+ thor
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ activesupport (5.1.4)
14
+ concurrent-ruby (~> 1.0, >= 1.0.2)
15
+ i18n (~> 0.7)
16
+ minitest (~> 5.1)
17
+ tzinfo (~> 1.1)
18
+ byebug (9.1.0)
19
+ codeclimate-test-reporter (1.0.8)
20
+ simplecov (<= 0.13)
21
+ coderay (1.1.2)
22
+ colorize (0.8.1)
23
+ concurrent-ruby (1.0.5)
24
+ diff-lcs (1.3)
25
+ docile (1.1.5)
26
+ ffi (1.9.18)
27
+ formatador (0.2.5)
28
+ guard (2.14.1)
29
+ formatador (>= 0.2.4)
30
+ listen (>= 2.7, < 4.0)
31
+ lumberjack (~> 1.0)
32
+ nenv (~> 0.1)
33
+ notiffany (~> 0.0)
34
+ pry (>= 0.9.12)
35
+ shellany (~> 0.0)
36
+ thor (>= 0.18.1)
37
+ guard-bundler (2.1.0)
38
+ bundler (~> 1.0)
39
+ guard (~> 2.2)
40
+ guard-compat (~> 1.1)
41
+ guard-compat (1.2.1)
42
+ guard-rspec (4.7.3)
43
+ guard (~> 2.1)
44
+ guard-compat (~> 1.1)
45
+ rspec (>= 2.99.0, < 4.0)
46
+ hashie (3.5.6)
47
+ i18n (0.9.0)
48
+ concurrent-ruby (~> 1.0)
49
+ json (2.1.0)
50
+ listen (3.1.5)
51
+ rb-fsevent (~> 0.9, >= 0.9.4)
52
+ rb-inotify (~> 0.9, >= 0.9.7)
53
+ ruby_dep (~> 1.2)
54
+ lumberjack (1.0.12)
55
+ method_source (0.9.0)
56
+ minitest (5.10.3)
57
+ nenv (0.3.0)
58
+ notiffany (0.1.1)
59
+ nenv (~> 0.1)
60
+ shellany (~> 0.0)
61
+ pry (0.11.2)
62
+ coderay (~> 1.1.0)
63
+ method_source (~> 0.9.0)
64
+ rake (12.2.1)
65
+ rb-fsevent (0.10.2)
66
+ rb-inotify (0.9.10)
67
+ ffi (>= 0.5.0, < 2)
68
+ rspec (3.7.0)
69
+ rspec-core (~> 3.7.0)
70
+ rspec-expectations (~> 3.7.0)
71
+ rspec-mocks (~> 3.7.0)
72
+ rspec-core (3.7.0)
73
+ rspec-support (~> 3.7.0)
74
+ rspec-expectations (3.7.0)
75
+ diff-lcs (>= 1.2.0, < 2.0)
76
+ rspec-support (~> 3.7.0)
77
+ rspec-mocks (3.7.0)
78
+ diff-lcs (>= 1.2.0, < 2.0)
79
+ rspec-support (~> 3.7.0)
80
+ rspec-support (3.7.0)
81
+ ruby_dep (1.5.0)
82
+ shellany (0.0.1)
83
+ simplecov (0.13.0)
84
+ docile (~> 1.1.0)
85
+ json (>= 1.8, < 3)
86
+ simplecov-html (~> 0.10.0)
87
+ simplecov-html (0.10.2)
88
+ thor (0.20.0)
89
+ thread_safe (0.3.6)
90
+ tzinfo (1.2.3)
91
+ thread_safe (~> 0.1)
92
+
93
+ PLATFORMS
94
+ ruby
95
+
96
+ DEPENDENCIES
97
+ bundler
98
+ byebug
99
+ codeclimate-test-reporter
100
+ guard
101
+ guard-bundler
102
+ guard-rspec
103
+ lam!
104
+ rake
105
+
106
+ BUNDLED WITH
107
+ 1.15.4
@@ -0,0 +1,22 @@
1
+ guard "bundler", cmd: "bundle" do
2
+ watch("Gemfile")
3
+ watch(/^.+\.gemspec/)
4
+ end
5
+
6
+ guard :rspec, cmd: "bundle exec rspec" do
7
+ require "guard/rspec/dsl"
8
+ dsl = Guard::RSpec::Dsl.new(self)
9
+
10
+ # RSpec files
11
+ rspec = dsl.rspec
12
+ watch(rspec.spec_helper) { rspec.spec_dir }
13
+ watch(rspec.spec_support) { rspec.spec_dir }
14
+ watch(rspec.spec_files)
15
+
16
+ # Ruby files
17
+ ruby = dsl.ruby
18
+ puts "ruby.lib_files #{ruby.lib_files.inspect}"
19
+ dsl.watch_spec_files_for(ruby.lib_files)
20
+
21
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
22
+ end
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Tung Nguyen
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,37 @@
1
+ # Lam
2
+
3
+ [![Build Status](https://magnum.travis-ci.com/)](https://magnum.travis-ci.com/)
4
+ [![Code Climate](https://codeclimate.com/)](https://codeclimate.com/)
5
+ [![Code Climate](https://codeclimate.com/)](https://codeclimate.com/)
6
+
7
+ To these the lam, run these commands:
8
+
9
+ TODO: Write a gem description
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```sh
16
+ gem "lam"
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ ```sh
22
+ $ bundle
23
+ ```
24
+
25
+ Or install it yourself as:
26
+
27
+ ```
28
+ $ gem install lam
29
+ ```
30
+
31
+ ## Contributing
32
+
33
+ 1. Fork it
34
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
35
+ 3. Commit your changes (`git commit -am "Add some feature"`)
36
+ 4. Push to the branch (`git push origin my-new-feature`)
37
+ 5. Create new Pull Request
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ task :default => :spec
5
+
6
+ RSpec::Core::RakeTask.new
data/bin/lam ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Trap ^C
4
+ Signal.trap("INT") {
5
+ puts "\nCtrl-C detected. Exiting..."
6
+ sleep 1
7
+ exit
8
+ }
9
+
10
+ $:.unshift(File.expand_path("../../lib", __FILE__))
11
+ require "lam"
12
+ require "lam/cli"
13
+
14
+ Lam::CLI.start(ARGV)
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "lam/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "lam"
8
+ spec.version = Lam::VERSION
9
+ spec.authors = ["Tung Nguyen"]
10
+ spec.email = ["tongueroo@gmail.com"]
11
+ spec.description = %q{Test}
12
+ spec.summary = %q{Test}
13
+ spec.homepage = "https://github.com/tongueroo/lam"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "thor"
22
+ spec.add_dependency "hashie"
23
+ spec.add_dependency "colorize"
24
+ spec.add_dependency "activesupport"
25
+
26
+ spec.add_development_dependency "bundler"
27
+ spec.add_development_dependency "byebug"
28
+ spec.add_development_dependency "rake"
29
+ spec.add_development_dependency "guard"
30
+ spec.add_development_dependency "guard-bundler"
31
+ spec.add_development_dependency "guard-rspec"
32
+ end
@@ -0,0 +1,14 @@
1
+ $:.unshift(File.expand_path("../", __FILE__))
2
+ require "lam/version"
3
+ require 'active_support/core_ext/string'
4
+
5
+ module Lam
6
+ autoload :Util, "lam/util"
7
+ autoload :Command, "lam/command"
8
+ autoload :CLI, "lam/cli"
9
+ autoload :Build, 'lam/build'
10
+ autoload :Process, 'lam/process'
11
+ autoload :BaseController, 'lam/base_controller'
12
+
13
+ extend Util
14
+ end
@@ -0,0 +1,54 @@
1
+ require 'json'
2
+
3
+ module Lam
4
+ class BaseController
5
+ attr_reader :event, :context
6
+ def initialize(event, context)
7
+ @event = event
8
+ @context = context
9
+ end
10
+
11
+ # The public methods defined in the user's custom class will become
12
+ # lambda functions.
13
+ # Returns Example:
14
+ # ["FakeController#handler1", "FakeController#handler2"]
15
+ def lambda_functions
16
+ # public_instance_methods(false) - to not include inherited methods
17
+ self.class.public_instance_methods(false) - Object.public_instance_methods
18
+ end
19
+
20
+ def self.lambda_functions
21
+ new(nil, nil).lambda_functions
22
+ end
23
+
24
+ private
25
+ def render(options={})
26
+ # render json: {"mytestdata": "value1"}, status: 200, headers: {...}
27
+ if options.has_key?(:json)
28
+ # Transform the structure to Lambda Proxy structure
29
+ # {statusCode: ..., body: ..., headers: }
30
+ status = options.delete(:status)
31
+ body = options.delete(:json)
32
+ result = options.merge(
33
+ statusCode: status,
34
+ body: body
35
+ )
36
+ # render text: "text"
37
+ elsif options.has_key?(:text)
38
+ result = options.delete(:text)
39
+ else
40
+ raise "Unsupported render option. Only :text and :json supported. options #{options.inspect}"
41
+ end
42
+
43
+ result
44
+ end
45
+
46
+ # API Gateway LAMBDA_PROXY wraps the event in its own structure.
47
+ # We unwrap the "body" before sending it back
48
+ # For regular Lambda function calls, no need to unwrap but need to
49
+ # transform it to a string with JSON.dump.
50
+ def normalize_event_body(event)
51
+ body = event.has_key?("body") ? event["body"] : JSON.dump(event)
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,43 @@
1
+ require 'pp'
2
+
3
+ class Lam::Build
4
+ autoload :LambdaDeducer, "lam/build/lambda_deducer"
5
+ autoload :HandlerGenerator, "lam/build/handler_generator"
6
+ autoload :TravelingRuby, "lam/build/traveling_ruby"
7
+
8
+ def initialize(options)
9
+ @options = options
10
+ end
11
+
12
+ def run
13
+ puts "Building project for Lambda..."
14
+ build
15
+ end
16
+
17
+ def build
18
+ handlers.each do |handler|
19
+ HandlerGenerator.new(handler).generate
20
+ end
21
+
22
+ TravelingRuby.new.build unless @options[:noop]
23
+ end
24
+
25
+ def handlers
26
+ handlers = []
27
+ expression = "#{Lam.root}app/controllers/**/*.rb"
28
+ Dir.glob(expression).each do |path|
29
+ next unless File.file?(path)
30
+ next if path.include?("application_controller.rb")
31
+
32
+ path = relative_path(path)
33
+ handlers += LambdaDeducer.new(path).deduce.handlers
34
+ end
35
+ # pp handlers
36
+ handlers
37
+ end
38
+
39
+ # Rids of the Lam.root at beginning
40
+ def relative_path(path)
41
+ path.sub(Lam.root, '')
42
+ end
43
+ end
@@ -0,0 +1,34 @@
1
+ require "fileutils"
2
+ require "erb"
3
+
4
+ class Lam::Build
5
+ class HandlerGenerator
6
+ # handler_info:
7
+ # {:handler=>"handlers/controllers/posts.create",
8
+ # :js_path=>"handlers/controllers/posts.js",
9
+ # :js_method=>"create"}
10
+ def initialize(handler_info)
11
+ @handler_info = handler_info
12
+ @handler = handler_info[:handler]
13
+ @js_path = handler_info[:js_path]
14
+ @js_method = handler_info[:js_method]
15
+ end
16
+
17
+ def generate
18
+ js_path = "#{Lam.root}#{@js_path}"
19
+ FileUtils.mkdir_p(File.dirname(js_path))
20
+
21
+ template_path = File.expand_path('../templates/handler.js', __FILE__)
22
+ template = IO.read(template_path)
23
+
24
+ # Important ERB variables with examples:
25
+ # @handler - handlers/controllers/posts.create
26
+ # @process_type - controller
27
+ @process_type = @handler.split('/')[1].singularize
28
+ result = ERB.new(template, nil, "-").result(binding)
29
+ puts "generating #{js_path}"
30
+ IO.write(js_path, result)
31
+ # FileUtils.cp(template_path, js_path)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,47 @@
1
+ class Lam::Build
2
+ class LambdaDeducer
3
+ attr_reader :handlers
4
+ def initialize(path)
5
+ @path = path
6
+ end
7
+
8
+ def run
9
+ deduce
10
+ end
11
+
12
+ def deduce
13
+ # Example: require "./app/controllers/posts_controller.rb"
14
+ require_path = @path.starts_with?('/') ? @path : "#{Lam.root}#{@path}"
15
+ require require_path
16
+
17
+ # Example: @klass_name = "PostsController"
18
+ @klass_name = File.basename(@path, '.rb').classify
19
+ klass = @klass_name.constantize
20
+ @handlers = klass.lambda_functions.map { |fn| handler_info(fn) }
21
+ self
22
+ end
23
+
24
+ # Transform the method to the handler info
25
+ def handler_info(function_name)
26
+ handler = get_handler(function_name)
27
+ js_path = get_js_path(function_name)
28
+ {
29
+ handler: handler,
30
+ js_path: js_path,
31
+ js_method: function_name.to_s
32
+ }
33
+ end
34
+
35
+ def get_handler(function_name)
36
+ "handlers/controllers/#{module_name}.create"
37
+ end
38
+
39
+ def get_js_path(function_name)
40
+ "handlers/controllers/#{module_name}.js"
41
+ end
42
+
43
+ def module_name
44
+ @klass_name.sub(/Controller$/,'').underscore
45
+ end
46
+ end
47
+ end