grape-starter 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 +7 -0
- data/.gitignore +12 -0
- data/.rubocop.yml +36 -0
- data/.rubocop_todo.yml +12 -0
- data/.travis.yml +5 -0
- data/CHANGELOG.md +27 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +70 -0
- data/Rakefile +14 -0
- data/bin/grape-starter +119 -0
- data/grape-starter.gemspec +36 -0
- data/lib/starter.rb +9 -0
- data/lib/starter/builder.rb +90 -0
- data/lib/starter/builder/names.rb +56 -0
- data/lib/starter/builder/template_endpoints.rb +97 -0
- data/lib/starter/builder/template_files.rb +73 -0
- data/lib/starter/rake/grape_tasks.rb +71 -0
- data/lib/starter/rspec/request_specs.rb +109 -0
- data/lib/starter/version.rb +4 -0
- data/template/.rubocop.yml +15 -0
- data/template/.rubocop_todo.yml +28 -0
- data/template/Gemfile +23 -0
- data/template/LICENSE +21 -0
- data/template/README.md +70 -0
- data/template/Rakefile +25 -0
- data/template/api/base.rb +18 -0
- data/template/api/endpoints/root.rb +20 -0
- data/template/api/entities/api_error.rb +17 -0
- data/template/api/entities/route.rb +22 -0
- data/template/config.ru +12 -0
- data/template/config/application.rb +22 -0
- data/template/config/boot.rb +3 -0
- data/template/config/environment.rb +4 -0
- data/template/lib/api.rb +6 -0
- data/template/lib/api/version.rb +4 -0
- data/template/script/console +8 -0
- data/template/script/server +14 -0
- data/template/script/setup +6 -0
- data/template/script/stop +8 -0
- data/template/script/test +17 -0
- data/template/script/update +6 -0
- data/template/spec/lib/api/version_spec.rb +8 -0
- data/template/spec/requests/documentation_spec.rb +12 -0
- data/template/spec/requests/root_spec.rb +25 -0
- data/template/spec/spec_helper.rb +25 -0
- metadata +216 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 52f430416f92875210e64914e6fe61c29d4c3e56
|
4
|
+
data.tar.gz: 77f33daa8ca7ef7f49e4415acaf2261edc888969
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 94908b48037df0376311ddb26b61e408e99b9fd65e017fbb484a121cdaacea7fc65fe12fc7eae1930ba5239becefddf5555ecca2d02599ec9b05cafe570ae48a
|
7
|
+
data.tar.gz: f089a230198355841150ae7353973e0fc8180c50e2e742f98ed63363c193b48ac199f46694238e2a516ebd0ce970028e876bcae079f97962820c500962919b90
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
inherit_from: .rubocop_todo.yml
|
2
|
+
|
3
|
+
AllCops:
|
4
|
+
Exclude:
|
5
|
+
- '**/bin/**/*'
|
6
|
+
- '**/tmp/**/*'
|
7
|
+
- '**/script/**/*'
|
8
|
+
- grape-starter.gemspec
|
9
|
+
UseCache: true
|
10
|
+
TargetRubyVersion: 2.3
|
11
|
+
|
12
|
+
Metrics/BlockLength:
|
13
|
+
Exclude:
|
14
|
+
- 'spec/**/*'
|
15
|
+
|
16
|
+
Metrics/LineLength:
|
17
|
+
Max: 120
|
18
|
+
|
19
|
+
Style/AccessorMethodName:
|
20
|
+
Exclude:
|
21
|
+
- 'lib/starter/builder/template_files.rb'
|
22
|
+
- 'lib/starter/builder/template_endpoints.rb'
|
23
|
+
|
24
|
+
Style/AsciiComments:
|
25
|
+
Enabled: false
|
26
|
+
|
27
|
+
Style/IndentationWidth:
|
28
|
+
Exclude:
|
29
|
+
- 'lib/starter/builder/template_files.rb'
|
30
|
+
- 'lib/starter/builder/template_endpoints.rb'
|
31
|
+
|
32
|
+
Style/Documentation:
|
33
|
+
Exclude:
|
34
|
+
- 'template/**/*'
|
35
|
+
- 'lib/**/*'
|
36
|
+
- 'spec/**/*'
|
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2016-10-18 20:40:59 +0200 using RuboCop version 0.44.1.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 1
|
10
|
+
# Configuration parameters: CountComments.
|
11
|
+
Metrics/MethodLength:
|
12
|
+
Max: 13
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
### 0.1.8
|
2
|
+
|
3
|
+
- adds request specs shared examples
|
4
|
+
|
5
|
+
### 0.1.7
|
6
|
+
|
7
|
+
- corrects path param for specific endpoints
|
8
|
+
|
9
|
+
### 0.1.6
|
10
|
+
|
11
|
+
- corrects adding of endpoints, if no http verb was given
|
12
|
+
|
13
|
+
### 0.1.5
|
14
|
+
|
15
|
+
- adds flag for entity creating
|
16
|
+
|
17
|
+
### 0.1.4
|
18
|
+
|
19
|
+
- version bump v0.1.4
|
20
|
+
- moves back dependencies to gemspec
|
21
|
+
- adds rubygems badge
|
22
|
+
- cleans up dependencies …
|
23
|
+
- updates readme
|
24
|
+
- version bump v0.1.2
|
25
|
+
- adds `force` option to add
|
26
|
+
- version bump v0.1.1
|
27
|
+
- adds specifying http verbs
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Peter Scholz
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
[](https://app.codeship.com/projects/186901)
|
2
|
+
[](https://badge.fury.io/rb/grape-starter)
|
3
|
+
[](http://inch-ci.org/github/LeFnord/grape-starter)
|
4
|
+
|
5
|
+
# Grape Starter
|
6
|
+
|
7
|
+
Is a tool to help you to build up a skeleton for a [Grape](http://github.com/ruby-grape/grape) API mounted on [Rack](https://github.com/rack/rack) ready to run.
|
8
|
+
[grape-swagger](http://github.com/ruby-grape/grape-swagger) would be used to generate a [OAPI](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md) compatible documentation.
|
9
|
+
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
#### Install it
|
14
|
+
```
|
15
|
+
$ gem install grape-starter
|
16
|
+
```
|
17
|
+
|
18
|
+
#### Create a new project
|
19
|
+
```
|
20
|
+
$ grape-starter new awesome_api
|
21
|
+
```
|
22
|
+
|
23
|
+
This command creates a folder named `awesome_api` containing the skeleton. With following structure:
|
24
|
+
|
25
|
+
```
|
26
|
+
├── <Standards>
|
27
|
+
├── api
|
28
|
+
│ ├── base.rb # the main API class, all other endpoints would be mounted in it
|
29
|
+
│ ├── endpoints # contains the endpoint file for a resource
|
30
|
+
│ │ └── root.rb # root is always available, it exposes all routes/endpoints, disable by comment out in base.rb
|
31
|
+
│ └── entities # contains the entity representation of the reource, if wanted
|
32
|
+
│ └── route.rb
|
33
|
+
├── config # base configuration
|
34
|
+
│ └── …
|
35
|
+
├── config.ru # Rack it up
|
36
|
+
├── lib # contains the additional lib file for a resource
|
37
|
+
│ ├── api
|
38
|
+
│ │ └── version.rb
|
39
|
+
│ └── api.rb
|
40
|
+
├── script # setup / server / test etc.
|
41
|
+
│ └── …
|
42
|
+
└── spec # RSpec
|
43
|
+
└── …
|
44
|
+
```
|
45
|
+
|
46
|
+
To run it, go into awesome_api folder, start the server
|
47
|
+
```
|
48
|
+
$ cd awesome_api
|
49
|
+
$ ./script/server
|
50
|
+
```
|
51
|
+
the API is now accessible under: [http://localhost:9292/api/v1/root](http://localhost:9292/api/v1/root)
|
52
|
+
|
53
|
+
More could be found in [README](template/README.md).
|
54
|
+
|
55
|
+
#### Add resources
|
56
|
+
```
|
57
|
+
$ grape-starter add foo
|
58
|
+
```
|
59
|
+
to add CRUD endpoints for resource foo. For more options, see command help.
|
60
|
+
|
61
|
+
This adds endpoint and lib file and belonging specs, and a mount entry in base.rb.
|
62
|
+
|
63
|
+
## Contributing
|
64
|
+
|
65
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/LeFnord/grape-starter.
|
66
|
+
|
67
|
+
|
68
|
+
## License
|
69
|
+
|
70
|
+
The gem is available as open source under the terms of the [MIT License](LICENSE).
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
|
4
|
+
require 'rake'
|
5
|
+
|
6
|
+
require 'rspec/core'
|
7
|
+
require 'rspec/core/rake_task'
|
8
|
+
|
9
|
+
RSpec::Core::RakeTask.new(:spec)
|
10
|
+
|
11
|
+
require 'rubocop/rake_task'
|
12
|
+
RuboCop::RakeTask.new(:rubocop)
|
13
|
+
|
14
|
+
task default: [:rubocop, :spec]
|
data/bin/grape-starter
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
4
|
+
|
5
|
+
|
6
|
+
require 'pry'
|
7
|
+
require 'gli'
|
8
|
+
require 'starter'
|
9
|
+
|
10
|
+
include GLI::App
|
11
|
+
|
12
|
+
program_desc 'Create initial grape api skeleton'
|
13
|
+
|
14
|
+
version Starter::VERSION
|
15
|
+
|
16
|
+
subcommand_option_handling :normal
|
17
|
+
arguments :strict
|
18
|
+
|
19
|
+
desc 'overwrites existend stuff'
|
20
|
+
switch [:f, :force], negatable: false
|
21
|
+
|
22
|
+
desc 'Create initial grape api skeleton'
|
23
|
+
arg_name 'project name'
|
24
|
+
|
25
|
+
command :new do |c|
|
26
|
+
|
27
|
+
c.action do |global_options, _, args|
|
28
|
+
dir = args.empty? ? nil : File.join(Dir.getwd, args.first)
|
29
|
+
|
30
|
+
case
|
31
|
+
when args.empty? || dir.nil?
|
32
|
+
exit_now! 'no name given: starter new project'
|
33
|
+
when Dir.exist?(dir) && !global_options[:force]
|
34
|
+
exit_now! 'project exist: -f to overwrite'
|
35
|
+
end
|
36
|
+
|
37
|
+
$stdout.puts "created: #{args.first}"
|
38
|
+
starter_gem = Gem::Specification.find_by_name('grape-starter').gem_dir
|
39
|
+
|
40
|
+
src = File.join(starter_gem, 'template', '.')
|
41
|
+
FileUtils.copy_entry src, dir
|
42
|
+
|
43
|
+
FileUtils.cd(dir) do
|
44
|
+
# TODO:
|
45
|
+
$stdout.puts `bundle install`
|
46
|
+
$stdout.puts `bundle exec rubocop -a`
|
47
|
+
$stdout.puts `git init`
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
desc 'Adds a new resource - run from inside the project'
|
53
|
+
long_desc "run this command from inside the project
|
54
|
+
hereby the the given resource name
|
55
|
+
can be given in form of
|
56
|
+
'foo(s)', 'foo_bar(s)''"
|
57
|
+
arg_name 'resource [post* get* put* patch* delete*]'
|
58
|
+
command :add do |c|
|
59
|
+
c.desc 'adds entity file'
|
60
|
+
c.switch [:e, :entity], negatable: false
|
61
|
+
|
62
|
+
c.action do |global_options, options, args|
|
63
|
+
exit_now! 'no resource given' if args.empty?
|
64
|
+
|
65
|
+
resource = args.shift
|
66
|
+
set = args
|
67
|
+
|
68
|
+
begin
|
69
|
+
builder_options = global_options.merge(set: set).merge(options)
|
70
|
+
Starter::Builder.call!(resource, builder_options)
|
71
|
+
created_files = Starter::Builder.save
|
72
|
+
|
73
|
+
`bundle exec rubocop -a #{created_files.join(' ')}`
|
74
|
+
$stdout.puts "added resource: #{resource}"
|
75
|
+
rescue => e
|
76
|
+
exit_now! e
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
desc 'Removes a resource - run from inside the project'
|
82
|
+
arg_name 'resource'
|
83
|
+
command :remove do |c|
|
84
|
+
# c.desc 'adds entity file'
|
85
|
+
# c.switch [:e, :entity], negatable: false
|
86
|
+
|
87
|
+
c.action do |global_options, options, args|
|
88
|
+
exit_now! 'no resource given' if args.empty?
|
89
|
+
resource = args.first
|
90
|
+
|
91
|
+
Starter::Builder.remove!(resource)
|
92
|
+
|
93
|
+
$stdout.puts "removed resource: #{resource}"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
pre do |_global, _command, _options, _args|
|
99
|
+
# Pre logic here
|
100
|
+
# Return true to proceed; false to abort and not call the
|
101
|
+
# chosen command
|
102
|
+
# Use skips_pre before a command to skip this block
|
103
|
+
# on that command only
|
104
|
+
true
|
105
|
+
end
|
106
|
+
|
107
|
+
post do |global, command, options, args|
|
108
|
+
# Post logic here
|
109
|
+
# Use skips_post before a command to skip this
|
110
|
+
# block on that command only
|
111
|
+
end
|
112
|
+
|
113
|
+
on_error do |_exception|
|
114
|
+
# Error logic here
|
115
|
+
# return false to skip default error handling
|
116
|
+
true
|
117
|
+
end
|
118
|
+
|
119
|
+
exit run(ARGV)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'starter/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = 'grape-starter'
|
9
|
+
spec.version = Starter::VERSION
|
10
|
+
spec.authors = ['LeFnord']
|
11
|
+
spec.email = ['pscholz.le@gmail.com']
|
12
|
+
|
13
|
+
spec.summary = 'Create a Grape Rack skeleton'
|
14
|
+
spec.description = 'CLI to create a API skeleton based on Grape and Rack'
|
15
|
+
spec.homepage = 'https://github.com/LeFnord/grape-starter'
|
16
|
+
spec.license = 'MIT'
|
17
|
+
|
18
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
19
|
+
f.match(%r{^(test|spec|features)/})
|
20
|
+
end
|
21
|
+
spec.bindir = 'bin'
|
22
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
23
|
+
spec.require_paths = ['lib']
|
24
|
+
|
25
|
+
spec.add_dependency 'gli', '~> 2.14'
|
26
|
+
spec.add_dependency 'activesupport', '~> 5.0'
|
27
|
+
spec.add_dependency 'rubocop', '~> 0.40'
|
28
|
+
|
29
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
30
|
+
spec.add_development_dependency 'grape', '~> 0.18'
|
31
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
32
|
+
spec.add_development_dependency 'rack-test'
|
33
|
+
spec.add_development_dependency 'pry'
|
34
|
+
spec.add_development_dependency 'awesome_print'
|
35
|
+
|
36
|
+
end
|
data/lib/starter.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'active_support/core_ext/string'
|
3
|
+
|
4
|
+
module Starter
|
5
|
+
require 'starter/builder/names'
|
6
|
+
require 'starter/builder/template_files'
|
7
|
+
require 'starter/builder/template_endpoints'
|
8
|
+
|
9
|
+
class Builder
|
10
|
+
extend Starter::Names
|
11
|
+
extend Template::Files
|
12
|
+
extend Template::Endpoints
|
13
|
+
|
14
|
+
class << self
|
15
|
+
attr_reader :resource, :set, :force, :entity
|
16
|
+
|
17
|
+
def call!(resource, options = {})
|
18
|
+
@resource = resource
|
19
|
+
@set = options[:set]
|
20
|
+
@force = options[:force]
|
21
|
+
@entity = options[:entity]
|
22
|
+
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
def remove!(resource)
|
27
|
+
@resource = resource
|
28
|
+
|
29
|
+
files_to_remove = file_list.map { |x| send("#{x}_name") }
|
30
|
+
FileUtils.rm files_to_remove
|
31
|
+
end
|
32
|
+
|
33
|
+
def save
|
34
|
+
file_list.each do |new_file|
|
35
|
+
save_file(new_file)
|
36
|
+
end
|
37
|
+
|
38
|
+
add_moint_point
|
39
|
+
|
40
|
+
file_list.map { |x| send("#{x}_name") }
|
41
|
+
end
|
42
|
+
|
43
|
+
def endpoints
|
44
|
+
content(endpoint_set).join("\n\n")
|
45
|
+
end
|
46
|
+
|
47
|
+
def endpoint_specs
|
48
|
+
content(endpoint_set.map { |x| "#{x}_spec" }).join("\n")
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def file_list
|
54
|
+
standards = %w(api_file lib_file api_spec lib_spec)
|
55
|
+
|
56
|
+
entity ? standards + ['entity_file'] : standards
|
57
|
+
end
|
58
|
+
|
59
|
+
def save_file(new_file)
|
60
|
+
new_file_name = "#{new_file}_name"
|
61
|
+
should_raise?(send(new_file_name))
|
62
|
+
|
63
|
+
File.open(send(new_file_name), 'w+') { |file| file.write(send(new_file.strip_heredoc)) }
|
64
|
+
end
|
65
|
+
|
66
|
+
def should_raise?(file)
|
67
|
+
raise StandardError, '… resource exists' if File.exist?(file) && !force
|
68
|
+
end
|
69
|
+
|
70
|
+
def add_moint_point
|
71
|
+
file = File.read(api_base_file_name)
|
72
|
+
occurence = file.scan(/(\s+mount.*?\n)/).last.first
|
73
|
+
replacement = occurence + " mount Endpoints::#{klass_name}\n"
|
74
|
+
file.sub!(occurence, replacement)
|
75
|
+
File.open(api_base_file_name, 'w') { |f| f.write(file) }
|
76
|
+
end
|
77
|
+
|
78
|
+
def endpoint_set
|
79
|
+
crud_set = singular? ? singular_one : crud
|
80
|
+
return crud_set if set.blank?
|
81
|
+
|
82
|
+
crud_set.each_with_object([]) { |x, memo| set.map { |y| memo << x if x.to_s.start_with?(y) } }
|
83
|
+
end
|
84
|
+
|
85
|
+
def content(set)
|
86
|
+
set.map { |x| send(x) }
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|