ngenie 0.0.1
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.
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/bin/ngenie +5 -0
- data/lib/ext/mustache.rb +126 -0
- data/lib/ngenie.rb +17 -0
- data/lib/ngenie/builder.rb +8 -0
- data/lib/ngenie/builder/base_builder.rb +58 -0
- data/lib/ngenie/builder/domain_builder.rb +19 -0
- data/lib/ngenie/builder/proxy_builder.rb +3 -0
- data/lib/ngenie/builder/route_builder.rb +9 -0
- data/lib/ngenie/cli.rb +44 -0
- data/lib/ngenie/generator.rb +24 -0
- data/lib/ngenie/version.rb +3 -0
- data/ngenie.gemspec +28 -0
- data/spec/builder_spec.rb +11 -0
- data/spec/spec_helper.rb +19 -0
- metadata +187 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Jan Mendoza
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Ngenie
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'ngenie'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install ngenie
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/ngenie
ADDED
data/lib/ext/mustache.rb
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
class Mustache
|
2
|
+
class Generator
|
3
|
+
def on_routes(name, indentation)
|
4
|
+
result = on_fetch([name])
|
5
|
+
|
6
|
+
ev("ctx.route(#{result}, #{indentation.inspect})")
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Context
|
11
|
+
def route(str, indentation = '')
|
12
|
+
mustache = mustache_in_stack
|
13
|
+
part = str.to_s.gsub(/^/, indentation)
|
14
|
+
|
15
|
+
result = mustache.render(part, self)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Parser
|
20
|
+
def scan_tags
|
21
|
+
# Scan until we hit an opening delimiter.
|
22
|
+
start_of_line = @scanner.beginning_of_line?
|
23
|
+
pre_match_position = @scanner.pos
|
24
|
+
last_index = @result.length
|
25
|
+
|
26
|
+
return unless x = @scanner.scan(/([ \t]*)?#{Regexp.escape(otag)}/)
|
27
|
+
padding = @scanner[1] || ''
|
28
|
+
|
29
|
+
# Don't touch the preceding whitespace unless we're matching the start
|
30
|
+
# of a new line.
|
31
|
+
unless start_of_line
|
32
|
+
@result << [:static, padding] unless padding.empty?
|
33
|
+
pre_match_position += padding.length
|
34
|
+
padding = ''
|
35
|
+
end
|
36
|
+
|
37
|
+
# Since {{= rewrites ctag, we store the ctag which should be used
|
38
|
+
# when parsing this specific tag.
|
39
|
+
current_ctag = self.ctag
|
40
|
+
type = @scanner.scan(/#|\^|\/|=|!|<|>|&|\{/)
|
41
|
+
@scanner.skip(/\s*/)
|
42
|
+
|
43
|
+
# ANY_CONTENT tags allow any character inside of them, while
|
44
|
+
# other tags (such as variables) are more strict.
|
45
|
+
if ANY_CONTENT.include?(type)
|
46
|
+
r = /\s*#{regexp(type)}?#{regexp(current_ctag)}/
|
47
|
+
content = scan_until_exclusive(r)
|
48
|
+
else
|
49
|
+
content = @scanner.scan(ALLOWED_CONTENT)
|
50
|
+
end
|
51
|
+
|
52
|
+
# We found {{ but we can't figure out what's going on inside.
|
53
|
+
error "Illegal content in tag" if content.empty?
|
54
|
+
|
55
|
+
fetch = [:mustache, :fetch, content.split('.')]
|
56
|
+
prev = @result
|
57
|
+
|
58
|
+
# Based on the sigil, do what needs to be done.
|
59
|
+
case type
|
60
|
+
when '#'
|
61
|
+
block = [:multi]
|
62
|
+
@result << [:mustache, :section, fetch, block]
|
63
|
+
@sections << [content, position, @result]
|
64
|
+
@result = block
|
65
|
+
when '^'
|
66
|
+
block = [:multi]
|
67
|
+
@result << [:mustache, :inverted_section, fetch, block]
|
68
|
+
@sections << [content, position, @result]
|
69
|
+
@result = block
|
70
|
+
when '/'
|
71
|
+
section, pos, result = @sections.pop
|
72
|
+
raw = @scanner.pre_match[pos[3]...pre_match_position] + padding
|
73
|
+
(@result = result).last << raw << [self.otag, self.ctag]
|
74
|
+
|
75
|
+
if section.nil?
|
76
|
+
error "Closing unopened #{content.inspect}"
|
77
|
+
elsif section != content
|
78
|
+
error "Unclosed section #{section.inspect}", pos
|
79
|
+
end
|
80
|
+
when '!'
|
81
|
+
# ignore comments
|
82
|
+
when '='
|
83
|
+
self.otag, self.ctag = content.split(' ', 2)
|
84
|
+
when '>'
|
85
|
+
@result << [:mustache, :partial, content, padding]
|
86
|
+
when '<'
|
87
|
+
@result << [:mustache, :routes, content, padding]
|
88
|
+
when '{', '&'
|
89
|
+
# The closing } in unescaped tags is just a hack for
|
90
|
+
# aesthetics.
|
91
|
+
type = "}" if type == "{"
|
92
|
+
@result << [:mustache, :utag, fetch]
|
93
|
+
else
|
94
|
+
@result << [:mustache, :etag, fetch]
|
95
|
+
end
|
96
|
+
|
97
|
+
# Skip whitespace and any balancing sigils after the content
|
98
|
+
# inside this tag.
|
99
|
+
@scanner.skip(/\s+/)
|
100
|
+
@scanner.skip(regexp(type)) if type
|
101
|
+
|
102
|
+
# Try to find the closing tag.
|
103
|
+
unless close = @scanner.scan(regexp(current_ctag))
|
104
|
+
error "Unclosed tag"
|
105
|
+
end
|
106
|
+
|
107
|
+
# If this tag was the only non-whitespace content on this line, strip
|
108
|
+
# the remaining whitespace. If not, but we've been hanging on to padding
|
109
|
+
# from the beginning of the line, re-insert the padding as static text.
|
110
|
+
if start_of_line && !@scanner.eos?
|
111
|
+
if @scanner.peek(2) =~ /\r?\n/ && SKIP_WHITESPACE.include?(type)
|
112
|
+
@scanner.skip(/\r?\n/)
|
113
|
+
else
|
114
|
+
prev.insert(last_index, [:static, padding]) unless padding.empty?
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Store off the current scanner position now that we've closed the tag
|
119
|
+
# and consumed any irrelevant whitespace.
|
120
|
+
@sections.last[1] << @scanner.pos unless @sections.empty?
|
121
|
+
|
122
|
+
return unless @result == [:multi]
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
end
|
data/lib/ngenie.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require "ngenie/version"
|
2
|
+
require "mustache"
|
3
|
+
require "ext/mustache"
|
4
|
+
require "docile"
|
5
|
+
require "colored"
|
6
|
+
|
7
|
+
module Ngenie
|
8
|
+
WORK_PATH = File.join(ENV['HOME'], '.ngenie') || Dir.pwd
|
9
|
+
TEMPLATE_PATH = File.join(WORK_PATH, 'templates')
|
10
|
+
CONFD_PATH = File.join(WORK_PATH, 'conf.d')
|
11
|
+
|
12
|
+
attr_accessor :work_path
|
13
|
+
|
14
|
+
autoload :Builder, 'ngenie/builder'
|
15
|
+
autoload :CLI, 'ngenie/cli'
|
16
|
+
autoload :Generator, 'ngenie/generator'
|
17
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
module Ngenie
|
2
|
+
module Builder
|
3
|
+
autoload :BaseBuilder, 'ngenie/builder/base_builder'
|
4
|
+
autoload :DomainBuilder, 'ngenie/builder/domain_builder'
|
5
|
+
autoload :ProxyBuilder, 'ngenie/builder/proxy_builder'
|
6
|
+
autoload :RouteBuilder, 'ngenie/builder/route_builder'
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Ngenie::Builder
|
2
|
+
class BaseBuilder < Mustache
|
3
|
+
DEFAULT_BIND = '127.0.0.1'
|
4
|
+
DEFAULT_PORT = '80'
|
5
|
+
|
6
|
+
attr_accessor :name, :blueprint
|
7
|
+
|
8
|
+
def initialize(name)
|
9
|
+
@name = name
|
10
|
+
@bind = DEFAULT_BIND
|
11
|
+
@port = DEFAULT_PORT
|
12
|
+
end
|
13
|
+
|
14
|
+
def blueprint(template)
|
15
|
+
@blueprint = get_template(template)
|
16
|
+
end
|
17
|
+
|
18
|
+
def build(template='')
|
19
|
+
|
20
|
+
set_template(template)
|
21
|
+
|
22
|
+
File.open(File.join(Ngenie::CONFD_PATH, "#{name}.conf"), "w") do |f|
|
23
|
+
f.write("# GENERATED BY Ngenie. DO NOT EDIT\n#{render}\n".chomp)
|
24
|
+
f.close
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_template(template)
|
29
|
+
File.read(File.join(Ngenie::TEMPLATE_PATH, "#{template}.#{self.template_extension}"))
|
30
|
+
end
|
31
|
+
|
32
|
+
def set_template(template)
|
33
|
+
self.template = @blueprint || get_template(template)
|
34
|
+
end
|
35
|
+
|
36
|
+
def method_missing(meth, *args, &blk)
|
37
|
+
name = meth.to_s
|
38
|
+
|
39
|
+
klass = class << self; self; end
|
40
|
+
|
41
|
+
klass.class_eval do
|
42
|
+
define_method(name) do |*args|
|
43
|
+
if !args.empty?
|
44
|
+
self.instance_variable_set(:"@#{name}", args.first)
|
45
|
+
else
|
46
|
+
self.instance_variable_get(:"@#{name}")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
send(meth, *args, &blk)
|
52
|
+
end
|
53
|
+
|
54
|
+
def respond_to?(meth)
|
55
|
+
meth != :has_key? ? true : super(meth)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Ngenie::Builder
|
2
|
+
class DomainBuilder < BaseBuilder
|
3
|
+
attr_accessor :routes, :file_name
|
4
|
+
|
5
|
+
def initialize(name)
|
6
|
+
super(name)
|
7
|
+
|
8
|
+
@routes = ''
|
9
|
+
end
|
10
|
+
|
11
|
+
def route(arg='', &blk)
|
12
|
+
if arg.empty?
|
13
|
+
@routes
|
14
|
+
else
|
15
|
+
@routes += Docile.dsl_eval(RouteBuilder.new(arg), &blk).build
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/ngenie/cli.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
module Ngenie
|
4
|
+
class CLI < Thor
|
5
|
+
TREE = { :work_path => WORK_PATH,
|
6
|
+
:confd_path => CONFD_PATH,
|
7
|
+
:template_path => TEMPLATE_PATH
|
8
|
+
}
|
9
|
+
|
10
|
+
desc "bootstrap", "bootstrap an ngenie deployment"
|
11
|
+
|
12
|
+
def bootstrap
|
13
|
+
bootstrap_work_path
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "check", "check if node has been bootstrapped"
|
17
|
+
|
18
|
+
def check
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "generate", "generate nginx config files"
|
23
|
+
def generate
|
24
|
+
Generator.new.generate
|
25
|
+
end
|
26
|
+
|
27
|
+
no_commands do
|
28
|
+
def bootstrap_work_path
|
29
|
+
TREE.each { |key, val| create_if_not_exists(key, val) }
|
30
|
+
end
|
31
|
+
|
32
|
+
def create_if_not_exists(name, file)
|
33
|
+
if File.exists?(file)
|
34
|
+
say("#{name} %s found. Skipping.", :yellow)
|
35
|
+
else
|
36
|
+
say("#{name} not found. Creating #{name}.", :green)
|
37
|
+
|
38
|
+
FileUtils.mkdir_p(file)
|
39
|
+
say("Done. Created #{name}: #{file}", :green)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Ngenie
|
2
|
+
class Generator
|
3
|
+
DEFAULT_DOMAIN_TEMPLATE = 'domain'
|
4
|
+
DEFAULT_PROXY_TEMPLATE = 'upstream'
|
5
|
+
|
6
|
+
def generate
|
7
|
+
load
|
8
|
+
end
|
9
|
+
|
10
|
+
def load
|
11
|
+
Dir.glob("%s/*.rb" % WORK_PATH) do |file|
|
12
|
+
eval File.read(file), binding, File.basename(file)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def proxy(arg, &blk)
|
17
|
+
Docile.dsl_eval(Builder::ProxyBuilder.new(arg), &blk).build(DEFAULT_PROXY_TEMPLATE)
|
18
|
+
end
|
19
|
+
|
20
|
+
def domain(arg, &blk)
|
21
|
+
Docile.dsl_eval(Builder::DomainBuilder.new(arg), &blk).build(DEFAULT_DOMAIN_TEMPLATE)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/ngenie.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ngenie/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ngenie"
|
8
|
+
spec.version = Ngenie::VERSION
|
9
|
+
spec.authors = ["Jan Mendoza"]
|
10
|
+
spec.email = ["poymode@gmail.com"]
|
11
|
+
spec.description = %q{}
|
12
|
+
spec.summary = %q{}
|
13
|
+
spec.homepage = ""
|
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 "docile"
|
22
|
+
spec.add_dependency "mustache"
|
23
|
+
spec.add_dependency "thor"
|
24
|
+
spec.add_dependency "colored"
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
26
|
+
spec.add_development_dependency "rake"
|
27
|
+
spec.add_development_dependency "rspec"
|
28
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
RSpec.configure do |config|
|
8
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
9
|
+
config.run_all_when_everything_filtered = true
|
10
|
+
config.filter_run :focus
|
11
|
+
|
12
|
+
# Run specs in random order to surface order dependencies. If you find an
|
13
|
+
# order dependency and want to debug it, you can fix the order by providing
|
14
|
+
# the seed, which is printed after each run.
|
15
|
+
# --seed 1234
|
16
|
+
config.order = 'random'
|
17
|
+
end
|
18
|
+
|
19
|
+
require File.expand_path('lib/ngenie')
|
metadata
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ngenie
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jan Mendoza
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-06-18 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: docile
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: mustache
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: thor
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: colored
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: bundler
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '1.3'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '1.3'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: rake
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: rspec
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
description: ''
|
127
|
+
email:
|
128
|
+
- poymode@gmail.com
|
129
|
+
executables:
|
130
|
+
- ngenie
|
131
|
+
extensions: []
|
132
|
+
extra_rdoc_files: []
|
133
|
+
files:
|
134
|
+
- .gitignore
|
135
|
+
- .rspec
|
136
|
+
- Gemfile
|
137
|
+
- LICENSE.txt
|
138
|
+
- README.md
|
139
|
+
- Rakefile
|
140
|
+
- bin/ngenie
|
141
|
+
- lib/ext/mustache.rb
|
142
|
+
- lib/ngenie.rb
|
143
|
+
- lib/ngenie/builder.rb
|
144
|
+
- lib/ngenie/builder/base_builder.rb
|
145
|
+
- lib/ngenie/builder/domain_builder.rb
|
146
|
+
- lib/ngenie/builder/proxy_builder.rb
|
147
|
+
- lib/ngenie/builder/route_builder.rb
|
148
|
+
- lib/ngenie/cli.rb
|
149
|
+
- lib/ngenie/generator.rb
|
150
|
+
- lib/ngenie/version.rb
|
151
|
+
- ngenie.gemspec
|
152
|
+
- spec/builder_spec.rb
|
153
|
+
- spec/spec_helper.rb
|
154
|
+
homepage: ''
|
155
|
+
licenses:
|
156
|
+
- MIT
|
157
|
+
post_install_message:
|
158
|
+
rdoc_options: []
|
159
|
+
require_paths:
|
160
|
+
- lib
|
161
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
162
|
+
none: false
|
163
|
+
requirements:
|
164
|
+
- - ! '>='
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
segments:
|
168
|
+
- 0
|
169
|
+
hash: -3093275548724926976
|
170
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
171
|
+
none: false
|
172
|
+
requirements:
|
173
|
+
- - ! '>='
|
174
|
+
- !ruby/object:Gem::Version
|
175
|
+
version: '0'
|
176
|
+
segments:
|
177
|
+
- 0
|
178
|
+
hash: -3093275548724926976
|
179
|
+
requirements: []
|
180
|
+
rubyforge_project:
|
181
|
+
rubygems_version: 1.8.25
|
182
|
+
signing_key:
|
183
|
+
specification_version: 3
|
184
|
+
summary: ''
|
185
|
+
test_files:
|
186
|
+
- spec/builder_spec.rb
|
187
|
+
- spec/spec_helper.rb
|