nodo 1.5.0 → 1.5.1

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: 8f997b2c506f2cec9bfd235c68cb0db93fcb103fa7f9b40f03740ca27b59ffb4
4
- data.tar.gz: 8a1ba6ae691ee2a992b2af5a127c43c70178cc403134db04a08f9597dd8588b3
3
+ metadata.gz: c2a8ef54e67cf745b78353e740a440edf45ee300e97d50d7e0edd93abf33bf62
4
+ data.tar.gz: 4c5196d63edf85242640050487a86b582fb2fe9d373b79408750973b88622a68
5
5
  SHA512:
6
- metadata.gz: 77c7a96627569da1b4093eb0fbfb6ab94c0c7dae4e425b019d52e06183f098daac57b88f68924fbe117afc1a0cf8be3aec143fd8e6935c839ebd573dde5afd70
7
- data.tar.gz: 8057351d0968d8bc357af3926b805f82ce6e05949ee54efb9df40293ba4faf0ce8d337550318de0114c7f9dc2df05958ea481dc35aa2981a0d95501c9cb18c64
6
+ metadata.gz: aad587338156426fd70ba262b01086056e70730aeff6774e70272c01898c9ba81e2937121226304dc00cd38f83917a788da5507160577747829a595a03a37e13
7
+ data.tar.gz: 14abb31d37eb578bba1233afa22c6f1d5c79ea28d9cb48eefa052604a3d148494f58c7af019b6ec85682348d357fdef79d14fea2e4d90cb30de96a6222b5935f
data/README.md CHANGED
@@ -117,8 +117,9 @@ end
117
117
  class BarFoo < Nodo::Core
118
118
 
119
119
  script <<~JS
120
- // some custom JS
121
- // to be executed during initialization
120
+ // custom JS to be executed during initialization
121
+ // things defined here can later be used inside functions
122
+ const bigThing = someLib.init();
122
123
  JS
123
124
  end
