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.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/LICENSE +21 -0
  4. data/Rakefile +5 -0
  5. data/Readme.md +56 -0
  6. data/bin/console +15 -0
  7. data/bin/pico_api +14 -0
  8. data/bin/setup +8 -0
  9. data/lib/pico_api/configuration.rb +30 -0
  10. data/lib/pico_api/database.rb +24 -0
  11. data/lib/pico_api/entities/error.rb +22 -0
  12. data/lib/pico_api/entities/errors.rb +22 -0
  13. data/lib/pico_api/generators/commands/base.rb +45 -0
  14. data/lib/pico_api/generators/commands/copy_template.rb +19 -0
  15. data/lib/pico_api/generators/commands/create_base.rb +29 -0
  16. data/lib/pico_api/generators/commands/create_config_application.rb +19 -0
  17. data/lib/pico_api/generators/commands/create_config_boot.rb +19 -0
  18. data/lib/pico_api/generators/commands/create_config_configuration.rb +19 -0
  19. data/lib/pico_api/generators/commands/create_config_database_setup.rb +19 -0
  20. data/lib/pico_api/generators/commands/create_config_database_yml.rb +19 -0
  21. data/lib/pico_api/generators/commands/create_config_dotenv.rb +19 -0
  22. data/lib/pico_api/generators/commands/create_config_ru.rb +19 -0
  23. data/lib/pico_api/generators/commands/create_gemfile.rb +19 -0
  24. data/lib/pico_api/generators/commands/create_gitignore.rb +19 -0
  25. data/lib/pico_api/generators/commands/create_rakefile.rb +19 -0
  26. data/lib/pico_api/generators/commands/create_template.rb +21 -0
  27. data/lib/pico_api/generators/generator.rb +40 -0
  28. data/lib/pico_api/generators/templates/.gitignore +2 -0
  29. data/lib/pico_api/generators/templates/Gemfile.erb +7 -0
  30. data/lib/pico_api/generators/templates/Rakefile.erb +9 -0
  31. data/lib/pico_api/generators/templates/config/application.erb +5 -0
  32. data/lib/pico_api/generators/templates/config/boot.erb +9 -0
  33. data/lib/pico_api/generators/templates/config/configuration.erb +13 -0
  34. data/lib/pico_api/generators/templates/config/database.yml +8 -0
  35. data/lib/pico_api/generators/templates/config/database_setup.erb +6 -0
  36. data/lib/pico_api/generators/templates/config/dotenv.erb +6 -0
  37. data/lib/pico_api/generators/templates/config.ru.erb +3 -0
  38. data/lib/pico_api/handlers/errors.rb +23 -0
  39. data/lib/pico_api/json_api_renderer.rb +11 -0
  40. data/lib/pico_api/serializers/base.rb +11 -0
  41. data/lib/pico_api/version.rb +5 -0
  42. data/lib/pico_api.rb +30 -0
  43. data/pico_api.gemspec +33 -0
  44. 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
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ *.gem
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
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+
5
+ task default: :spec
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,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -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,2 @@
1
+ .env
2
+ *.db
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "pico_api"
4
+
5
+ group :development, :test do
6
+ gem "dotenv"
7
+ end
@@ -0,0 +1,9 @@
1
+ require "pico_api"
2
+ require "./config/dotenv"
3
+ require 'rom/sql/rake_task'
4
+
5
+ namespace :db do
6
+ task :setup do
7
+ ROM::SQL::RakeSupport.env = ROM.container(default: [:sql, ENV.fetch("DB_CONNECTION_STRING")])
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ module <%= @project_name_camelcased %>
2
+ class Application < PicoApi::Application
3
+ # Add routing instructions here. https://github.com/jeremyevans/roda
4
+ end
5
+ 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,8 @@
1
+ # https://rom-rb.org/5.0/learn/sql/#general-connection-options
2
+
3
+ default:
4
+ adapter:
5
+ connection_string:
6
+ options:
7
+ encoding:
8
+
@@ -0,0 +1,6 @@
1
+ PicoApi::Database.setup! do |config|
2
+ config.auto_registration(
3
+ File.expand_path(PicoApi.configuration.lib_path, './'),
4
+ namespace: PicoApi.configuration.namespace
5
+ )
6
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ unless ENV["RACK_ENV"] == "production"
4
+ require "dotenv"
5
+ Dotenv.overload ".env", ".env.local", ".env.#{ENV.fetch('RACK_ENV', nil)}"
6
+ end
@@ -0,0 +1,3 @@
1
+ require './config/boot'
2
+
3
+ run <%= @project_name_camelcased %>::Application.freeze.app
@@ -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
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PicoApi
4
+ module JsonApiRenderer
5
+ def serialize(resource, **opts)
6
+ serializer_klass = opts.delete(:serializer)
7
+ serializer = serializer_klass.new(resource, opts)
8
+ serializer.serializable_hash
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'jsonapi/serializer'
4
+
5
+ module PicoApi
6
+ module Serializers
7
+ class Base
8
+ include JSONAPI::Serializer
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PicoApi
4
+ VERSION = '0.0.1'
5
+ 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: []