schemaless_rest_api 0.3.1 → 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
- - ">="
|