func_e 0.0.5 → 0.0.7

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: 03d79cc58581d2b50d1c2f5e3b461b0f7d8f95bf173d8f8a87174963d9b3bb8e
4
- data.tar.gz: cac711c8e9976711cdd9f1a8ffb6475af977d8f5a48c60f4000f82cbdd99b4b8
3
+ metadata.gz: cf3d794b61b361924e275872acc6e494f8ffd636d67b8270e024fc8d5bcbca15
4
+ data.tar.gz: 1832b1fa89c5a55af3c9cfc078f77b22fca9aaad118487cbb55dfc0ff13ae484
5
5
  SHA512:
6
- metadata.gz: 36a14915583fdb6bf948a58ab14b343ac1bf0bf4bff69537dac3bc19e7d3796ba08afc037eee99fe96b2c596f4e381e3bdaa5bc5c645cff14758cbfdaea55f7e
7
- data.tar.gz: c1ba5cbbcc7026350feeedd706aa8586a647eca69d4a1da48406c56b6ee33c21c853c24ed86eb4ee48c282da903b9159d2dd160d5297de0735f14e7604ca5c37
6
+ metadata.gz: ec48dbbc2838b5bd799d62d04fcda789a0cf45d5a92f76af2ab22c7c6b1430db7c9d89526b4a3dae3cae52581140c3238ad2ff74cf5b0c7c971e327087af7167
7
+ data.tar.gz: adf4ef50a1c9c9b5024f0528ba34b9807cd19801fd71c612f83a20369d1937eb8a736553ae077cfc7554658a109253a29cf076bd2a885a451bbe92d75a22ccc8
data/lib/func_e/config.rb CHANGED
@@ -8,29 +8,34 @@ module FuncE
8
8
  class Config
9
9
  include Singleton
10
10
 
11
+ DEFAULT_PORT = 3030
11
12
  DEFAULT_INSTALL_DIR = 'funcs'
12
13
 
13
- attr_accessor :fn_dir_path
14
+ attr_accessor :fn_dir_path, :local_server, :local_server_port
14
15
 
15
16
  def self.configure
16
17
  yield instance
18
+
19
+ # Set default values if they are not set.
20
+ instance.local_server ||= false
21
+ instance.local_server_port ||= DEFAULT_PORT
22
+ instance.fn_dir_path ||= DEFAULT_INSTALL_DIR
23
+
24
+ # Start the server if the local_server option is set to true.
25
+ FuncE::Http.start_server if instance.local_server
17
26
  end
18
27
 
19
28
  def self.config
20
29
  instance
21
30
  end
22
31
 
23
- def self.get(key)
24
- instance.send(key)
25
- end
26
-
27
32
  def self.install_path
28
33
  if defined?(Rails)
29
- Rails.root.join(@fn_dir_path || DEFAULT_INSTALL_DIR)
34
+ Rails.root.join(config.fn_dir_path)
30
35
  elsif defined?(Bundler)
31
- Bundler.root.join(@fn_dir_path || DEFAULT_INSTALL_DIR)
36
+ Bundler.root.join(config.fn_dir_path)
32
37
  else
33
- Pathname.new(Dir.pwd).join(@fn_dir_path || DEFAULT_INSTALL_DIR)
38
+ Pathname.new(Dir.pwd).join(config.fn_dir_path)
34
39
  end
35
40
  end
36
41
  end
data/lib/func_e/func.rb CHANGED
@@ -24,6 +24,10 @@ module FuncE
24
24
  @result
25
25
  end
26
26
 
27
+ def set_payload(payload)
28
+ @payload = payload
29
+ end
30
+
27
31
  def serialize_payload
28
32
  @payload.to_json
29
33
  end
