pico_api 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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/LICENSE +21 -0
- data/Rakefile +5 -0
- data/Readme.md +56 -0
- data/bin/console +15 -0
- data/bin/pico_api +14 -0
- data/bin/setup +8 -0
- data/lib/pico_api/configuration.rb +30 -0
- data/lib/pico_api/database.rb +24 -0
- data/lib/pico_api/entities/error.rb +22 -0
- data/lib/pico_api/entities/errors.rb +22 -0
- data/lib/pico_api/generators/commands/base.rb +45 -0
- data/lib/pico_api/generators/commands/copy_template.rb +19 -0
- data/lib/pico_api/generators/commands/create_base.rb +29 -0
- data/lib/pico_api/generators/commands/create_config_application.rb +19 -0
- data/lib/pico_api/generators/commands/create_config_boot.rb +19 -0
- data/lib/pico_api/generators/commands/create_config_configuration.rb +19 -0
- data/lib/pico_api/generators/commands/create_config_database_setup.rb +19 -0
- data/lib/pico_api/generators/commands/create_config_database_yml.rb +19 -0
- data/lib/pico_api/generators/commands/create_config_dotenv.rb +19 -0
- data/lib/pico_api/generators/commands/create_config_ru.rb +19 -0
- data/lib/pico_api/generators/commands/create_gemfile.rb +19 -0
- data/lib/pico_api/generators/commands/create_gitignore.rb +19 -0
- data/lib/pico_api/generators/commands/create_rakefile.rb +19 -0
- data/lib/pico_api/generators/commands/create_template.rb +21 -0
- data/lib/pico_api/generators/generator.rb +40 -0
- data/lib/pico_api/generators/templates/.gitignore +2 -0
- data/lib/pico_api/generators/templates/Gemfile.erb +7 -0
- data/lib/pico_api/generators/templates/Rakefile.erb +9 -0
- data/lib/pico_api/generators/templates/config/application.erb +5 -0
- data/lib/pico_api/generators/templates/config/boot.erb +9 -0
- data/lib/pico_api/generators/templates/config/configuration.erb +13 -0
- data/lib/pico_api/generators/templates/config/database.yml +8 -0
- data/lib/pico_api/generators/templates/config/database_setup.erb +6 -0
- data/lib/pico_api/generators/templates/config/dotenv.erb +6 -0
- data/lib/pico_api/generators/templates/config.ru.erb +3 -0
- data/lib/pico_api/handlers/errors.rb +23 -0
- data/lib/pico_api/json_api_renderer.rb +11 -0
- data/lib/pico_api/serializers/base.rb +11 -0
- data/lib/pico_api/version.rb +5 -0
- data/lib/pico_api.rb +30 -0
- data/pico_api.gemspec +33 -0
- metadata +197 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 42f576489c0e3b0b4cc8ab9d23d3dd273f50f3fcd6cf29689b26a67ee6508c3f
|
4
|
+
data.tar.gz: 83723e1d3095b13f302d016b8a3f2b166220a7e42842b569ef77cfd86f76648e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7eb82db803e9e5f78d7c78ecf8a2054dfbd523f200331586e8ac1e9c45c38c837fdae794c4296c593627c97a976382aca69b77a478359d8473e882435dcb936f
|
7
|
+
data.tar.gz: 43935b1f888497e2dafc4f488d53ecc4b55fdd48efa112ef6ca659b37cc94c4f8bbdef392ef30857ac0c474490a88d4e60cf8c1c2e2fb0186a6e719727fb17cf
|
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2022 Alex Avlonitis
|
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/Rakefile
ADDED
data/Readme.md
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# Pico API
|
2
|
+
|
3
|
+
A tiny boilerplate JSON API template in ruby. Its minimal footprint makes it ideal for microservices or even full blown APIs.
|
4
|
+
It has been created for those who don't need the RAILS "magic" and bloat. Can easily create different architectures, like STAR, CQRS..., and MVC.
|
5
|
+
|
6
|
+
Pico API is just a collection of the fastest ruby libraries put together to form a basic API environment, with the JSON:API specification. It doesn't create any folder structures for your business logic, it only creates the initial configurations to get you started.
|
7
|
+
|
8
|
+
Example demo project can be found [here](https://github.com/alexavlonitis/pico_api_example)
|
9
|
+
|
10
|
+
## Libraries Used
|
11
|
+
|
12
|
+
- [roda](https://github.com/jeremyevans/roda) -> Routing
|
13
|
+
- [rom-rb](https://github.com/rom-rb/rom) -> ORM
|
14
|
+
- [jsonapi serializer](https://github.com/jsonapi-serializer/jsonapi-serializer) -> Fast-jsonapi fork
|
15
|
+
|
16
|
+
## Usage
|
17
|
+
|
18
|
+
### Create your app
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
gem install pico_api
|
22
|
+
|
23
|
+
pico_api --new my_app
|
24
|
+
|
25
|
+
cd my_app
|
26
|
+
|
27
|
+
bundle install
|
28
|
+
```
|
29
|
+
|
30
|
+
### Configure your database
|
31
|
+
|
32
|
+
Migration info: https://rom-rb.org/5.0/learn/sql/migrations/
|
33
|
+
|
34
|
+
- Add the database config details in `config/database.yml`
|
35
|
+
- Setup the Database: `rake db:setup`
|
36
|
+
- Create a migration: `rake db:create_migration[create_users]` (include your preferred DB gem in the Gemfile)
|
37
|
+
- Run the migrations: `rake db:migrate`
|
38
|
+
- Run the server: `rackup -p 3001`
|
39
|
+
|
40
|
+
|
41
|
+
## Development
|
42
|
+
- [x] Create Database config
|
43
|
+
- [x] Hook a json-api library
|
44
|
+
- [x] Handle Errors
|
45
|
+
- [ ] Create a Logger config
|
46
|
+
- [ ] Create a testing environment
|
47
|
+
- [ ] Allow multiple db gateways in the config
|
48
|
+
- [ ] Add irb/pry console script
|
49
|
+
|
50
|
+
## Contributing
|
51
|
+
|
52
|
+
All Pull Requests are welcome, from a single typo to a new feature.
|
53
|
+
|
54
|
+
- Fork this repo
|
55
|
+
- Create a new branch, add your changes with tests when necessary
|
56
|
+
- Submit a Pull Request
|
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'pico_api'
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require 'irb'
|
15
|
+
IRB.start(__FILE__)
|
data/bin/pico_api
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
|
2
|
+
#!/usr/bin/env ruby
|
3
|
+
|
4
|
+
require 'optparse'
|
5
|
+
require 'pico_api'
|
6
|
+
|
7
|
+
options = {}
|
8
|
+
OptionParser.new do |opts|
|
9
|
+
opts.banner = "Usage: pico_api [options]"
|
10
|
+
|
11
|
+
opts.on('-n', '--new project_name') { |o| options[:project_name] = o }
|
12
|
+
end.parse!
|
13
|
+
|
14
|
+
PicoApi::Generators::Generator.call(options[:project_name])
|
data/bin/setup
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'erb'
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
module PicoApi
|
7
|
+
class << self
|
8
|
+
def configuration
|
9
|
+
@configuration ||= Configuration.new(db_config)
|
10
|
+
end
|
11
|
+
|
12
|
+
def db_config
|
13
|
+
template = ERB.new(File.new('./config/database.yml').read)
|
14
|
+
YAML.safe_load(template.result(binding))
|
15
|
+
end
|
16
|
+
|
17
|
+
def configure
|
18
|
+
yield(configuration)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class Configuration
|
23
|
+
attr_reader :db_config
|
24
|
+
attr_accessor :namespace, :lib_path, :errors_map
|
25
|
+
|
26
|
+
def initialize(db_config)
|
27
|
+
@db_config = db_config
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rom'
|
4
|
+
require 'rom-sql'
|
5
|
+
|
6
|
+
module PicoApi
|
7
|
+
class Database
|
8
|
+
class << self
|
9
|
+
attr_accessor :container
|
10
|
+
|
11
|
+
def setup!
|
12
|
+
database_config = PicoApi.configuration.db_config['default']
|
13
|
+
adapter = database_config['adapter'].to_sym
|
14
|
+
options = database_config['options'].symbolize_keys
|
15
|
+
connection_string = database_config['connection_string']
|
16
|
+
|
17
|
+
config = ROM::Configuration.new(adapter, connection_string, options)
|
18
|
+
yield config if block_given?
|
19
|
+
|
20
|
+
@container = ROM.container(config)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'securerandom'
|
4
|
+
|
5
|
+
module PicoApi
|
6
|
+
module Entities
|
7
|
+
class Error < ROM::Struct
|
8
|
+
attribute? :title, ROM::Types::String
|
9
|
+
attribute? :status, ROM::Types::String.optional
|
10
|
+
attribute? :code, ROM::Types::String.optional
|
11
|
+
attribute? :detail, ROM::Types::String.optional
|
12
|
+
|
13
|
+
def to_h
|
14
|
+
id.merge(super)
|
15
|
+
end
|
16
|
+
|
17
|
+
def id
|
18
|
+
{ id: SecureRandom.hex(5) }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PicoApi
|
4
|
+
module Entities
|
5
|
+
class Errors < ROM::Struct
|
6
|
+
class << self
|
7
|
+
def call(error)
|
8
|
+
class_name = error.class.name.demodulize
|
9
|
+
error_entities = [
|
10
|
+
Entities::Error.new(
|
11
|
+
title: class_name.underscore,
|
12
|
+
detail: error.message
|
13
|
+
)
|
14
|
+
]
|
15
|
+
new(errors: error_entities)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
attribute? :errors, ROM::Types::Array(Entities::Error)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'erb'
|
5
|
+
|
6
|
+
module PicoApi
|
7
|
+
module Generators
|
8
|
+
module Commands
|
9
|
+
class Base
|
10
|
+
def self.call(project_name)
|
11
|
+
new(project_name).call
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(project_name)
|
15
|
+
@project_name_camelcased = project_name.camelize
|
16
|
+
@project_name_snakecased = project_name.underscore
|
17
|
+
end
|
18
|
+
|
19
|
+
def call
|
20
|
+
NotImplementError
|
21
|
+
end
|
22
|
+
|
23
|
+
def get_binding
|
24
|
+
binding
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :project_name_camelised, :project_name_snakecased
|
30
|
+
|
31
|
+
def erb
|
32
|
+
ERB.new(File.read(template_full_path))
|
33
|
+
end
|
34
|
+
|
35
|
+
def template_full_path
|
36
|
+
File.join(PicoApi.lib_path, template_relative_path)
|
37
|
+
end
|
38
|
+
|
39
|
+
def template_relative_path
|
40
|
+
''
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PicoApi
|
4
|
+
module Generators
|
5
|
+
module Commands
|
6
|
+
class CopyTemplate < Base
|
7
|
+
def call
|
8
|
+
copy_file
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def copy_file
|
14
|
+
FileUtils.cp(template_full_path, "#{project_name_snakecased}#{destination_path}")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PicoApi
|
4
|
+
module Generators
|
5
|
+
module Commands
|
6
|
+
class CreateBase < Base
|
7
|
+
def call
|
8
|
+
create_bin_folder
|
9
|
+
create_lib_folder
|
10
|
+
create_config_folder
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def create_bin_folder
|
16
|
+
FileUtils.mkdir_p("#{project_name_snakecased}/bin")
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_lib_folder
|
20
|
+
FileUtils.mkdir_p("#{project_name_snakecased}/lib/#{project_name_snakecased}")
|
21
|
+
end
|
22
|
+
|
23
|
+
def create_config_folder
|
24
|
+
FileUtils.mkdir_p("#{project_name_snakecased}/config")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PicoApi
|
4
|
+
module Generators
|
5
|
+
module Commands
|
6
|
+
class CreateConfigApplication < CreateTemplate
|
7
|
+
private
|
8
|
+
|
9
|
+
def destination_path
|
10
|
+
'/config/application.rb'
|
11
|
+
end
|
12
|
+
|
13
|
+
def template_relative_path
|
14
|
+
'/generators/templates/config/application.erb'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PicoApi
|
4
|
+
module Generators
|
5
|
+
module Commands
|
6
|
+
class CreateConfigBoot < CopyTemplate
|
7
|
+
private
|
8
|
+
|
9
|
+
def destination_path
|
10
|
+
'/config/boot.rb'
|
11
|
+
end
|
12
|
+
|
13
|
+
def template_relative_path
|
14
|
+
'/generators/templates/config/boot.erb'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PicoApi
|
4
|
+
module Generators
|
5
|
+
module Commands
|
6
|
+
class CreateConfigConfiguration < CreateTemplate
|
7
|
+
private
|
8
|
+
|
9
|
+
def destination_path
|
10
|
+
'/config/configuration.rb'
|
11
|
+
end
|
12
|
+
|
13
|
+
def template_relative_path
|
14
|
+
'/generators/templates/config/configuration.erb'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PicoApi
|
4
|
+
module Generators
|
5
|
+
module Commands
|
6
|
+
class CreateConfigDatabaseSetup < CopyTemplate
|
7
|
+
private
|
8
|
+
|
9
|
+
def destination_path
|
10
|
+
'/config/database_setup.rb'
|
11
|
+
end
|
12
|
+
|
13
|
+
def template_relative_path
|
14
|
+
'/generators/templates/config/database_setup.erb'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PicoApi
|
4
|
+
module Generators
|
5
|
+
module Commands
|
6
|
+
class CreateConfigDatabaseYml < CopyTemplate
|
7
|
+
private
|
8
|
+
|
9
|
+
def destination_path
|
10
|
+
'/config/database.yml'
|
11
|
+
end
|
12
|
+
|
13
|
+
def template_relative_path
|
14
|
+
'/generators/templates/config/database.yml'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PicoApi
|
4
|
+
module Generators
|
5
|
+
module Commands
|
6
|
+
class CreateConfigDotenv < CopyTemplate
|
7
|
+
private
|
8
|
+
|
9
|
+
def destination_path
|
10
|
+
'/config/dotenv.rb'
|
11
|
+
end
|
12
|
+
|
13
|
+
def template_relative_path
|
14
|
+
'/generators/templates/config/dotenv.erb'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PicoApi
|
4
|
+
module Generators
|
5
|
+
module Commands
|
6
|
+
class CreateConfigRu < CreateTemplate
|
7
|
+
private
|
8
|
+
|
9
|
+
def destination_path
|
10
|
+
'/config.ru'
|
11
|
+
end
|
12
|
+
|
13
|
+
def template_relative_path
|
14
|
+
'/generators/templates/config.ru.erb'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PicoApi
|
4
|
+
module Generators
|
5
|
+
module Commands
|
6
|
+
class CreateGemfile < CopyTemplate
|
7
|
+
private
|
8
|
+
|
9
|
+
def destination_path
|
10
|
+
'/Gemfile'
|
11
|
+
end
|
12
|
+
|
13
|
+
def template_relative_path
|
14
|
+
'/generators/templates/Gemfile.erb'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PicoApi
|
4
|
+
module Generators
|
5
|
+
module Commands
|
6
|
+
class CreateGitignore < CopyTemplate
|
7
|
+
private
|
8
|
+
|
9
|
+
def destination_path
|
10
|
+
'/.gitignore'
|
11
|
+
end
|
12
|
+
|
13
|
+
def template_relative_path
|
14
|
+
'/generators/templates/.gitignore'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PicoApi
|
4
|
+
module Generators
|
5
|
+
module Commands
|
6
|
+
class CreateRakefile < CopyTemplate
|
7
|
+
private
|
8
|
+
|
9
|
+
def destination_path
|
10
|
+
'/Rakefile'
|
11
|
+
end
|
12
|
+
|
13
|
+
def template_relative_path
|
14
|
+
'/generators/templates/Rakefile.erb'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PicoApi
|
4
|
+
module Generators
|
5
|
+
module Commands
|
6
|
+
class CreateTemplate < Base
|
7
|
+
def call
|
8
|
+
create_file
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def create_file
|
14
|
+
File.open("#{project_name_snakecased}#{destination_path}", 'w') do |f|
|
15
|
+
f.write(erb.result(get_binding))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PicoApi
|
4
|
+
module Generators
|
5
|
+
class Generator
|
6
|
+
class << self
|
7
|
+
def call(project_name)
|
8
|
+
commands = load_commands
|
9
|
+
new(project_name, commands).call
|
10
|
+
end
|
11
|
+
|
12
|
+
def load_commands
|
13
|
+
skip_commands = %w[base copytemplate createtemplate]
|
14
|
+
|
15
|
+
Dir[File.join(PicoApi.lib_path, '/generators/commands/*.rb')].sort.map do |file_path|
|
16
|
+
file_name = file_path.split('/').last.gsub('.rb', '').camelize
|
17
|
+
next if skip_commands.include?(file_name.downcase)
|
18
|
+
|
19
|
+
"PicoApi::Generators::Commands::#{file_name}".constantize
|
20
|
+
end.compact
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(project_name, commands = [])
|
25
|
+
raise 'Missing project name' unless project_name
|
26
|
+
|
27
|
+
@project_name = project_name
|
28
|
+
@commands = commands
|
29
|
+
end
|
30
|
+
|
31
|
+
def call
|
32
|
+
commands.each { |command| command.call(project_name) }
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
attr_reader :project_name, :commands
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require "pico_api"
|
2
|
+
require "./config/dotenv" if ENV['PICO_API_ENV'] == "development"
|
3
|
+
require "./config/configuration"
|
4
|
+
require "./config/database_setup"
|
5
|
+
require "./config/application"
|
6
|
+
|
7
|
+
loader = Zeitwerk::Loader.new
|
8
|
+
loader.push_dir("./lib")
|
9
|
+
loader.setup
|
@@ -0,0 +1,13 @@
|
|
1
|
+
PicoApi.configure do |config|
|
2
|
+
## the base namespace of your app
|
3
|
+
config.namespace = "<%= @project_name_camelcased %>"
|
4
|
+
|
5
|
+
## the root directory where all the business logic resides
|
6
|
+
config.lib_path = "lib/<%= @project_name_snakecased %>"
|
7
|
+
|
8
|
+
## Add your custom exception mappings -> { exception: status_code }.
|
9
|
+
# PicoApi serializes runtime exceptions to json-api specification error objects
|
10
|
+
config.errors_map = {
|
11
|
+
StandardError: :unprocessable_entity
|
12
|
+
}.freeze
|
13
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PicoApi
|
4
|
+
module Handlers
|
5
|
+
class Errors
|
6
|
+
def self.call(error, response)
|
7
|
+
exception_key = error.class.name.demodulize.to_sym
|
8
|
+
status = PicoApi.configuration.errors_map[exception_key]
|
9
|
+
return system_error(error, response) unless status
|
10
|
+
|
11
|
+
response.status = status
|
12
|
+
Entities::Errors.call(error).to_h
|
13
|
+
end
|
14
|
+
|
15
|
+
ServerError = Struct.new(:message)
|
16
|
+
def self.system_error(error, response)
|
17
|
+
response.status = :internal_server_error
|
18
|
+
error = ServerError.new('Something went wrong, we are investigating')
|
19
|
+
Entities::Errors.call(error).to_h
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/pico_api.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'roda'
|
4
|
+
require 'zeitwerk'
|
5
|
+
|
6
|
+
loader = Zeitwerk::Loader.for_gem
|
7
|
+
loader.setup
|
8
|
+
|
9
|
+
module PicoApi
|
10
|
+
def self.root_path
|
11
|
+
File.dirname(__dir__)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.lib_path
|
15
|
+
File.join(root_path, 'lib/pico_api')
|
16
|
+
end
|
17
|
+
|
18
|
+
class Application < Roda
|
19
|
+
parser = proc { |data| JSON.parse(data, symbolize_names: true) }
|
20
|
+
|
21
|
+
plugin :symbol_status
|
22
|
+
plugin :json_parser, parser: parser
|
23
|
+
plugin :json, content_type: 'application/vnd.api+json'
|
24
|
+
plugin :error_handler do |e|
|
25
|
+
PicoApi::Handlers::Errors.call(e, response)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
loader.eager_load
|
data/pico_api.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lib/pico_api/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'pico_api'
|
7
|
+
spec.version = PicoApi::VERSION
|
8
|
+
spec.authors = ['Alex Avlonitis']
|
9
|
+
|
10
|
+
spec.summary = 'A tiny Rack-based ruby template for APIs'
|
11
|
+
spec.description = 'A tiny Rack-based ruby template for APIs'
|
12
|
+
spec.homepage = 'https://github.com/alexavlonitis/pico_api'
|
13
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
|
14
|
+
|
15
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
16
|
+
|
17
|
+
# Specify which files should be added to the gem when it is released.
|
18
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
19
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
20
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
21
|
+
end
|
22
|
+
spec.require_paths = ['lib']
|
23
|
+
spec.executables << 'pico_api'
|
24
|
+
|
25
|
+
spec.add_runtime_dependency 'erb', '~> 2.2.3'
|
26
|
+
spec.add_runtime_dependency 'jsonapi-serializer', '~> 2.2.0'
|
27
|
+
spec.add_runtime_dependency 'rackup', '~> 0.2.2'
|
28
|
+
spec.add_runtime_dependency 'rake', '~> 13.0.6'
|
29
|
+
spec.add_runtime_dependency 'roda', '~> 3.61.0'
|
30
|
+
spec.add_runtime_dependency 'rom', '~> 5.2.6'
|
31
|
+
spec.add_runtime_dependency 'rom-sql', '~> 3.5.0'
|
32
|
+
spec.add_runtime_dependency 'zeitwerk', '~> 2.6.1'
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,197 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pico_api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alex Avlonitis
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-10-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: erb
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 2.2.3
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 2.2.3
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: jsonapi-serializer
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.2.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.2.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rackup
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.2.2
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.2.2
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 13.0.6
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 13.0.6
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: roda
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 3.61.0
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 3.61.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rom
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 5.2.6
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 5.2.6
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rom-sql
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 3.5.0
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 3.5.0
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: zeitwerk
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 2.6.1
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 2.6.1
|
125
|
+
description: A tiny Rack-based ruby template for APIs
|
126
|
+
email:
|
127
|
+
executables:
|
128
|
+
- pico_api
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- ".gitignore"
|
133
|
+
- LICENSE
|
134
|
+
- Rakefile
|
135
|
+
- Readme.md
|
136
|
+
- bin/console
|
137
|
+
- bin/pico_api
|
138
|
+
- bin/setup
|
139
|
+
- lib/pico_api.rb
|
140
|
+
- lib/pico_api/configuration.rb
|
141
|
+
- lib/pico_api/database.rb
|
142
|
+
- lib/pico_api/entities/error.rb
|
143
|
+
- lib/pico_api/entities/errors.rb
|
144
|
+
- lib/pico_api/generators/commands/base.rb
|
145
|
+
- lib/pico_api/generators/commands/copy_template.rb
|
146
|
+
- lib/pico_api/generators/commands/create_base.rb
|
147
|
+
- lib/pico_api/generators/commands/create_config_application.rb
|
148
|
+
- lib/pico_api/generators/commands/create_config_boot.rb
|
149
|
+
- lib/pico_api/generators/commands/create_config_configuration.rb
|
150
|
+
- lib/pico_api/generators/commands/create_config_database_setup.rb
|
151
|
+
- lib/pico_api/generators/commands/create_config_database_yml.rb
|
152
|
+
- lib/pico_api/generators/commands/create_config_dotenv.rb
|
153
|
+
- lib/pico_api/generators/commands/create_config_ru.rb
|
154
|
+
- lib/pico_api/generators/commands/create_gemfile.rb
|
155
|
+
- lib/pico_api/generators/commands/create_gitignore.rb
|
156
|
+
- lib/pico_api/generators/commands/create_rakefile.rb
|
157
|
+
- lib/pico_api/generators/commands/create_template.rb
|
158
|
+
- lib/pico_api/generators/generator.rb
|
159
|
+
- lib/pico_api/generators/templates/.gitignore
|
160
|
+
- lib/pico_api/generators/templates/Gemfile.erb
|
161
|
+
- lib/pico_api/generators/templates/Rakefile.erb
|
162
|
+
- lib/pico_api/generators/templates/config.ru.erb
|
163
|
+
- lib/pico_api/generators/templates/config/application.erb
|
164
|
+
- lib/pico_api/generators/templates/config/boot.erb
|
165
|
+
- lib/pico_api/generators/templates/config/configuration.erb
|
166
|
+
- lib/pico_api/generators/templates/config/database.yml
|
167
|
+
- lib/pico_api/generators/templates/config/database_setup.erb
|
168
|
+
- lib/pico_api/generators/templates/config/dotenv.erb
|
169
|
+
- lib/pico_api/handlers/errors.rb
|
170
|
+
- lib/pico_api/json_api_renderer.rb
|
171
|
+
- lib/pico_api/serializers/base.rb
|
172
|
+
- lib/pico_api/version.rb
|
173
|
+
- pico_api.gemspec
|
174
|
+
homepage: https://github.com/alexavlonitis/pico_api
|
175
|
+
licenses: []
|
176
|
+
metadata:
|
177
|
+
homepage_uri: https://github.com/alexavlonitis/pico_api
|
178
|
+
post_install_message:
|
179
|
+
rdoc_options: []
|
180
|
+
require_paths:
|
181
|
+
- lib
|
182
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
183
|
+
requirements:
|
184
|
+
- - ">="
|
185
|
+
- !ruby/object:Gem::Version
|
186
|
+
version: 2.3.0
|
187
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
188
|
+
requirements:
|
189
|
+
- - ">="
|
190
|
+
- !ruby/object:Gem::Version
|
191
|
+
version: '0'
|
192
|
+
requirements: []
|
193
|
+
rubygems_version: 3.1.6
|
194
|
+
signing_key:
|
195
|
+
specification_version: 4
|
196
|
+
summary: A tiny Rack-based ruby template for APIs
|
197
|
+
test_files: []
|