124
125
  ```
@@ -126,3 +127,34 @@ end
126
127
  ### Inheritance
127
128
 
128
129
  Subclasses will inherit functions, constants, dependencies and scripts from their superclasses, while only functions can be overwritten.
130
+
131
+ ```ruby
132
+ class Foo < Nodo::Core
133
+ function :foo, "() => 'superclass'"
134
+ end
135
+
136
+ class SubFoo < Foo
137
+ function :bar, "() => { return 'calling' + foo() }"
138
+ end
139
+
140
+ class SubSubFoo < SubFoo
141
+ function :foo, "() => 'subsubclass'"
142
+ end
143
+
144
+ Foo.new.foo => "superclass"
145
+ SubFoo.new.bar => "callingsuperclass"
146
+ SubSubFoo.new.bar => "callingsubsubclass"
147
+ ```
148
+
149
+ ### Async functions
150
+
151
+ `Nodo` supports calling `async` functions from Ruby.
152
+ The Ruby call will happen synchronously, i.e. it will block until the JS function resolves:
153
+
154
+ ```ruby
155
+ class SyncFoo < Nodo::Core
156
+ function :do_something, <<~JS
157
+ async () => { return await asyncFunc(); }
158
+ JS
159
+ end
160
+ ```
data/lib/nodo/nodo.js ADDED
@@ -0,0 +1,120 @@
1
+ module.exports = (function() {
2
+ const DEFINE_METHOD = '__nodo_define_class__';
3
+
4
+ const vm = require('vm');
5
+ const http = require('http');
6
+ const path = require('path');
7
+ const fs = require('fs');
8
+ const performance = require('perf_hooks').performance;
9
+
10
+ let server, closing;
11
+ const classes = {};
12
+
13
+ function render_error(e) {
14
+ let errInfo = {};
15
+ if (e instanceof Error) {
16
+ errInfo.name = e.name;
17
+ Object.getOwnPropertyNames(e).reduce((obj, prop) => { obj[prop] = e[prop]; return obj }, errInfo);
18
+ } else {
19
+ errInfo.name = e.toString();
20
+ }
21
+ return JSON.stringify({ error: errInfo });
22
+ }
23
+
24
+ function respond_with_error(res, code, name) {
25
+ res.statusCode = code;
26
+ const rendered = render_error(name);
27
+ log(`Error ${code} ${rendered}`);
28
+ res.end(rendered, 'utf8');
29
+ }
30
+
31
+ function respond_with_data(res, data, start) {
32
+ let timing;
33
+ res.statusCode = 200;
34
+ res.end(JSON.stringify(data), 'utf8');
35
+ if (start) {
36
+ timing = ` in ${(performance.now() - start).toFixed(2)}ms`;
37
+ }
38
+ log(`Completed 200 OK${timing}`);
39
+ }
40
+
41
+ function log(message) {
42
+ // fs.appendFileSync('log/nodo.log', `${message}\n`);
43
+ // console.log(`[Nodo] ${message}`);
44
+ }
45
+
46
+ const core = {
47
+ run: (socket) => {
48
+ log('Starting up...');
49
+ server = http.createServer((req, res) => {
50
+ const start = performance.now();
51
+
52
+ res.setHeader('Content-Type', 'application/json');
53
+ log(`${req.method} ${req.url}`);
54
+
55
+ if (req.method !== 'POST' || !req.url.startsWith('/')) {
56
+ return respond_with_error(res, 405, 'Method Not Allowed');
57
+ }
58
+
59
+ const url = req.url.substring(1);
60
+ const [class_name, method] = url.split('/');
61
+ let klass;
62
+
63
+ if (classes.hasOwnProperty(class_name)) {
64
+ klass = classes[class_name];
65
+ if (!klass.hasOwnProperty(method)) {
66
+ return respond_with_error(res, 404, `Method ${class_name}#${method} not found`);
67
+ }
68
+ } else if (DEFINE_METHOD != method) {
69
+ return respond_with_error(res, 404, `Class ${class_name} not defined`);
70
+ }
71
+
72
+ let body = '';
73
+
74
+ req.on('data', (data) => { body += data; });
75
+
76
+ req.on('end', () => {
77
+ let input, result;
78
+
79
+ try {
80
+ input = JSON.parse(body);
81
+ } catch (e) {
82
+ return respond_with_error(res, 400, 'Bad Request');
83
+ }
84
+
85
+ try {
86
+ if (DEFINE_METHOD == method) {
87
+ let new_class = vm.runInThisContext(input, class_name);
88
+ classes[class_name] = new_class;
89
+ respond_with_data(res, class_name, start);
90
+ } else {
91
+ Promise.resolve(klass[method].apply(null, input)).then(function (result) {
92
+ respond_with_data(res, result, start);
93
+ }).catch(function(error) {
94
+ respond_with_error(res, 500, error);
95
+ });
96
+ }
97
+ } catch(error) {
98
+ return respond_with_error(res, 500, error);
99
+ }
100
+
101
+ });
102
+ });
103
+
104
+ //server.maxConnections = 64;
105
+ server.listen(socket, () => {
106
+ log(`server ready, listening on ${socket} (max connections: ${server.maxConnections})`);
107
+ });
108
+ },
109
+
110
+ close: (finalizer) => {
111
+ log("Shutting down");
112
+ if (!closing) {
113
+ closing = true;
114
+ server.close(finalizer);
115
+ }
116
+ }
117
+ };
118
+
119
+ return { core: core, log: log };
120
+ })();
data/lib/nodo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Nodo
2
- VERSION = '1.5.0'
2
+ VERSION = '1.5.1'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nodo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthias Grosser
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-10-02 00:00:00.000000000 Z
11
+ date: 2021-10-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -82,6 +82,7 @@ files:
82
82
  - lib/nodo/dependency.rb
83
83
  - lib/nodo/errors.rb
84
84
  - lib/nodo/function.rb
85
+ - lib/nodo/nodo.js
85
86
  - lib/nodo/railtie.rb
86
87
  - lib/nodo/script.rb
87
88
  - lib/nodo/version.rb
@@ -89,7 +90,7 @@ homepage: https://github.com/mtgrosser/nodo
89
90
  licenses:
90
91
  - MIT
91
92
  metadata: {}
92
- post_install_message:
93
+ post_install_message:
93
94
  rdoc_options: []
94
95
  require_paths:
95
96
  - lib
@@ -105,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
105
106
  version: '0'
106
107
  requirements: []
107
108
  rubygems_version: 3.0.3
108
- signing_key:
109
+ signing_key:
109
110
  specification_version: 4
110
111
  summary: Call Node.js from Ruby
111
112
  test_files: []