@@ -0,0 +1,44 @@
1
+ require 'net/http'
2
+
3
+ module FuncE
4
+ module Http
5
+ def self.uri
6
+ URI("http://localhost:#{FuncE::Config.config.local_server_port}")
7
+ end
8
+
9
+ def self.headers
10
+ { 'Content-Type': 'application/json' }
11
+ end
12
+
13
+ def self.post(func)
14
+ Net::HTTP.post(uri, { name: func.name, payload: func.payload }.to_json, headers)
15
+ end
16
+
17
+ def self.start_server
18
+ kill_server
19
+ npm_install if has_dependencies?
20
+ Thread.new { node_serve }
21
+ end
22
+
23
+ def self.kill_server
24
+ active_pid.tap { |pid| system("kill -9 #{pid}") unless pid.zero? }
25
+ end
26
+
27
+ def self.npm_install
28
+ puts "Installing func_e dependencies..."
29
+ system("cd #{Config.install_path} && npm i && cd #{`pwd`.strip}")
30
+ end
31
+
32
+ def self.node_serve
33
+ system("node #{FuncE::SERVER_PATH} --port=#{Config.config.local_server_port} --functions_path=#{Config.install_path}")
34
+ end
35
+
36
+ def self.active_pid
37
+ `lsof -i:#{Config.config.local_server_port} -t`.to_i
38
+ end
39
+
40
+ def self.has_dependencies?
41
+ File.exist?("#{Config.install_path}/package.json")
42
+ end
43
+ end
44
+ end
data/lib/func_e.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require 'json'
4
4
  require 'terrapin'
5
5
 
6
+ require 'func_e/http'
6
7
  require 'func_e/func'
7
8
  require 'func_e/config'
8
9
 
@@ -10,10 +11,21 @@ require 'func_e/config'
10
11
  module FuncE
11
12
  require 'railtie' if defined?(Rails)
12
13
 
13
- RUNNER_PATH = "#{File.expand_path(__dir__)}/func_e.js"
14
+ RUNNER_PATH = "#{File.expand_path(__dir__)}/func_e_runner.js"
15
+ SERVER_PATH = "#{File.expand_path(__dir__)}/func_e_server.js"
14
16
 
15
17
  def self.exec(func)
16
- JSON.parse line.run(path: func.path, payload: func.serialize_payload), symbolize_names: true
18
+ Config.config.local_server ? server(func) : runner(func)
19
+ end
20
+
21
+ def self.server(func)
22
+ json_parse FuncE::Http.post(func).body
23
+ rescue Errno::ECONNREFUSED
24
+ { error: 'The server is not running. Please start the server before executing functions.' }
25
+ end
26
+
27
+ def self.runner(func)
28
+ json_parse line.run(path: func.path, payload: func.serialize_payload)
17
29
  rescue Terrapin::CommandLineError => e
18
30
  { error: 'An error occurred while executing the node function.', message: e.message }
19
31
  end
@@ -21,4 +33,8 @@ module FuncE
21
33
  def self.line
22
34
  Terrapin::CommandLine.new("node #{RUNNER_PATH}", '--path=:path --payload=:payload')
23
35
  end
36
+
37
+ def self.json_parse(json)
38
+ JSON.parse(json, symbolize_names: true)
39
+ end
24
40
  end
@@ -9,18 +9,7 @@
9
9
  * always return an Promise that resolves to the result of the function. Thus
10
10
  * all functions must be asynchronous.
11
11
  */
12
-
13
- /**
14
- * Extract the arguments from the command line.
15
- */
16
- let args = {};
17
-
18
- process.argv.slice(2).forEach(arg => {
19
- if (arg.startsWith('--')) {
20
- const split = arg.indexOf('=');
21
- args[arg.substring(2, split)] = arg.substring(split + 1);
22
- }
23
- })
12
+ const args = require('./support/args')();
24
13
 
25
14
  // If any of the required arguments are missing, throw an error.
26
15
  if (!args.path) throw new Error('Missing function name (--fn=<FUNCTION_NAME>');
