faastruby 0.4.8 → 0.4.9
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/CHANGELOG.md +7 -0
- data/Gemfile.lock +1 -1
- data/exe/faastruby-server +59 -185
- data/lib/faastruby/server.rb +230 -0
- data/lib/faastruby/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a1643e934126a8b362f512fef2ab59834562fc01cc1d8751f9ee7606d1586503
|
4
|
+
data.tar.gz: f363ba8b0befa0a807fd16f29c28893a7c5302457628511d77d9675c2683ce13
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: adce689b5896a361aed94ea73438d1cf7090afc3638f438fa9744cf9a8cceb34cf5a5c089506c24c47f433c22be0ed35cabb3c3266301fff731dc1a2415ba475
|
7
|
+
data.tar.gz: fc39dcf79dc53e71e788233b978f756aab26907562c0fb07cc912496c4b1821a151c2f2f3ba5db65476046f3bc31e284e17fb2a70d3bd304cc8a8c4c1293da89
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 0.4.9 - Jan 13 2019
|
4
|
+
- Changes in `faastruby server`
|
5
|
+
- Cleaned up code
|
6
|
+
- Logs are easier to read
|
7
|
+
- Function responses show up in the log
|
8
|
+
- Support for events with `publish`
|
9
|
+
|
3
10
|
## 0.4.8 - Jan 8 2019
|
4
11
|
- Use the actual param rather than the Sinatra::Params object
|
5
12
|
|
data/Gemfile.lock
CHANGED
data/exe/faastruby-server
CHANGED
@@ -1,200 +1,74 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'sinatra'
|
4
|
-
require 'sinatra/multi_route'
|
5
2
|
require 'yaml'
|
6
3
|
require 'oj'
|
7
4
|
require 'faastruby-rpc'
|
8
5
|
require 'base64'
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
require 'faastruby/server'
|
7
|
+
require 'sinatra'
|
8
|
+
require 'sinatra/multi_route'
|
9
|
+
require 'colorize'
|
10
|
+
FaaStRuby::EventHub.listen_for_events!
|
11
|
+
|
12
|
+
set :port, 3000
|
13
|
+
set :bind, '0.0.0.0'
|
14
|
+
case ARGV.shift
|
15
|
+
when '-p'
|
16
|
+
set :port, ARGV.shift
|
17
|
+
when '-b', '-o'
|
18
|
+
set :bind, ARGV.shift
|
12
19
|
end
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
'error' => "Please use the helpers 'render' or 'respond_with' as your function return value."
|
27
|
-
}
|
28
|
-
FaaStRuby::Response.new(body: Oj.dump(body), status: 500, headers: {'Content-Type' => 'application/json'})
|
29
|
-
rescue Exception => e
|
30
|
-
body = {
|
31
|
-
'error' => e.message,
|
32
|
-
'location' => e.backtrace&.first,
|
33
|
-
}
|
34
|
-
FaaStRuby::Response.new(body: Oj.dump(body), status: 500, headers: {'Content-Type' => 'application/json'})
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def rendered!
|
39
|
-
@rendered = true
|
40
|
-
end
|
41
|
-
def rendered?
|
42
|
-
@rendered
|
43
|
-
end
|
44
|
-
|
45
|
-
def respond_with(body, status: 200, headers: {}, binary: false)
|
46
|
-
raise FaaStRuby::DoubleRenderError.new("You called 'render' or 'respond_with' twice in your handler method") if rendered?
|
47
|
-
response = FaaStRuby::Response.new(body: body, status: status, headers: headers, binary: binary)
|
48
|
-
rendered!
|
49
|
-
response
|
50
|
-
end
|
51
|
-
|
52
|
-
def render(
|
53
|
-
js: nil,
|
54
|
-
body: nil,
|
55
|
-
inline: nil,
|
56
|
-
html: nil,
|
57
|
-
json: nil,
|
58
|
-
yaml: nil,
|
59
|
-
text: nil,
|
60
|
-
data: nil,
|
61
|
-
png: nil,
|
62
|
-
svg: nil,
|
63
|
-
jpeg: nil,
|
64
|
-
gif: nil,
|
65
|
-
icon: nil,
|
66
|
-
status: 200, headers: {}, content_type: nil, binary: false
|
67
|
-
)
|
68
|
-
headers["Content-Type"] = content_type if content_type
|
69
|
-
bin = false
|
70
|
-
case
|
71
|
-
when json
|
72
|
-
headers["Content-Type"] ||= "application/json"
|
73
|
-
resp_body = json.is_a?(String) ? json : Oj.dump(json)
|
74
|
-
when html, inline
|
75
|
-
headers["Content-Type"] ||= "text/html"
|
76
|
-
resp_body = html
|
77
|
-
when text
|
78
|
-
headers["Content-Type"] ||= "text/plain"
|
79
|
-
resp_body = text
|
80
|
-
when yaml
|
81
|
-
headers["Content-Type"] ||= "application/yaml"
|
82
|
-
resp_body = yaml.is_a?(String) ? yaml : YAML.load(yaml)
|
83
|
-
when body
|
84
|
-
headers["Content-Type"] ||= "application/octet-stream"
|
85
|
-
bin = binary
|
86
|
-
resp_body = bin ? Base64.urlsafe_encode64(body) : body
|
87
|
-
when data
|
88
|
-
headers["Content-Type"] ||= "application/octet-stream"
|
89
|
-
resp_body = Base64.urlsafe_encode64(data)
|
90
|
-
bin = true
|
91
|
-
when js
|
92
|
-
headers["Content-Type"] ||= "text/javascript"
|
93
|
-
resp_body = js
|
94
|
-
when png
|
95
|
-
headers["Content-Type"] ||= "image/png"
|
96
|
-
resp_body = Base64.urlsafe_encode64(png)
|
97
|
-
bin = true
|
98
|
-
when svg
|
99
|
-
headers["Content-Type"] ||= "image/svg+xml"
|
100
|
-
resp_body = svg
|
101
|
-
when jpeg
|
102
|
-
headers["Content-Type"] ||= "image/jpeg"
|
103
|
-
resp_body = Base64.urlsafe_encode64(jpeg)
|
104
|
-
bin = true
|
105
|
-
when gif
|
106
|
-
headers["Content-Type"] ||= "image/gif"
|
107
|
-
resp_body = Base64.urlsafe_encode64(gif)
|
108
|
-
bin = true
|
109
|
-
when icon
|
110
|
-
headers["Content-Type"] ||= "image/x-icon"
|
111
|
-
resp_body = Base64.urlsafe_encode64(icon)
|
112
|
-
bin = true
|
113
|
-
end
|
114
|
-
respond_with(resp_body, status: status, headers: headers, binary: bin)
|
115
|
-
end
|
20
|
+
set :server, %w[puma]
|
21
|
+
set :show_exceptions, true
|
22
|
+
|
23
|
+
register Sinatra::MultiRoute
|
24
|
+
route :get, :post, :put, :patch, :delete, '/:workspace_name/:function_name' do
|
25
|
+
path = "#{params[:workspace_name]}/#{params[:function_name]}"
|
26
|
+
headers = env.select { |key, value| key.include?('HTTP_') || ['CONTENT_TYPE', 'CONTENT_LENGTH', 'REMOTE_ADDR', 'REQUEST_METHOD', 'QUERY_STRING'].include?(key) }
|
27
|
+
if headers.has_key?("HTTP_FAASTRUBY_RPC")
|
28
|
+
body = nil
|
29
|
+
rpc_args = parse_body(request.body.read, headers['CONTENT_TYPE'], request.request_method) || []
|
30
|
+
else
|
31
|
+
body = parse_body(request.body.read, headers['CONTENT_TYPE'], request.request_method)
|
32
|
+
rpc_args = []
|
116
33
|
end
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
@binary = binary
|
128
|
-
end
|
129
|
-
|
130
|
-
def binary?
|
131
|
-
@binary
|
132
|
-
end
|
34
|
+
query_params = parse_query(request.query_string)
|
35
|
+
context = set_context(params[:workspace_name], params[:function_name])
|
36
|
+
event = FaaStRuby::Event.new(body, query_params, headers, context)
|
37
|
+
response = FaaStRuby::Runner.new.call(params[:workspace_name], params[:function_name], event, rpc_args)
|
38
|
+
status response.status
|
39
|
+
headers response.headers
|
40
|
+
if response.binary?
|
41
|
+
response_body = Base64.urlsafe_decode64(response.body)
|
42
|
+
else
|
43
|
+
response_body = response.body
|
133
44
|
end
|
45
|
+
puts "[#{path}] #=> status=#{response.status} body=#{response_body.inspect} headers=#{Oj.dump response.headers}".light_blue
|
46
|
+
body response_body
|
134
47
|
end
|
135
48
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
when '-b'
|
143
|
-
set :bind, ARGV.shift
|
144
|
-
end
|
145
|
-
set :server, %w[puma]
|
146
|
-
set :run, false
|
147
|
-
set :show_exceptions, true
|
148
|
-
|
149
|
-
register Sinatra::MultiRoute
|
150
|
-
route :get, :post, :put, :patch, :delete, '/:workspace_name/:function_name' do
|
151
|
-
e = FaaStRuby::Event.new(:body, :query_params, :headers, :context)
|
152
|
-
headers = env.select { |key, value| key.include?('HTTP_') || ['CONTENT_TYPE', 'CONTENT_LENGTH', 'REMOTE_ADDR', 'REQUEST_METHOD', 'QUERY_STRING'].include?(key) }
|
153
|
-
if headers.has_key?("HTTP_FAASTRUBY_RPC")
|
154
|
-
body = nil
|
155
|
-
rpc_args = parse_body(request.body.read, headers['CONTENT_TYPE'], request.request_method) || []
|
156
|
-
else
|
157
|
-
body = parse_body(request.body.read, headers['CONTENT_TYPE'], request.request_method)
|
158
|
-
rpc_args = []
|
159
|
-
end
|
160
|
-
query_params = parse_query(request.query_string)
|
161
|
-
context = set_context(params[:workspace_name], params[:function_name])
|
162
|
-
event = e.new(body, query_params, headers, context)
|
163
|
-
response = FaaStRuby::Runner.new.call(params[:workspace_name], params[:function_name], event, rpc_args)
|
164
|
-
status response.status
|
165
|
-
headers response.headers
|
166
|
-
if response.binary?
|
167
|
-
body Base64.urlsafe_decode64(response.body)
|
168
|
-
else
|
169
|
-
body response.body
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
def parse_body(body, content_type, method)
|
174
|
-
return nil if method == 'GET'
|
175
|
-
return {} if body.nil? && method != 'GET'
|
176
|
-
return Oj.load(body) if content_type == 'application/json'
|
177
|
-
return body
|
178
|
-
end
|
49
|
+
def parse_body(body, content_type, method)
|
50
|
+
return nil if method == 'GET'
|
51
|
+
return {} if body.nil? && method != 'GET'
|
52
|
+
return Oj.load(body) if content_type == 'application/json'
|
53
|
+
return body
|
54
|
+
end
|
179
55
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
56
|
+
def set_context(workspace_name, function_name)
|
57
|
+
return nil unless File.file?('context.yml')
|
58
|
+
yaml = YAML.load(File.read('context.yml'))
|
59
|
+
return nil unless yaml.has_key?(workspace_name)
|
60
|
+
yaml[workspace_name][function_name]
|
61
|
+
end
|
186
62
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
end
|
193
|
-
hash
|
194
|
-
end
|
195
|
-
def self.run?
|
196
|
-
true
|
63
|
+
def parse_query(query_string)
|
64
|
+
hash = {}
|
65
|
+
query_string.split('&').each do |param|
|
66
|
+
key, value = param.split('=')
|
67
|
+
hash[key] = value
|
197
68
|
end
|
69
|
+
hash
|
70
|
+
end
|
71
|
+
def self.run?
|
72
|
+
true
|
198
73
|
end
|
199
74
|
|
200
|
-
FaaStRubyServer.run! rescue nil # this will suppress some of the errors messages
|
@@ -0,0 +1,230 @@
|
|
1
|
+
module FaaStRuby
|
2
|
+
class DoubleRenderError < StandardError; end
|
3
|
+
class EventChannel
|
4
|
+
@@channels = {}
|
5
|
+
def self.channels
|
6
|
+
@@channels
|
7
|
+
end
|
8
|
+
attr_accessor :name
|
9
|
+
def initialize(channel)
|
10
|
+
@name = channel
|
11
|
+
@@channels[channel] ||= []
|
12
|
+
end
|
13
|
+
def subscribe(function_path)
|
14
|
+
@@channels[@name] << function_path
|
15
|
+
end
|
16
|
+
def subscribers
|
17
|
+
@@channels[@name] || []
|
18
|
+
end
|
19
|
+
end
|
20
|
+
class Subscriber
|
21
|
+
attr_accessor :path
|
22
|
+
def initialize(path)
|
23
|
+
@path = path
|
24
|
+
@workspace_name, @function_name = @path.split("/")
|
25
|
+
end
|
26
|
+
|
27
|
+
def call(encoded_data)
|
28
|
+
data = Base64.urlsafe_decode64(encoded_data)
|
29
|
+
headers = {'X-Origin' => 'event_hub', 'Content-Transfer-Encoding' => 'base64'}
|
30
|
+
event = Event.new(data, {}, headers, nil)
|
31
|
+
Runner.new.call(@workspace_name, @function_name, event, [])
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class EventHub
|
36
|
+
@@queue = Queue.new
|
37
|
+
def self.queue
|
38
|
+
@@queue
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.push(payload)
|
42
|
+
@@queue << payload
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.thread
|
46
|
+
@@thread
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.load_subscribers
|
50
|
+
Dir.glob('*/*/faastruby.yml').each do |file|
|
51
|
+
workspace_name, function_name, _ = file.split('/')
|
52
|
+
path = "#{workspace_name}/#{function_name}"
|
53
|
+
config = YAML.load(File.read(file))
|
54
|
+
next unless config['channels'].is_a?(Array)
|
55
|
+
config['channels'].compact!
|
56
|
+
config['channels'].each do |c|
|
57
|
+
channel = EventChannel.new(c)
|
58
|
+
channel.subscribe(path)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
puts "[EventHub] Channel subscriptions: #{EventChannel.channels}".yellow
|
62
|
+
puts "[EventHub] If you modify 'faastruby.yml' in any function, you will need to restart the server to apply the changes.".yellow
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.listen_for_events!
|
66
|
+
load_subscribers
|
67
|
+
@@thread = Thread.new do
|
68
|
+
loop do
|
69
|
+
encoded_channel, encoded_data = @@queue.pop.split(',')
|
70
|
+
channel = EventChannel.new(Base64.urlsafe_decode64(encoded_channel))
|
71
|
+
puts "[EventHub] Event channel=#{channel.name.inspect}".yellow
|
72
|
+
channel.subscribers.each do |s|
|
73
|
+
subscriber = Subscriber.new(s)
|
74
|
+
puts "[EventHub] Trigger function=#{subscriber.path.inspect} base64_payload=#{encoded_data.inspect}".yellow
|
75
|
+
response = subscriber.call(encoded_data)
|
76
|
+
puts "[#{subscriber.path}] #=> status=#{response.status} body=#{response.body.inspect} headers=#{Oj.dump response.headers}".light_blue
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
puts "[EventHub] Events thread started.".yellow
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
class Runner
|
85
|
+
def initialize
|
86
|
+
@rendered = false
|
87
|
+
end
|
88
|
+
|
89
|
+
def path
|
90
|
+
@path
|
91
|
+
end
|
92
|
+
|
93
|
+
def call(workspace_name, function_name, event, args)
|
94
|
+
@path = "#{workspace_name}/#{function_name}"
|
95
|
+
begin
|
96
|
+
load "./#{workspace_name}/#{function_name}/handler.rb"
|
97
|
+
response = handler(event, *args)
|
98
|
+
return response if response.is_a?(FaaStRuby::Response)
|
99
|
+
body = {
|
100
|
+
'error' => "Please use the helpers 'render' or 'respond_with' as your function return value."
|
101
|
+
}
|
102
|
+
FaaStRuby::Response.new(body: Oj.dump(body), status: 500, headers: {'Content-Type' => 'application/json'})
|
103
|
+
rescue Exception => e
|
104
|
+
body = {
|
105
|
+
'error' => e.message,
|
106
|
+
'location' => e.backtrace&.first,
|
107
|
+
}
|
108
|
+
FaaStRuby::Response.new(body: Oj.dump(body), status: 500, headers: {'Content-Type' => 'application/json'})
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def rendered!
|
113
|
+
@rendered = true
|
114
|
+
end
|
115
|
+
def rendered?
|
116
|
+
@rendered
|
117
|
+
end
|
118
|
+
|
119
|
+
def respond_with(body, status: 200, headers: {}, binary: false)
|
120
|
+
raise FaaStRuby::DoubleRenderError.new("You called 'render' or 'respond_with' twice in your handler method") if rendered?
|
121
|
+
response = FaaStRuby::Response.new(body: body, status: status, headers: headers, binary: binary)
|
122
|
+
rendered!
|
123
|
+
response
|
124
|
+
end
|
125
|
+
|
126
|
+
def render(
|
127
|
+
js: nil,
|
128
|
+
body: nil,
|
129
|
+
inline: nil,
|
130
|
+
html: nil,
|
131
|
+
json: nil,
|
132
|
+
yaml: nil,
|
133
|
+
text: nil,
|
134
|
+
data: nil,
|
135
|
+
png: nil,
|
136
|
+
svg: nil,
|
137
|
+
jpeg: nil,
|
138
|
+
gif: nil,
|
139
|
+
icon: nil,
|
140
|
+
status: 200, headers: {}, content_type: nil, binary: false
|
141
|
+
)
|
142
|
+
headers["Content-Type"] = content_type if content_type
|
143
|
+
bin = false
|
144
|
+
case
|
145
|
+
when json
|
146
|
+
headers["Content-Type"] ||= "application/json"
|
147
|
+
resp_body = json.is_a?(String) ? json : Oj.dump(json)
|
148
|
+
when html, inline
|
149
|
+
headers["Content-Type"] ||= "text/html"
|
150
|
+
resp_body = html
|
151
|
+
when text
|
152
|
+
headers["Content-Type"] ||= "text/plain"
|
153
|
+
resp_body = text
|
154
|
+
when yaml
|
155
|
+
headers["Content-Type"] ||= "application/yaml"
|
156
|
+
resp_body = yaml.is_a?(String) ? yaml : YAML.load(yaml)
|
157
|
+
when body
|
158
|
+
headers["Content-Type"] ||= "application/octet-stream"
|
159
|
+
bin = binary
|
160
|
+
resp_body = bin ? Base64.urlsafe_encode64(body) : body
|
161
|
+
when data
|
162
|
+
headers["Content-Type"] ||= "application/octet-stream"
|
163
|
+
resp_body = Base64.urlsafe_encode64(data)
|
164
|
+
bin = true
|
165
|
+
when js
|
166
|
+
headers["Content-Type"] ||= "text/javascript"
|
167
|
+
resp_body = js
|
168
|
+
when png
|
169
|
+
headers["Content-Type"] ||= "image/png"
|
170
|
+
resp_body = Base64.urlsafe_encode64(png)
|
171
|
+
bin = true
|
172
|
+
when svg
|
173
|
+
headers["Content-Type"] ||= "image/svg+xml"
|
174
|
+
resp_body = svg
|
175
|
+
when jpeg
|
176
|
+
headers["Content-Type"] ||= "image/jpeg"
|
177
|
+
resp_body = Base64.urlsafe_encode64(jpeg)
|
178
|
+
bin = true
|
179
|
+
when gif
|
180
|
+
headers["Content-Type"] ||= "image/gif"
|
181
|
+
resp_body = Base64.urlsafe_encode64(gif)
|
182
|
+
bin = true
|
183
|
+
when icon
|
184
|
+
headers["Content-Type"] ||= "image/x-icon"
|
185
|
+
resp_body = Base64.urlsafe_encode64(icon)
|
186
|
+
bin = true
|
187
|
+
end
|
188
|
+
respond_with(resp_body, status: status, headers: headers, binary: bin)
|
189
|
+
end
|
190
|
+
|
191
|
+
def puts(msg)
|
192
|
+
super "[#{@path}] #{msg}".green
|
193
|
+
end
|
194
|
+
|
195
|
+
def publish(channel, data: nil)
|
196
|
+
begin
|
197
|
+
encoded_data = data ? Base64.urlsafe_encode64(data, padding: false) : ""
|
198
|
+
payload = %(#{Base64.urlsafe_encode64(channel, padding: false)},#{encoded_data})
|
199
|
+
EventHub.queue.push payload
|
200
|
+
true
|
201
|
+
rescue
|
202
|
+
false
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
class Event
|
208
|
+
attr_accessor :body, :query_params, :headers, :context
|
209
|
+
def initialize(body, query_params, headers, context)
|
210
|
+
@body = body
|
211
|
+
@query_params = query_params
|
212
|
+
@headers = headers
|
213
|
+
@context = context
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
class Response
|
218
|
+
attr_accessor :body, :status, :headers, :binary
|
219
|
+
def initialize(body:, status: 200, headers: {}, binary: false)
|
220
|
+
@body = body
|
221
|
+
@status = status
|
222
|
+
@headers = headers
|
223
|
+
@binary = binary
|
224
|
+
end
|
225
|
+
|
226
|
+
def binary?
|
227
|
+
@binary
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
data/lib/faastruby/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: faastruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paulo Arruda
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-01-
|
11
|
+
date: 2019-01-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rest-client
|
@@ -256,6 +256,7 @@ files:
|
|
256
256
|
- lib/faastruby/cli/credentials.rb
|
257
257
|
- lib/faastruby/cli/package.rb
|
258
258
|
- lib/faastruby/function.rb
|
259
|
+
- lib/faastruby/server.rb
|
259
260
|
- lib/faastruby/version.rb
|
260
261
|
- lib/faastruby/workspace.rb
|
261
262
|
- templates/crystal/example-blank/spec/handler_spec.cr
|