pg_rest 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 14805bcffd4e3ab056ba03d67cbbf95c5b55c8eef8151747128c642a9d6a6ec7
4
+ data.tar.gz: 3b6ae7e62b0c2219becdc4e0f9a5add180c705c063efefad2b017b477d6571f3
5
+ SHA512:
6
+ metadata.gz: ac75e237f676378184bd70e9c0c91656c01a0a413fb338cb632d6238cbf9914e5962dc7994a5de797f10b3ea51dc83056609dfce548f0305814064cabc31a650
7
+ data.tar.gz: bc560603b0b5f5f51d600acff4c962cdc0ffa51059dc6f202926f41efacbe789322e8f7d31710f7e013414ed6fd93caeeaffe17baad8e161d20b1a51abdedc8b
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2021 Rami Bitar
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,206 @@
1
+ # PgRest
2
+ PgRest is a REST API for managing Active Record database migrations.
3
+
4
+ Perform Active Record database migrations to manage database schema migrations.
5
+
6
+ ## Features
7
+ PgRest supports the following database migrations using a REST API:
8
+ - Add table
9
+ - Drop table
10
+ - Add column
11
+ - Remove column
12
+
13
+ PgRest operations are secured using an API token.
14
+
15
+ ## Installation
16
+ Add this line to your application's Gemfile:
17
+
18
+ ```ruby
19
+ gem 'pg_rest'
20
+ ```
21
+
22
+ And then execute:
23
+ ```bash
24
+ $ bundle
25
+ ```
26
+
27
+ Mount the PgRest API by updating your `config/routes.rb` file:
28
+
29
+ ```
30
+ Rails.application.routes.draw do
31
+ ...
32
+ mount PgRest::Engine, at: "/pg-rest"
33
+ ...
34
+ end
35
+ ```
36
+
37
+ You can also configure PgRest with an initializer by creating a file at `config/initializers/pg_rest.rb`.
38
+
39
+ ```
40
+ # Place file at config/initializers/pg_rest.rb
41
+
42
+ PgRest.tap |config|
43
+ config.api_token = ENV['PG_REST_API_TOKEN']
44
+ end
45
+ ```
46
+
47
+ ## Requirements
48
+
49
+ PgRest requires Ruby on Rails and PostgreSQL, and below are recommended versions:
50
+ - Rails 6+
51
+ - Ruby 2.7.4+
52
+ - Active Record supported database.
53
+
54
+ ## Documentation
55
+
56
+ PgRest is designed to remotely create common database migration tasks using a REST API.
57
+
58
+ ### Schema
59
+
60
+ Your database schema is available in order to inspect available tables and column data.
61
+
62
+ ```
63
+ GET /pg-rest
64
+ ```
65
+
66
+ You can inspect any specific table using the schema endpoint:
67
+
68
+ ```
69
+ GET /pg-rest/tables/<table_name>
70
+ ```
71
+
72
+ ### Create table
73
+
74
+ Create a table migration.
75
+
76
+ ```
77
+ POST /pg-rest/tables
78
+ ```
79
+
80
+ Parameters
81
+
82
+ | Parameter | Type | Description |
83
+ | --- | --- |
84
+ | name | string | The name of the database table. |
85
+
86
+
87
+ ### Drop table
88
+
89
+ Drop a database table.
90
+
91
+ ```
92
+ DELETE /pg-rest/tables/:table_name
93
+ ```
94
+
95
+ Parameters
96
+
97
+ | Parameter | Type | Description |
98
+ | --- | --- | --- |
99
+ | table_name | string | The name of the database table to drop.|
100
+
101
+ ### Add column
102
+
103
+ Add a database column.
104
+
105
+ ```
106
+ POST /pg-rest/tables/<table_name>/columns
107
+ ```
108
+
109
+ Parameters
110
+
111
+ | Parameter | Type | Description |
112
+ | --- | --- | --- |
113
+ | table_name | string | The name of the table.|
114
+ | name | string | The column name. |
115
+ | type | string | Active Record supported database field type.|
116
+ | default | boolean | The default value. Defaults to `null`|
117
+ | array | boolean |The name of the database table.|
118
+ | foreign_key | boolean | Column is a foreign_key. Defaults to `false`. |
119
+ | primary_key | boolean | Column is a primary_key. Defaults to `false`. |
120
+
121
+
122
+ ### Remove column
123
+
124
+ Remove a database column.
125
+
126
+ ```
127
+ POST /pg-rest/tables/<table_name>/<column_name>
128
+ ```
129
+
130
+ Parameters
131
+
132
+ | Parameter | Type | Description |
133
+ | --- | --- | --- |
134
+ | table_name | string | The name of the table.|
135
+ | column_name | string | The name of the column to remove.|
136
+
137
+
138
+ ## REST API client
139
+
140
+ PgRest also supports a ruby client for handling the API requests.
141
+
142
+ You can initialize the PgRest client using:
143
+
144
+ ```
145
+ pg_client = PgRest::Api.new(api_key: <API_KEY>, api_url: <API_URL>)
146
+ ```
147
+
148
+ ### Database migrations using PgRest API client
149
+
150
+ Create table:
151
+
152
+ ```
153
+ pg_client.create_table(table_name: <TABLE_NAME>)
154
+ ```
155
+
156
+ Drop table:
157
+
158
+ ```
159
+ pg_client.drop_table(table_name: <TABLE_NAME>)
160
+ ```
161
+
162
+ Add table column:
163
+
164
+ ```
165
+ pg_client.add_column(
166
+ table_name: <TABLE_NAME>,
167
+ name: <COLUMN_NAME>,
168
+ type: <COLUMN_TYPE>,
169
+ default: <DEFAULT_VALUE>,
170
+ array: <IS_ARRAY>,
171
+ primary_key: <IS_PRIMARY_KEY>,
172
+ foreign_key: <IS_FOREIGN_KEY>,
173
+ )
174
+ ```
175
+
176
+ Remove table column:
177
+
178
+ ```
179
+ pg_client.remove_column(
180
+ table_name: <TABLE_NAME>,
181
+ name: <COLUMN_NAME>
182
+ )
183
+ ```
184
+
185
+ ### API Token Authentication
186
+
187
+ The PgRest API is secured using an API token.
188
+
189
+
190
+ ```
191
+ # /config/initializers/pg_rest.rb
192
+
193
+ PgRest.tap do |config|
194
+ config.api_token = ENV['PG_REST_API_TOKEN']
195
+ ...
196
+ end
197
+ ```
198
+
199
+ ## Contributing
200
+ Contributions are welcome by issuing a pull request at our github repository:
201
+ https:/github.com/dash-api/pg-rest
202
+
203
+
204
+ ## License
205
+
206
+ The gem is available as open source under the terms of the [MIT License](https:/opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/setup"
2
+
3
+ APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
4
+ load "rails/tasks/engine.rake"
5
+
6
+ load "rails/tasks/statistics.rake"
7
+
8
+ require "bundler/gem_tasks"
@@ -0,0 +1 @@
1
+ //= link_directory ../stylesheets/pg_rest.css
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,30 @@
1
+ module PgRest
2
+ class ApplicationController < ActionController::Base
3
+
4
+ rescue_from Exception, with: :unprocessable_entity
5
+ rescue_from StandardError, with: :unprocessable_entity
6
+ rescue_from ActiveRecord::RecordNotFound, with: :unprocessable_entity
7
+ rescue_from ActiveRecord::ActiveRecordError, with: :unprocessable_entity
8
+
9
+ def authenticate_request!
10
+ auth_token === PgRest.api_token && !PgRest.api_token.blank?
11
+ end
12
+
13
+ private
14
+
15
+ def auth_token
16
+ http_token || params['token']
17
+ end
18
+
19
+ def http_token
20
+ if request.headers['Authorization'].present?
21
+ request.headers['Authorization'].split(' ').last
22
+ end
23
+ end
24
+
25
+ def unprocessable_entity(e)
26
+ render json: { error: e }, status: :unprocessable_entity
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,45 @@
1
+ module PgRest
2
+ class ColumnsController < ApplicationController
3
+
4
+ skip_before_action :verify_authenticity_token
5
+
6
+ before_action :authenticate_request!
7
+
8
+ def create
9
+ result = PgService.add_column(
10
+ table_name: params[:table_id],
11
+ name: pg_params[:name],
12
+ type: pg_params[:type],
13
+ default: pg_params[:default],
14
+ array: pg_params[:array],
15
+ primary_key: pg_params[:primary_key],
16
+ foreign_key: pg_params[:foreign_key]
17
+ )
18
+ render json: { message: 'Column added.', data: result }
19
+ end
20
+
21
+ def destroy
22
+ result = PgService.remove_column(
23
+ table_name: params[:table_id],
24
+ name: params[:id]
25
+ )
26
+ render json: { message: 'Column removed.', data: result }
27
+ end
28
+
29
+ private
30
+
31
+ def pg_params
32
+ params
33
+ .require(:column)
34
+ .permit(
35
+ :name,
36
+ :type,
37
+ :default,
38
+ :array,
39
+ :foreign_key,
40
+ :primary_key
41
+ )
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,38 @@
1
+ module PgRest
2
+ class TablesController < ApplicationController
3
+
4
+ before_action :authenticate_request!
5
+ skip_before_action :verify_authenticity_token
6
+
7
+ def index
8
+ schema = PgRest::Schema.pg_schema
9
+ render json: { data: schema }
10
+ end
11
+
12
+ def show
13
+ table = PgRest::Schema.table_schema(params[:id])
14
+ render json: { data: table }
15
+ end
16
+
17
+ def create
18
+ PgService.create_table(table_name: pg_params[:name])
19
+ render json: { message: 'Table created.' }
20
+ end
21
+
22
+ def destroy
23
+ PgService.drop_table(table_name: params[:id])
24
+ render json: { message: 'Table dropped.' }
25
+ end
26
+
27
+ private
28
+
29
+ def pg_params
30
+ params
31
+ .require(:table)
32
+ .permit(
33
+ :name
34
+ )
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,4 @@
1
+ module PgRest
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module PgRest
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module PgRest
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: 'from@example.com'
4
+ layout 'mailer'
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module PgRest
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,17 @@
1
+ module PgRest
2
+ class PgTable < ApplicationRecord
3
+ include PgSearch::Model
4
+
5
+ self.abstract_class = true
6
+
7
+ def self.modelize(table_name)
8
+ class_name = table_name.singularize.capitalize
9
+ if Object.const_defined? class_name
10
+ class_name.constantize
11
+ else
12
+ Object.const_set class_name, Class.new(PgRest::PgTable)
13
+ end
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,82 @@
1
+ require 'rest-client'
2
+
3
+ module PgRest
4
+ class Api
5
+
6
+ attr_accessor :api_url, :api_token
7
+
8
+ def initialize(api_url:, api_token: PgRest.api_token)
9
+ @api_url = api_url
10
+ @api_token = api_token
11
+ end
12
+
13
+ def find_table(table_name:)
14
+ url = "#{@api_url}/tables/#{table_name}"
15
+ resp = RestClient.get(url, headers)
16
+ result = handle_response(resp)
17
+ end
18
+
19
+ def create_table(table_name:)
20
+ url = "#{@api_url}/tables"
21
+ params = {
22
+ name: table_name
23
+ }.to_json
24
+ resp = RestClient.post(url, params, headers)
25
+ result = handle_response(resp)
26
+ end
27
+
28
+ def drop_table(table_name:)
29
+ url = "#{@api_url}/tables/#{table_name}"
30
+ resp = RestClient.delete(url, headers)
31
+ result = handle_response(resp)
32
+ end
33
+
34
+ def add_column(
35
+ table_name:,
36
+ name:,
37
+ type:,
38
+ default: nil,
39
+ array: false,
40
+ primary_key: false,
41
+ foreign_key: false
42
+ )
43
+ url = "#{@api_url}/tables/#{table_name}/columns"
44
+ params = {
45
+ column: {
46
+ name: name,
47
+ type: type,
48
+ default: default,
49
+ array: array,
50
+ primary_key: primary_key,
51
+ foreign_key: foreign_key
52
+ }
53
+ }.to_json
54
+ resp = RestClient.post(url, params, headers)
55
+ result = handle_response(resp)
56
+ end
57
+
58
+ def remove_column(table_name:,name:)
59
+ url = "#{@api_url}/tables/#{table_name}/columns/#{name}"
60
+ resp = RestClient.delete(url, headers)
61
+ result = handle_response(resp)
62
+ end
63
+
64
+ def schema
65
+ url = "#{@api_url}/schema"
66
+ resp = RestClient.get(url, headers)
67
+ result = handle_response(resp)
68
+ end
69
+
70
+ def headers
71
+ {
72
+ "Content-Type": "application/json",
73
+ "Authorization": "Bearer #{@api_token}"
74
+ }
75
+ end
76
+
77
+ def handle_response(resp)
78
+ JSON.parse(resp)
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1,51 @@
1
+ module PgRest
2
+ class PgService
3
+
4
+ attr_accessor :uri
5
+
6
+ def initialize
7
+ end
8
+
9
+ def self.create_table(table_name:)
10
+ self.with_transaction do
11
+ ActiveRecord::Migration[6.0].create_table table_name.to_sym do |t|
12
+ t.timestamps
13
+ end
14
+ end
15
+ end
16
+
17
+ def self.drop_table(table_name:)
18
+ self.with_transaction do
19
+ ActiveRecord::Migration[6.0].drop_table table_name.to_sym
20
+ end
21
+ end
22
+
23
+ def self.add_column(
24
+ table_name:,
25
+ name:,
26
+ type:,
27
+ primary_key: false,
28
+ foreign_key: false,
29
+ null: true,
30
+ default: nil,
31
+ array: false
32
+ )
33
+ self.with_transaction do
34
+ ActiveRecord::Migration[6.0].add_column table_name.to_sym, name.to_sym, type.to_sym, null: null, default: default, array: array, foreign_key: foreign_key
35
+ end
36
+ end
37
+
38
+ def self.remove_column(table_name:, name:)
39
+ self.with_transaction do
40
+ ActiveRecord::Migration[6.0].remove_column table_name.to_sym, name.to_sym
41
+ end
42
+ end
43
+
44
+ def self.with_transaction
45
+ ActiveRecord::Base.transaction do
46
+ yield
47
+ end
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,43 @@
1
+ module PgRest
2
+ module Schema
3
+
4
+ attr_accessor :tables
5
+
6
+ def self.table_names
7
+ #ActiveRecord::Base.connection.query_cache.clear
8
+ @tables = ActiveRecord::Base.connection.tables
9
+ end
10
+
11
+ def self.table_schema(table_name)
12
+ @tables = table_names
13
+ pg_table = PgRest::PgTable.modelize(table_name)
14
+ pg_table.reset_column_information
15
+ columns = []
16
+ pg_table.columns.each do |column|
17
+ columns << render_column(column)
18
+ end
19
+ columns
20
+ end
21
+
22
+ def self.pg_schema
23
+ @tables = table_names
24
+ schema = {
25
+ tables: @tables
26
+ }
27
+ @tables.each do |table_name|
28
+ schema[table_name] = table_schema(table_name)
29
+ end
30
+ schema
31
+ end
32
+
33
+ def self.render_column(column)
34
+ {
35
+ name: column.name,
36
+ type: column.sql_type_metadata.type,
37
+ limit: column.sql_type_metadata.limit,
38
+ precision: column.sql_type_metadata.precision,
39
+ }
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>PgRest</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+ <%= stylesheet_link_tag "pg_rest/application", media: "all" %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
data/config/routes.rb ADDED
@@ -0,0 +1,9 @@
1
+ PgRest::Engine.routes.draw do
2
+
3
+ root 'tables#index'
4
+
5
+ resources :tables do
6
+ resources :columns, only: [:create, :destroy]
7
+ end
8
+
9
+ end
@@ -0,0 +1,5 @@
1
+ module PgRest
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace PgRest
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module PgRest
2
+ VERSION = '0.0.2'
3
+ end
data/lib/pg_rest.rb ADDED
@@ -0,0 +1,8 @@
1
+ require "pg_rest/version"
2
+ require "pg_rest/engine"
3
+
4
+ module PgRest
5
+
6
+ mattr_accessor :api_token
7
+
8
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :pg_rest do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pg_rest
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Rami Bitar
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-10-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 6.1.4
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 6.1.4.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: 6.1.4
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 6.1.4.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: pg
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rest-client
49
+ requirement: !ruby/object:Gem::Requirement
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
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: dotenv-rails
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ description: REST API for remote PostgreSQL database migrations.
76
+ email:
77
+ - rami@skillhire.com
78
+ executables: []
79
+ extensions: []
80
+ extra_rdoc_files: []
81
+ files:
82
+ - MIT-LICENSE
83
+ - README.md
84
+ - Rakefile
85
+ - app/assets/config/pg_rest_manifest.js
86
+ - app/assets/stylesheets/pg_rest/application.css
87
+ - app/controllers/pg_rest/application_controller.rb
88
+ - app/controllers/pg_rest/columns_controller.rb
89
+ - app/controllers/pg_rest/tables_controller.rb
90
+ - app/helpers/pg_rest/application_helper.rb
91
+ - app/jobs/pg_rest/application_job.rb
92
+ - app/mailers/pg_rest/application_mailer.rb
93
+ - app/models/pg_rest/application_record.rb
94
+ - app/models/pg_rest/pg_table.rb
95
+ - app/services/pg_rest/api.rb
96
+ - app/services/pg_rest/pg_service.rb
97
+ - app/services/pg_rest/schema.rb
98
+ - app/views/layouts/dash_api/application.html.erb
99
+ - config/routes.rb
100
+ - lib/pg_rest.rb
101
+ - lib/pg_rest/engine.rb
102
+ - lib/pg_rest/version.rb
103
+ - lib/tasks/pg_rest_tasks.rake
104
+ homepage: https://github.com/dash-api/pg-rest
105
+ licenses:
106
+ - MIT
107
+ metadata:
108
+ homepage_uri: https://github.com/dash-api/pg-rest
109
+ source_code_uri: https://github.com/dash-api/pg-rest
110
+ changelog_uri: https://github.com/dash-api/pg-rest
111
+ post_install_message:
112
+ rdoc_options: []
113
+ require_paths:
114
+ - lib
115
+ required_ruby_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ requirements: []
126
+ rubygems_version: 3.1.6
127
+ signing_key:
128
+ specification_version: 4
129
+ summary: REST API for PostgreSQL database migrations.
130
+ test_files: []