@@ -0,0 +1,70 @@
1
+ const fs = require("fs");
2
+ const http = require("http");
3
+
4
+ // Get the port number from the cli arguments or use the default port number
5
+ const args = require("./support/args")();
6
+
7
+ const PORT = args.port || 3030;
8
+
9
+ /**
10
+ * Load all the functions from the provided directory.
11
+ */
12
+ let functions = fs.readdirSync(args.functions_path).reduce((obj, file) => {
13
+ const isFunction = file.endsWith(".js");
14
+
15
+ if (isFunction) {
16
+ const functionName = file.split(".")[0];
17
+ const functionPath = args.functions_path + "/" + file;
18
+ obj[functionName] = require(functionPath);
19
+ }
20
+
21
+ return obj;
22
+ }, {});
23
+
24
+ const invalidRequestMethodError = JSON.stringify({
25
+ message: "This server only accepts POST requests"
26
+ })
27
+
28
+ const functionExecutionError = (err) => JSON.stringify({
29
+ error: err.message
30
+ });
31
+
32
+ const functionNotFoundError = (name) => JSON.stringify({
33
+ error: `Function "${name}" not loaded. Check the function name or restart the server.`
34
+ })
35
+
36
+ function setDefaultHeaders(res) {
37
+ res.setHeader("Content-Type", "application/json");
38
+ }
39
+
40
+ function handler(req, res) {
41
+ if (req.method != "POST") res.end(invalidRequestMethodError);
42
+
43
+ setDefaultHeaders(res)
44
+
45
+ let post_data = "";
46
+
47
+ req.on("data", chunk => post_data += chunk);
48
+ req.on("end", () => {
49
+ const data = JSON.parse(post_data);
50
+ const fn = functions[data.name];
51
+
52
+ if (!fn) {
53
+ res.statusCode = 404;
54
+ res.end(functionNotFoundError(data.name));
55
+ } else {
56
+ fn(data.payload)
57
+ .then((result) => {
58
+ res.statusCode = 200;
59
+ res.end(JSON.stringify(result));
60
+ }).catch((err) => {
61
+ res.statusCode = 500;
62
+ res.end(functionExecutionError(err));
63
+ });
64
+ }
65
+ });
66
+ }
67
+
68
+ const server = http.createServer(handler);
69
+
70
+ server.listen(PORT, () => console.log(`\nRunning FuncE server on http://localhost:${PORT}/\n`));
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Extract the arguments from the command line and return them as an object
3
+ * of key value pairs. Args are expected to be in the format --key=value.
4
+ */
5
+ module.exports = () => {
6
+ let args = {};
7
+
8
+ process.argv.slice(2).forEach(arg => {
9
+ if (arg.startsWith('--')) {
10
+ const split = arg.indexOf('=');
11
+ args[arg.substring(2, split)] = arg.substring(split + 1);
12
+ }
13
+ })
14
+
15
+ return args;
16
+ };
@@ -1,4 +1,4 @@
1
- module.exports = function helloFn({ planet }) {
1
+ module.exports = async function helloFn({ planet }) {
2
2
  return {
3
3
  result: `Hello, ${planet}!`
4
4
  }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: func_e
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sebastian Scholl
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-08-31 00:00:00.000000000 Z
11
+ date: 2024-09-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: terrapin
@@ -36,11 +36,14 @@ executables: []
36
36
  extensions: []
37
37
  extra_rdoc_files: []
38
38
  files:
39
- - lib/func_e.js
40
39
  - lib/func_e.rb
41
40
  - lib/func_e/config.rb
42
41
  - lib/func_e/func.rb
42
+ - lib/func_e/http.rb
43
+ - lib/func_e_runner.js
44
+ - lib/func_e_server.js
43
45
  - lib/railtie.rb
46
+ - lib/support/args.js
44
47
  - lib/tasks/install/install.rake
45
48
  - lib/tasks/install/template/helloFn.js
46
49
  - lib/tasks/install/template/package.json