nodo 1.5.5 → 1.6.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3cef66bc4b1d53b20500110ac7acbc226ec361b6aaed569874ce8568a6718242
4
- data.tar.gz: ab2cae6eef01d53ebc1c471a5e08edfd37a263178adc49aa459c98dfcea4e92f
3
+ metadata.gz: 95d8c9823753373c6be5ad0c493e7f14346950b611d4ca0d90c5a96bcabfa5e6
4
+ data.tar.gz: 3ad4b37694f4ef33cfadad03794ce7b4bf2a9fd42dc4e0abb319ec981e529b33
5
5
  SHA512:
6
- metadata.gz: 9bf90e8b56366f2e42039026575db43a0c5a9808a677a533c3e211c9ae211a8f06b2ea0890550e22fca259f9fa416c0e96017a676538a3eb673f2a66caa0996a
7
- data.tar.gz: 2573e2dfd199bb9f8e25dc11c5dcb49e0ba6f29796aaa523656fa1020e0d8ce325ab411cf2d60413ac0557407fec4a132ba51d75075585a0e7b56d76bfc42811
6
+ metadata.gz: 0e0004a84541cb4edd4cc398250fe17ee5623aed13f1bbb76b31eee531867906cffd87c5e0f71b50c0c72fdae4f26e57d24f654fdd2623bee90b20c60f3ff0b4
7
+ data.tar.gz: 539b75f4a8283f4db872db614158403129651f4b0811d9e7f9ef5dfa1f506bedcf238fa0b93896fe776ae936bbc8eba9cbd44ea86fa8f80b87142e5d69cfe957
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
- [![Gem Version](https://badge.fury.io/rb/nodo.svg)](http://badge.fury.io/rb/nodo) [![build](https://github.com/mtgrosser/nodo/actions/workflows/build.yml/badge.svg)](https://github.com/mtgrosser/nodo/actions/workflows/build.yml)
1
+ [![Gem Version](https://badge.fury.io/rb/nodo.svg)](http://badge.fury.io/rb/nodo)
2
+ [![build](https://github.com/mtgrosser/nodo/actions/workflows/build.yml/badge.svg)](https://github.com/mtgrosser/nodo/actions/workflows/build.yml)
2
3
 
3
4
  # Nōdo – call Node.js from Ruby
4
5
 
@@ -107,13 +108,7 @@ To set a custom path:
107
108
  Nodo.modules_root = 'path/to/node_modules'
108
109
  ```
109
110
 
110
- For Rails applications, it will be set to `vendor/node_modules`.
111
- To use the Rails 6 default of putting `node_modules` to `RAILS_ROOT`:
112
-
113
- ```ruby
114
- # config/initializers/nodo.rb
115
- Nodo.modules_root = Rails.root.join('node_modules')
116
- ```
111
+ Also see: [Clean your Rails root](#Clean-your-Rails-root)
117
112
 
118
113
  ### Defining JS constants
119
114
 
@@ -175,8 +170,17 @@ end
175
170
 
176
171
  ### Limiting function execution time
177
172
 
178
- The default timeout for a single JS function call is 60 seconds due to the
179
- `Net::HTTP` default. It can be overridden on a per-function basis:
173
+ The default timeout for a single JS function call is 60 seconds and can be
174
+ set globally:
175
+
176
+ ```ruby
177
+ Nodo.timeout = 5
178
+ ```
179
+
180
+ If the execution of a single function call exceeds the timeout, `Nodo::TimeoutError`
181
+ is raised.
182
+
183
+ The timeout can also be set on a per-function basis:
180
184
 
181
185
  ```ruby
182
186
  class Foo < Nodo::Core
@@ -185,6 +189,105 @@ class Foo < Nodo::Core
185
189
  JS
186
190
  end
187
191
 
188
- foo.new.sleep(2)
192
+ Foo.new.sleep(2)
189
193
  => Nodo::TimeoutError raised
190
194
  ```
195
+
196
+ ### Logging
197
+
198
+ By default, JS errors will be logged to `STDOUT`.
199
+
200
+ To set a custom logger:
201
+
202
+ ```ruby
203
+ Nodo.logger = Logger.new('nodo.log')
204
+ ```
205
+
206
+ In Rails applications, `Rails.logger` will automatically be set.
207
+
208
+
209
+ ### Debugging
210
+
211
+ To get verbose debug output, set
212
+
213
+ ```ruby
214
+ Nodo.debug = true
215
+ ```
216
+
217
+ before instantiating any worker instances. The debug mode will be active during
218
+ the current process run.
219
+
220
+ To print a debug message from JS code:
221
+
222
+ ```js
223
+ nodo.debug("Debug message");
224
+ ```
225
+
226
+ ### Evaluation
227
+
228
+ While `Nodo` is mainly function-based, it is possible to evaluate JS code in the
229
+ context of the defined object.
230
+
231
+ ```ruby
232
+ foo = Foo.new.evaluate("3 + 5")
233
+ => 8
234
+ ```
235
+
236
+ Evaluated code can access functions, required dependencies and constants:
237
+
238
+ ```ruby
239
+ class Foo < Nodo::Core
240
+ const :BAR, 'bar'
241
+ require :uuid
242
+ function :hello, code: '() => "world"'
243
+ end
244
+
245
+ foo = Foo.new
246
+
247
+ foo.evaluate('BAR')
248
+ => "bar"
249
+
250
+ foo.evaluate('uuid.v4()')
251
+ => "f258bef3-0d6f-4566-ad39-d8dec973ef6b"
252
+
253
+ foo.evaluate('hello()')
254
+ => "world"
255
+ ```
256
+
257
+ Variables defined by evaluation are local to the current instance:
258
+
259
+ ```ruby
260
+ one = Foo.new
261
+ one.evaluate('a = 1')
262
+ two = Foo.new
263
+ two.evaluate('a = 2')
264
+ one.evaluate('a') => 1
265
+ two.evaluate('a') => 2
266
+ ```
267
+
268
+ ⚠️ Evaluation comes with the usual caveats:
269
+
270
+ - Avoid modifying any of your predefined identifiers. Remember that in JS,
271
+ as in Ruby, constants are not necessarily constant.
272
+ - Never evaluate any code which includes un-checked user data. The Node.js process
273
+ has full read/write access to your filesystem! 💥
274
+
275
+
276
+ ## Clean your Rails root
277
+
278
+ For Rails applications, Nodo enables you to move `node_modules`, `package.json` and
279
+ `yarn.lock` into your application's `vendor` folder by setting the `NODE_PATH` in
280
+ an initializer:
281
+
282
+ ```ruby
283
+ # config/initializers/nodo.rb
284
+ Nodo.modules_root = Rails.root.join('vendor', 'node_modules')
285
+ ```
286
+
287
+ The rationale for this is NPM modules being external vendor dependencies, which
288
+ should not clutter the application root directory.
289
+
290
+ With this new default, all `yarn` operations should be done after `cd`ing to `vendor`.
291
+
292
+ This repo provides an [adapted version](https://github.com/mtgrosser/nodo/blob/master/install/yarn.rake)
293
+ of the `yarn:install` rake task which will automatically take care of the vendored module location.
data/lib/nodo/constant.rb CHANGED
@@ -7,7 +7,7 @@ module Nodo
7
7
  end
8
8
 
9
9
  def to_js
10
- "const #{name} = #{value.to_json};\n"
10
+ "const #{name} = __nodo_klass__.#{name} = #{value.to_json};\n"
11
11
  end
12
12
  end
13
13
  end
data/lib/nodo/core.rb CHANGED
@@ -1,8 +1,11 @@
1
1
  module Nodo
2
2
  class Core
3
3
  SOCKET_NAME = 'nodo.sock'
4
- DEFINE_METHOD = '__nodo_define_class__'
5
- TIMEOUT = 5
4
+ DEFINE_METHOD = '__nodo_define_class__'.freeze
5
+ EVALUATE_METHOD = '__nodo_evaluate__'.freeze
6
+ GC_METHOD = '__nodo_gc__'.freeze
7
+ INTERNAL_METHODS = [DEFINE_METHOD, EVALUATE_METHOD, GC_METHOD].freeze
8
+ LAUNCH_TIMEOUT = 5
6
9
  ARRAY_CLASS_ATTRIBUTES = %i[dependencies constants scripts].freeze
7
10
  HASH_CLASS_ATTRIBUTES = %i[functions].freeze
8
11
  CLASS_ATTRIBUTES = (ARRAY_CLASS_ATTRIBUTES + HASH_CLASS_ATTRIBUTES).freeze
@@ -10,6 +13,7 @@ module Nodo
10
13
  @@node_pid = nil
11
14
  @@tmpdir = nil
12
15
  @@mutex = Mutex.new
16
+ @@exiting = nil
13
17
 
14
18
  class << self
15
19
  extend Forwardable
@@ -21,15 +25,11 @@ module Nodo
21
25
  subclass.send "#{attr}=", send(attr).dup
22
26
  end
23
27
  end
24
-
28
+
25
29
  def instance
26
30
  @instance ||= new
27
31
  end
28
32
 
29
- def class_function(*methods)
30
- singleton_class.def_delegators(:instance, *methods)
31
- end
32
-
33
33
  def class_defined?
34
34
  !!class_defined
35
35
  end
@@ -42,6 +42,7 @@ module Nodo
42
42
  define_method "#{attr}=" do |value|
43
43
  instance_variable_set :"@#{attr}", value
44
44
  end
45
+ protected "#{attr}="
45
46
  end
46
47
 
47
48
  ARRAY_CLASS_ATTRIBUTES.each do |attr|
@@ -55,28 +56,6 @@ module Nodo
55
56
  instance_variable_get(:"@#{attr}") || instance_variable_set(:"@#{attr}", {})
56
57
  end
57
58
  end
58
-
59
- def require(*mods)
60
- deps = mods.last.is_a?(Hash) ? mods.pop : {}
61
- mods = mods.map { |m| [m, m] }.to_h
62
- self.dependencies = dependencies + mods.merge(deps).map { |name, package| Dependency.new(name, package) }
63
- end
64
-
65
- def function(name, _code = nil, timeout: 60, code: nil)
66
- raise ArgumentError, "reserved method name #{name.inspect}" if Nodo::Core.method_defined?(name)
67
- code = (code ||= _code).strip
68
- raise ArgumentError, 'function code is required' if '' == code
69
- self.functions = functions.merge(name => Function.new(name, _code || code, caller.first, timeout))
70
- define_method(name) { |*args| call_js_method(name, args) }
71
- end
72
-
73
- def const(name, value)
74
- self.constants = constants + [Constant.new(name, value)]
75
- end
76
-
77
- def script(code)
78
- self.scripts = scripts + [Script.new(code)]
79
- end
80
59
 
81
60
  def generate_core_code
82
61
  <<~JS
@@ -94,7 +73,7 @@ module Nodo
94
73
  nodo.core.close(() => { process.exit(0) });
95
74
  };
96
75
 
97
- process.on('SIGINT', shutdown);
76
+ // process.on('SIGINT', shutdown);
98
77
  process.on('SIGTERM', shutdown);
99
78
 
100
79
  nodo.core.run(socket);
@@ -104,8 +83,7 @@ module Nodo
104
83
  def generate_class_code
105
84
  <<~JS
106
85
  (() => {
107
- const __nodo_log = nodo.log;
108
- const __nodo_klass__ = {};
86
+ const __nodo_klass__ = { nodo: global.nodo };
109
87
  #{dependencies.map(&:to_js).join}
110
88
  #{constants.map(&:to_js).join}
111
89
  #{functions.values.map(&:to_js).join}
@@ -115,14 +93,57 @@ module Nodo
115
93
  JS
116
94
  end
117
95
 
96
+ protected
97
+
98
+ def finalize_context(context_id)
99
+ proc do
100
+ if not @@exiting and core = Nodo::Core.instance
101
+ core.send(:call_js_method, GC_METHOD, context_id)
102
+ end
103
+ end
104
+ end
105
+
118
106
  private
119
107
 
108
+ def require(*mods)
109
+ deps = mods.last.is_a?(Hash) ? mods.pop : {}
110
+ mods = mods.map { |m| [m, m] }.to_h
111
+ self.dependencies = dependencies + mods.merge(deps).map { |name, package| Dependency.new(name, package) }
112
+ end
113
+
114
+ def function(name, _code = nil, timeout: Nodo.timeout, code: nil)
115
+ raise ArgumentError, "reserved method name #{name.inspect}" if reserved_method_name?(name)
116
+ code = (code ||= _code).strip
117
+ raise ArgumentError, 'function code is required' if '' == code
118
+ loc = caller_locations(1, 1)[0]
119
+ source_location = "#{loc.path}:#{loc.lineno}: in `#{name}'"
120
+ self.functions = functions.merge(name => Function.new(name, _code || code, source_location, timeout))
121
+ define_method(name) { |*args| call_js_method(name, args) }
122
+ end
123
+
124
+ def class_function(*methods)
125
+ singleton_class.def_delegators(:instance, *methods)
126
+ end
127
+
128
+ def const(name, value)
129
+ self.constants = constants + [Constant.new(name, value)]
130
+ end
131
+
132
+ def script(code)
133
+ self.scripts = scripts + [Script.new(code)]
134
+ end
135
+
120
136
  def nodo_js
121
137
  Pathname.new(__FILE__).dirname.join('nodo.js').to_s.to_json
122
138
  end
139
+
140
+ def reserved_method_name?(name)
141
+ Nodo::Core.method_defined?(name, false) || Nodo::Core.private_method_defined?(name, false) || name.to_s == DEFINE_METHOD
142
+ end
123
143
  end
124
144
 
125
145
  def initialize
146
+ raise ClassError, :new if self.class == Nodo::Core
126
147
  @@mutex.synchronize do
127
148
  ensure_process_is_spawned
128
149
  wait_for_socket
@@ -130,6 +151,13 @@ module Nodo
130
151
  end
131
152
  end
132
153
 
154
+ def evaluate(code)
155
+ ensure_context_is_defined
156
+ call_js_method(EVALUATE_METHOD, code)
157
+ end
158
+
159
+ private
160
+
133
161
  def node_pid
134
162
  @@node_pid
135
163
  end
@@ -146,6 +174,17 @@ module Nodo
146
174
  self.class.clsid
147
175
  end
148
176
 
177
+ def context_defined?
178
+ @context_defined
179
+ end
180
+
181
+ def log_exception(e)
182
+ return unless logger = Nodo.logger
183
+ message = "\n#{e.class} (#{e.message})"
184
+ message << ":\n\n#{e.backtrace.join("\n")}" if e.backtrace
185
+ logger.error message
186
+ end
187
+
149
188
  def ensure_process_is_spawned
150
189
  return if node_pid
151
190
  spawn_process
@@ -157,11 +196,22 @@ module Nodo
157
196
  self.class.class_defined = true
158
197
  end
159
198
 
199
+ def ensure_context_is_defined
200
+ return if context_defined?
201
+ @@mutex.synchronize do
202
+ call_js_method(EVALUATE_METHOD, '')
203
+ ObjectSpace.define_finalizer(self, self.class.send(:finalize_context, self.object_id))
204
+ @context_defined = true
205
+ end
206
+ end
207
+
160
208
  def spawn_process
161
209
  @@tmpdir = Pathname.new(Dir.mktmpdir('nodo'))
162
210
  env = Nodo.env.merge('NODE_PATH' => Nodo.modules_root.to_s)
211
+ env['NODO_DEBUG'] = '1' if Nodo.debug
163
212
  @@node_pid = Process.spawn(env, Nodo.binary, '-e', self.class.generate_core_code, '--', socket_path.to_s, err: :out)
164
213
  at_exit do
214
+ @@exiting = true
165
215
  Process.kill(:SIGTERM, node_pid) rescue Errno::ECHILD
166
216
  Process.wait(node_pid) rescue Errno::ECHILD
167
217
  FileUtils.remove_entry(tmpdir) if File.directory?(tmpdir)
@@ -171,7 +221,7 @@ module Nodo
171
221
  def wait_for_socket
172
222
  start = Time.now
173
223
  socket = nil
174
- while Time.now - start < TIMEOUT
224
+ while Time.now - start < LAUNCH_TIMEOUT
175
225
  begin
176
226
  break if socket = UNIXSocket.new(socket_path)
177
227
  rescue Errno::ENOENT, Errno::ECONNREFUSED, Errno::ENOTDIR
@@ -184,10 +234,16 @@ module Nodo
184
234
 
185
235
  def call_js_method(method, args)
186
236
  raise CallError, 'Node process not ready' unless node_pid
187
- raise CallError, "Class #{clsid} not defined" unless self.class.class_defined? || method == DEFINE_METHOD
237
+ raise CallError, "Class #{clsid} not defined" unless self.class.class_defined? || INTERNAL_METHODS.include?(method)
188
238
  function = self.class.functions[method]
189
- raise NameError, "undefined function `#{method}' for #{self.class}" unless function || method == DEFINE_METHOD
190
- request = Net::HTTP::Post.new("/#{clsid}/#{method}", 'Content-Type': 'application/json')
239
+ raise NameError, "undefined function `#{method}' for #{self.class}" unless function || INTERNAL_METHODS.include?(method)
240
+ context_id = case method
241
+ when DEFINE_METHOD then 0
242
+ when GC_METHOD then args.first
243
+ else
244
+ object_id
245
+ end
246
+ request = Net::HTTP::Post.new("/#{clsid}/#{context_id}/#{method}", 'Content-Type': 'application/json')
191
247
  request.body = JSON.dump(args)
192
248
  client = Client.new("unix://#{socket_path}")
193
249
  client.read_timeout = function.timeout if function
@@ -207,9 +263,14 @@ module Nodo
207
263
  def handle_error(response, function)
208
264
  if response.body
209
265
  result = parse_response(response)
210
- raise JavaScriptError.new(result['error'], function) if result.is_a?(Hash) && result.key?('error')
266
+ error = if result.is_a?(Hash) && result['error'].is_a?(Hash)
267
+ attrs = result['error']
268
+ (attrs['nodo_dependency'] ? DependencyError : JavaScriptError).new(attrs, function)
269
+ end
211
270
  end
212
- raise CallError, "Node returned #{response.code}"
271
+ error ||= CallError.new("Node returned #{response.code}")
272
+ log_exception(error)
273
+ raise error
213
274
  end
214
275
 
215
276
  def parse_response(response)
@@ -7,7 +7,16 @@ module Nodo
7
7
  end
8
8
 
9
9
  def to_js
10
- "const #{name} = require(#{package.to_json});\n"
10
+ <<~JS
11
+ const #{name} = __nodo_klass__.#{name} = (() => {
12
+ try {
13
+ return require(#{package.to_json});
14
+ } catch(e) {
15
+ e.nodo_dependency = #{package.to_json};
16
+ throw e;
17
+ }
18
+ })();
19
+ JS
11
20
  end
12
21
  end
13
22
  end
data/lib/nodo/errors.rb CHANGED
@@ -2,6 +2,11 @@ module Nodo
2
2
  class Error < StandardError; end
3
3
  class TimeoutError < Error; end
4
4
  class CallError < Error; end
5
+ class ClassError < Error
6
+ def initialize(method = nil)
7
+ super("Cannot call method `#{method}' on Nodo::Core, use subclass instead")
8
+ end
9
+ end
5
10
 
6
11
  class JavaScriptError < Error
7
12
  attr_reader :attributes
@@ -37,13 +42,23 @@ module Nodo
37
42
  end
38
43
 
39
44
  def generate_message
40
- message = "#{attributes['message'] || 'Unknown error'}"
41
- if loc = attributes['loc']
42
- message << loc.inject(' in') { |s, (key, value)| s << " #{key}: #{value}" }
43
- end
44
- message
45
+ message = "#{attributes['message'] || attributes['name'] || 'Unknown error'}"
46
+ message << format_location(attributes['loc'])
47
+ end
48
+
49
+ def format_location(loc)
50
+ return '' unless loc
51
+ loc.inject(' in') { |s, (key, value)| s << " #{key}: #{value}" }
45
52
  end
46
53
  end
47
54
 
48
- class DependencyError < JavaScriptError; end
55
+ class DependencyError < JavaScriptError
56
+ private
57
+
58
+ def generate_message
59
+ message = "#{attributes['message'] || attributes['name'] || 'Dependency error'}\n"
60
+ message << "The specified dependency '#{attributes['nodo_dependency']}' could not be loaded. "
61
+ message << "Run 'yarn add #{attributes['nodo_dependency']}' to install it.\n"
62
+ end
63
+ end
49
64
  end
data/lib/nodo/nodo.js CHANGED
@@ -1,5 +1,8 @@
1
1
  module.exports = (function() {
2
2
  const DEFINE_METHOD = '__nodo_define_class__';
3
+ const EVALUATE_METHOD = '__nodo_evaluate__';
4
+ const GC_METHOD = '__nodo_gc__';
5
+ const DEBUG = process.env.NODO_DEBUG;
3
6
 
4
7
  const vm = require('vm');
5
8
  const http = require('http');
@@ -9,6 +12,7 @@ module.exports = (function() {
9
12
 
10
13
  let server, closing;
11
14
  const classes = {};
15
+ const contexts = {};
12
16
 
13
17
  function render_error(e) {
14
18
  let errInfo = {};
@@ -24,7 +28,7 @@ module.exports = (function() {
24
28
  function respond_with_error(res, code, name) {
25
29
  res.statusCode = code;
26
30
  const rendered = render_error(name);
27
- log(`Error ${code} ${rendered}`);
31
+ debug(`Error ${code} ${rendered}`);
28
32
  res.end(rendered, 'utf8');
29
33
  }
30
34
 
@@ -35,34 +39,41 @@ module.exports = (function() {
35
39
  if (start) {
36
40
  timing = ` in ${(performance.now() - start).toFixed(2)}ms`;
37
41
  }
38
- log(`Completed 200 OK${timing}`);
42
+ debug(`Completed 200 OK${timing}\n`);
39
43
  }
40
44
 
41
- function log(message) {
42
- // fs.appendFileSync('log/nodo.log', `${message}\n`);
43
- // console.log(`[Nodo] ${message}`);
45
+ function debug(message) {
46
+ if (DEBUG) {
47
+ // fs.appendFileSync('log/nodo.log', `${message}\n`);
48
+ console.log(`[Nodo] ${message}`);
49
+ }
44
50
  }
45
51
 
46
52
  const core = {
47
53
  run: (socket) => {
48
- log('Starting up...');
54
+ debug('Starting up...');
49
55
  server = http.createServer((req, res) => {
50
56
  const start = performance.now();
51
57
 
52
58
  res.setHeader('Content-Type', 'application/json');
53
- log(`${req.method} ${req.url}`);
59
+ debug(`${req.method} ${req.url}`);
54
60
 
55
61
  if (req.method !== 'POST' || !req.url.startsWith('/')) {
56
62
  return respond_with_error(res, 405, 'Method Not Allowed');
57
63
  }
58
64
 
59
65
  const url = req.url.substring(1);
60
- const [class_name, method] = url.split('/');
61
- let klass;
66
+ const [class_name, object_id, method] = url.split('/');
67
+ let klass, context;
62
68
 
63
69
  if (classes.hasOwnProperty(class_name)) {
64
70
  klass = classes[class_name];
65
- if (!klass.hasOwnProperty(method)) {
71
+ if (EVALUATE_METHOD == method) {
72
+ if (!contexts.hasOwnProperty(object_id)) {
73
+ contexts[object_id] = vm.createContext({ require: require, ...klass });
74
+ }
75
+ context = contexts[object_id];
76
+ } else if (!klass.hasOwnProperty(method) && !GC_METHOD == method) {
66
77
  return respond_with_error(res, 404, `Method ${class_name}#${method} not found`);
67
78
  }
68
79
  } else if (DEFINE_METHOD != method) {
@@ -84,13 +95,21 @@ module.exports = (function() {
84
95
 
85
96
  try {
86
97
  if (DEFINE_METHOD == method) {
87
- let new_class = vm.runInThisContext(input, class_name);
88
- classes[class_name] = new_class;
98
+ classes[class_name] = vm.runInThisContext(input, class_name);
89
99
  respond_with_data(res, class_name, start);
100
+ } else if (EVALUATE_METHOD == method) {
101
+ Promise.resolve(vm.runInNewContext(input, context)).then((result) => {
102
+ respond_with_data(res, result, start);
103
+ }).catch((error) => {
104
+ respond_with_error(res, 500, error);
105
+ });
106
+ } else if (GC_METHOD == method) {
107
+ delete contexts[object_id];
108
+ respond_with_data(res, true, start);
90
109
  } else {
91
- Promise.resolve(klass[method].apply(null, input)).then(function (result) {
110
+ Promise.resolve(klass[method].apply(null, input)).then((result) => {
92
111
  respond_with_data(res, result, start);
93
- }).catch(function(error) {
112
+ }).catch((error) => {
94
113
  respond_with_error(res, 500, error);
95
114
  });
96
115
  }
@@ -103,12 +122,12 @@ module.exports = (function() {
103
122
 
104
123
  //server.maxConnections = 64;
105
124
  server.listen(socket, () => {
106
- log(`server ready, listening on ${socket} (max connections: ${server.maxConnections})`);
125
+ debug(`server ready, listening on ${socket} (max connections: ${server.maxConnections})`);
107
126
  });
108
127
  },
109
128
 
110
129
  close: (finalizer) => {
111
- log("Shutting down");
130
+ debug("Shutting down");
112
131
  if (!closing) {
113
132
  closing = true;
114
133
  server.close(finalizer);
@@ -116,5 +135,5 @@ module.exports = (function() {
116
135
  }
117
136
  };
118
137
 
119
- return { core: core, log: log };
138
+ return { core: core, debug: debug };
120
139
  })();
data/lib/nodo/railtie.rb CHANGED
@@ -3,6 +3,7 @@ require 'active_support'
3
3
 
4
4
  class Nodo::Railtie < Rails::Railtie
5
5
  initializer 'nodo' do |app|
6
- Nodo.modules_root = Rails.root.join('vendor', 'node_modules')
6
+ Nodo.env['NODE_ENV'] = Rails.env.to_s
7
+ Nodo.logger = Rails.logger
7
8
  end
8
9
  end
data/lib/nodo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Nodo
2
- VERSION = '1.5.5'
2
+ VERSION = '1.6.2'
3
3
  end
data/lib/nodo.rb CHANGED
@@ -3,16 +3,20 @@ require 'json'
3
3
  require 'fileutils'
4
4
  require 'tmpdir'
5
5
  require 'tempfile'
6
+ require 'logger'
6
7
  require 'socket'
7
8
  require 'forwardable'
8
9
 
9
10
  module Nodo
10
11
  class << self
11
- attr_accessor :modules_root, :env, :binary
12
+ attr_accessor :modules_root, :env, :binary, :logger, :debug, :timeout
12
13
  end
13
14
  self.modules_root = './node_modules'
14
15
  self.env = {}
15
16
  self.binary = 'node'
17
+ self.logger = Logger.new(STDOUT)
18
+ self.debug = false
19
+ self.timeout = 60
16
20
  end
17
21
 
18
22
  require_relative 'nodo/version'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nodo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.5
4
+ version: 1.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthias Grosser