schemaless_rest_api 0.3.1 → 0.3.4
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 +4 -4
- data/lib/schemaless_rest_api/mongo_client.rb +19 -15
- data/lib/schemaless_rest_api/rest_server.rb +45 -18
- data/lib/schemaless_rest_api/version.rb +3 -1
- data/lib/schemaless_rest_api.rb +26 -15
- metadata +9 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c6884db983603d3fe99853d2daf2448c5a112535d427c4dcf93085c03d0d572
|
4
|
+
data.tar.gz: 233cf6a115128268144a612ff02e5de53c32b4f1dc0cb3e46a53f15ebc776e9d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6fddf98f70498d9efee708f86ba28a3ddc4da8b53c029886c964ba8be2078d8bc459d025c50236bb11c9992a8a4ef5edd62d3a05491d8686ac481c2d6a61238a
|
7
|
+
data.tar.gz: ad73ffe9c66723853b0e0a9dc6ecaeb30371b7b12ceb33267715de10dcac052bb3d2107ad3fd4d93bff978239077d2a9434e526b8a32dc550676145b4d0b7db9
|
@@ -1,4 +1,6 @@
|
|
1
|
-
require
|
1
|
+
require "mongo"
|
2
|
+
|
3
|
+
# typed: false - MongoClient new
|
2
4
|
|
3
5
|
module MongoClient
|
4
6
|
class << self
|
@@ -7,11 +9,11 @@ module MongoClient
|
|
7
9
|
|
8
10
|
def insert(model, data, id)
|
9
11
|
collection = MongoClient.client[model]
|
10
|
-
collection.insert_one({ id: id, **data})
|
12
|
+
collection.insert_one({ id: id, **data })
|
11
13
|
end
|
12
14
|
|
13
15
|
def find(model, id)
|
14
|
-
find_all(model, { id: id }
|
16
|
+
find_all(model, { id: id })
|
15
17
|
end
|
16
18
|
|
17
19
|
def get_all(model)
|
@@ -24,7 +26,7 @@ module MongoClient
|
|
24
26
|
|
25
27
|
def find_all(model, query)
|
26
28
|
collection = MongoClient.client[model]
|
27
|
-
collection.find(
|
29
|
+
collection.find(query).collect do |match|
|
28
30
|
match.delete("_id")
|
29
31
|
match
|
30
32
|
end
|
@@ -32,7 +34,7 @@ module MongoClient
|
|
32
34
|
|
33
35
|
def update(model, id, data)
|
34
36
|
collection = MongoClient.client[model]
|
35
|
-
collection.update_one({ id: id }, { id: id, **data})
|
37
|
+
collection.update_one({ id: id }, { id: id, **data })
|
36
38
|
end
|
37
39
|
|
38
40
|
def delete(model, id)
|
@@ -42,13 +44,15 @@ module MongoClient
|
|
42
44
|
end
|
43
45
|
end
|
44
46
|
|
45
|
-
if ENV[
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
47
|
+
MongoClient.client = if ENV["mongo_root_password"]
|
48
|
+
Mongo::Client.new(
|
49
|
+
["#{ENV["mongodb"]}:27017"],
|
50
|
+
database: "api", password: ENV["mongo_root_password"],
|
51
|
+
user: "root"
|
52
|
+
)
|
53
|
+
else
|
54
|
+
Mongo::Client.new(
|
55
|
+
["#{ENV["mongodb"]}:27017"],
|
56
|
+
database: "api"
|
57
|
+
)
|
58
|
+
end
|
@@ -1,10 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "sinatra"
|
4
|
-
require
|
4
|
+
require "docdsl"
|
5
5
|
require "puma"
|
6
|
-
require
|
6
|
+
require "route_downcaser"
|
7
7
|
|
8
|
+
# Server with endpoints generated based on Entities with CRUD operations for them
|
8
9
|
class RestServer < Sinatra::Base
|
9
10
|
set :server, :puma
|
10
11
|
enable :logging if ENV["debug"] == "true"
|
@@ -35,8 +36,8 @@ class RestServer < Sinatra::Base
|
|
35
36
|
end
|
36
37
|
get "/" do
|
37
38
|
summary = { models: Entities.models.keys.to_s,
|
38
|
-
docs_url:
|
39
|
-
summary[:db] = MongoClient.client.summary.to_s if ENV[
|
39
|
+
docs_url: "<a href=/docs>/docs</a>" }
|
40
|
+
summary[:db] = MongoClient.client.summary.to_s if ENV["mongodb"]
|
40
41
|
JSON.generate(summary)
|
41
42
|
rescue Exception => e
|
42
43
|
[500, e.message]
|
@@ -49,15 +50,17 @@ class RestServer < Sinatra::Base
|
|
49
50
|
status 201
|
50
51
|
end
|
51
52
|
post "/#{model.downcase}" do
|
53
|
+
response["Access-Control-Allow-Origin"] = "*"
|
54
|
+
SchemalessRestApi.logger.info "POST #{request.fullpath}"
|
52
55
|
data = JSON.parse(request.body.read)
|
53
|
-
id =
|
54
|
-
if
|
55
|
-
id = data[
|
56
|
+
id = ""
|
57
|
+
if data["id"]
|
58
|
+
id = data["id"].to_s
|
56
59
|
else
|
57
60
|
id = SecureRandom.uuid
|
58
|
-
data[
|
61
|
+
data["id"] = id
|
59
62
|
end
|
60
|
-
if ENV[
|
63
|
+
if ENV["mongodb"]
|
61
64
|
MongoClient.insert(model, data, id)
|
62
65
|
else
|
63
66
|
Entities.models[model][id] = data
|
@@ -65,14 +68,22 @@ class RestServer < Sinatra::Base
|
|
65
68
|
[201, JSON.generate({ id: id })]
|
66
69
|
end
|
67
70
|
|
71
|
+
options "/#{model.downcase}" do
|
72
|
+
response["Allow"] = "*"
|
73
|
+
response["Access-Control-Allow-Origin"] = "*"
|
74
|
+
response["Access-Control-Allow-Methods"] = "*"
|
75
|
+
response["Access-Control-Allow-Headers"] = "*"
|
76
|
+
end
|
77
|
+
|
68
78
|
documentation "Retrieve all instances of #{model} or filtered by query param" do
|
69
79
|
response "Data in #{model}"
|
70
80
|
query_param :key_to_search_in_data, "Value of key"
|
71
81
|
status 200
|
72
82
|
end
|
73
83
|
get "/#{model.downcase}" do
|
74
|
-
|
75
|
-
|
84
|
+
response["Access-Control-Allow-Origin"] = "*"
|
85
|
+
SchemalessRestApi.logger.info "GET #{request.fullpath}"
|
86
|
+
if ENV["mongodb"]
|
76
87
|
if params == {}
|
77
88
|
JSON.generate(MongoClient.get_all(model))
|
78
89
|
else
|
@@ -81,7 +92,10 @@ class RestServer < Sinatra::Base
|
|
81
92
|
else
|
82
93
|
return JSON.generate(Entities.models[model].values) if params == {}
|
83
94
|
|
84
|
-
Entities.models[model].values.find_all
|
95
|
+
matching_values = Entities.models[model].values.find_all do |val|
|
96
|
+
val[params.keys[0]].to_s == params.values[0]
|
97
|
+
end
|
98
|
+
return JSON.generate(matching_values)
|
85
99
|
end
|
86
100
|
rescue Exception => e
|
87
101
|
[404, "Nothing found using #{params}. Only first param considered. #{e.message}"]
|
@@ -93,10 +107,12 @@ class RestServer < Sinatra::Base
|
|
93
107
|
status 404
|
94
108
|
end
|
95
109
|
get "/#{model.downcase}/:id" do |id|
|
96
|
-
|
97
|
-
|
110
|
+
response["Access-Control-Allow-Origin"] = "*"
|
111
|
+
SchemalessRestApi.logger.info "GET #{request.fullpath}"
|
112
|
+
if ENV["mongodb"]
|
98
113
|
results = MongoClient.find(model, id)
|
99
114
|
return not_have(id) unless results.first
|
115
|
+
|
100
116
|
JSON.generate(results.first)
|
101
117
|
else
|
102
118
|
return not_have(id) unless has_id?(model, id)
|
@@ -105,6 +121,13 @@ class RestServer < Sinatra::Base
|
|
105
121
|
end
|
106
122
|
end
|
107
123
|
|
124
|
+
options "/#{model.downcase}/:id" do
|
125
|
+
response["Allow"] = "*"
|
126
|
+
response["Access-Control-Allow-Origin"] = "*"
|
127
|
+
response["Access-Control-Allow-Methods"] = "*"
|
128
|
+
response["Access-Control-Allow-Headers"] = "*"
|
129
|
+
end
|
130
|
+
|
108
131
|
documentation "Update id of #{model} to be provided data" do
|
109
132
|
payload "Whatever JSON you want updated to be. Needs to be valid JSON"
|
110
133
|
response "Data in #{model}"
|
@@ -112,11 +135,13 @@ class RestServer < Sinatra::Base
|
|
112
135
|
status 404
|
113
136
|
end
|
114
137
|
put "/#{model.downcase}/:id" do |id|
|
115
|
-
|
138
|
+
response["Access-Control-Allow-Origin"] = "*"
|
139
|
+
SchemalessRestApi.logger.info "PUT #{request.fullpath}"
|
116
140
|
data = JSON.parse(request.body.read)
|
117
|
-
if ENV[
|
141
|
+
if ENV["mongodb"]
|
118
142
|
results = MongoClient.find(model, id)
|
119
143
|
return not_have(id) unless results.first
|
144
|
+
|
120
145
|
MongoClient.update(model, id, data)
|
121
146
|
else
|
122
147
|
return not_have(id) unless has_id?(model, id)
|
@@ -131,10 +156,12 @@ class RestServer < Sinatra::Base
|
|
131
156
|
status 204
|
132
157
|
end
|
133
158
|
delete "/#{model.downcase}/:id" do |id|
|
134
|
-
|
135
|
-
|
159
|
+
response["Access-Control-Allow-Origin"] = "*"
|
160
|
+
SchemalessRestApi.logger.info "DEL #{request.fullpath}"
|
161
|
+
if ENV["mongodb"]
|
136
162
|
results = MongoClient.find(model, id)
|
137
163
|
return not_have(id) unless results.first
|
164
|
+
|
138
165
|
MongoClient.delete(model, id)
|
139
166
|
else
|
140
167
|
return not_have(id) unless has_id?(model, id)
|
data/lib/schemaless_rest_api.rb
CHANGED
@@ -1,28 +1,43 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# typed: true
|
4
|
+
|
3
5
|
require_relative "schemaless_rest_api/version"
|
4
6
|
require_relative "schemaless_rest_api/entities"
|
7
|
+
require "tapioca"
|
8
|
+
require "logger"
|
5
9
|
|
6
10
|
require "json"
|
7
11
|
require "securerandom"
|
8
12
|
|
13
|
+
# Global params for Schemalass REST API
|
14
|
+
module SchemalessRestApi
|
15
|
+
@logger = Logger.new($stdout)
|
16
|
+
class << self
|
17
|
+
# @return Logger
|
18
|
+
attr_accessor :logger
|
19
|
+
end
|
20
|
+
|
21
|
+
class Error < StandardError; end
|
22
|
+
end
|
23
|
+
|
9
24
|
def models_env_not_set
|
10
|
-
!ENV["models"] || ENV["models"].empty?
|
25
|
+
!ENV["models"] || T.must(ENV["models"]).empty?
|
11
26
|
end
|
12
27
|
|
13
28
|
def extract_models
|
14
|
-
return [] if
|
15
|
-
|
29
|
+
return [] if !Entities.models.empty? && models_env_not_set
|
30
|
+
|
16
31
|
error_msg = "Make 'models' environment variable an array (e.g ['model1', 'model2'])"
|
17
32
|
raise "Please set 'models' ENV variable or create 'db.json'. #{error_msg}" if ENV["models"].nil?
|
18
33
|
|
19
|
-
models = eval(ENV["models"])
|
34
|
+
models = eval(T.must(ENV["models"])) # rubocop:disable Security/Eval
|
20
35
|
raise error_msg unless models.is_a? Array
|
21
36
|
|
22
37
|
models
|
23
38
|
end
|
24
39
|
|
25
|
-
SEED_FILE =
|
40
|
+
SEED_FILE = "db.json"
|
26
41
|
|
27
42
|
if File.exist? SEED_FILE
|
28
43
|
puts "Seeding db based on '#{SEED_FILE}'"
|
@@ -31,10 +46,11 @@ if File.exist? SEED_FILE
|
|
31
46
|
Entities.models[entity.to_sym] = {} unless Entities.models[entity.to_sym]
|
32
47
|
if values.is_a? Array
|
33
48
|
values.each do |value|
|
34
|
-
next unless value[
|
35
|
-
|
49
|
+
next unless value["id"]
|
50
|
+
|
51
|
+
Entities.models[entity.to_sym][value["id"].to_s] = value
|
36
52
|
end
|
37
|
-
else
|
53
|
+
else
|
38
54
|
puts "Entity 'entity' doesn't have array, skipping"
|
39
55
|
end
|
40
56
|
end
|
@@ -46,15 +62,10 @@ end
|
|
46
62
|
|
47
63
|
puts "Modelling #{Entities.models.keys}"
|
48
64
|
|
49
|
-
if ENV[
|
50
|
-
require_relative
|
65
|
+
if ENV["mongodb"]
|
66
|
+
require_relative "schemaless_rest_api/mongo_client"
|
51
67
|
else
|
52
68
|
puts "[INFO] Using in memory storage. Pass in 'mongodb' ENV variable to store
|
53
69
|
in db"
|
54
70
|
end
|
55
71
|
require_relative "schemaless_rest_api/rest_server"
|
56
|
-
|
57
|
-
module SchemalessRestApi
|
58
|
-
class Error < StandardError; end
|
59
|
-
# Your code goes here...
|
60
|
-
end
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: schemaless_rest_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Garratt
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-05-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: mongo
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
@@ -25,7 +25,7 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: puma
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
@@ -39,7 +39,7 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: rackup
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
@@ -53,7 +53,7 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: route_downcaser
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
@@ -67,7 +67,7 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: sinatra
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ">="
|
@@ -81,7 +81,7 @@ dependencies:
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: sinatra-docdsl
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - ">="
|
@@ -95,7 +95,7 @@ dependencies:
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: thor
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - ">="
|