terminalwire-server 0.3.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6478b8cc01d3c36333ca938f647700798e211487fd6a4c076b91809348f8adaf
4
+ data.tar.gz: 5bf273aeb4f3cf36df8b4af47e78b96761daf2be32f6fc31945c6beb4bc235e9
5
+ SHA512:
6
+ metadata.gz: 5f6793ba99120adaef93ae16bbe9b71f38213f426bf3765ff19bea8d47fa7c5784df7d9c42c7e338769aa29ad9b3ae466cb961446f3cdaa77c6680429cfa4469
7
+ data.tar.gz: c0bbf7cb3d28d0a97893ad7befcf5b39404bdef47d55a7074cbfa6d1e3401466fd1b887d6ea46347b6b42050015568c3177b0d3bb66afd477b0a88d213fe692d
@@ -0,0 +1,80 @@
1
+ require "fileutils"
2
+
3
+ module Terminalwire::Server
4
+ # Contains all of the resources that are accessible to the server on the client-side.
5
+ # It's the primary interface for the server to interact with the client and is integrated
6
+ # into other libraries like Thor, etc.
7
+ class Context
8
+ extend Forwardable
9
+
10
+ attr_reader \
11
+ :stdout, :stdin, :stderr,
12
+ :browser,
13
+ :file, :directory,
14
+ :environment_variable,
15
+ :authority,
16
+ :root_path,
17
+ :authority_path,
18
+ :storage_path
19
+
20
+ def_delegators :@stdout, :puts, :print
21
+ def_delegators :@stdin, :gets, :getpass
22
+
23
+ def initialize(adapter:, entitlement:)
24
+ @adapter = adapter
25
+ @entitlement = entitlement
26
+
27
+ # Initialize resources
28
+ @stdout = Resource::STDOUT.new("stdout", @adapter)
29
+ @stdin = Resource::STDIN.new("stdin", @adapter)
30
+ @stderr = Resource::STDERR.new("stderr", @adapter)
31
+ @browser = Resource::Browser.new("browser", @adapter)
32
+ @file = Resource::File.new("file", @adapter)
33
+ @directory = Resource::Directory.new("directory", @adapter)
34
+ @environment_variable = Resource::EnvironmentVariable.new("environment_variable", @adapter)
35
+
36
+ # Authority is provided by the client.
37
+ @authority = @entitlement.fetch(:authority)
38
+ # The Terminalwire home path is provided by the client and set
39
+ # as an environment variable.
40
+ @root_path = Pathname.new(
41
+ @environment_variable.read("TERMINALWIRE_HOME")
42
+ )
43
+ # Now derive the rest of the paths from the Terminalwire home path.
44
+ @authority_path = @root_path.join("authorities", @authority)
45
+ @storage_path = @authority_path.join("storage")
46
+
47
+ if block_given?
48
+ begin
49
+ yield self
50
+ ensure
51
+ exit
52
+ end
53
+ end
54
+ end
55
+
56
+ # Wraps the environment variables in a hash-like object that can be accessed
57
+ # from client#ENV. This makes it look and feel just like the ENV object in Ruby.
58
+ class Env
59
+ def initialize(context:)
60
+ @context = context
61
+ end
62
+
63
+ def [](name)
64
+ @context.environment_variable.read(name)
65
+ end
66
+ end
67
+
68
+ def ENV
69
+ @ENV ||= Env.new(context: self)
70
+ end
71
+
72
+ def exit(status = 0)
73
+ @adapter.write(event: "exit", status: status)
74
+ end
75
+
76
+ def close
77
+ @adapter.close
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,120 @@
1
+ module Terminalwire::Server
2
+ # Representation of the resources avilable to the server on the client-side. These
3
+ # classes encapsulate the API alls to the client and provide a more Ruby-like interface.
4
+ module Resource
5
+ class Base < Terminalwire::Resource::Base
6
+ private
7
+
8
+ def command(command, **parameters)
9
+ @adapter.write(
10
+ event: "resource",
11
+ name: @name,
12
+ action: "command",
13
+ command: command,
14
+ parameters: parameters
15
+ )
16
+
17
+ response = @adapter.read
18
+ case response.fetch(:status)
19
+ when "success"
20
+ response.fetch(:response)
21
+ when "failure"
22
+ raise Terminalwire::Error, response.inspect
23
+ end
24
+ end
25
+ end
26
+
27
+ class EnvironmentVariable < Base
28
+ # Accepts a list of environment variables to permit.
29
+ def read(name)
30
+ command("read", name:)
31
+ end
32
+
33
+ # def write(name:, value:)
34
+ # command("write", name:, value:)
35
+ # end
36
+ end
37
+
38
+ class STDOUT < Base
39
+ def puts(data)
40
+ command("print_line", data: data)
41
+ end
42
+
43
+ def print(data)
44
+ command("print", data: data)
45
+ end
46
+
47
+ def flush
48
+ # Do nothing
49
+ end
50
+ end
51
+
52
+ class STDERR < STDOUT
53
+ end
54
+
55
+ class STDIN < Base
56
+ def getpass
57
+ command("read_password")
58
+ end
59
+
60
+ def gets
61
+ command("read_line")
62
+ end
63
+ end
64
+
65
+ class File < Base
66
+ def read(path)
67
+ command("read", path: path.to_s)
68
+ end
69
+
70
+ def write(path, content)
71
+ command("write", path: path.to_s, content:)
72
+ end
73
+
74
+ def append(path, content)
75
+ command("append", path: path.to_s, content:)
76
+ end
77
+
78
+ def delete(path)
79
+ command("delete", path: path.to_s)
80
+ end
81
+ alias :rm :delete
82
+
83
+ def exist?(path)
84
+ command("exist", path: path.to_s)
85
+ end
86
+
87
+ def change_mode(path, mode)
88
+ command("change_mode", path: path.to_s, mode:)
89
+ end
90
+ alias :chmod :change_mode
91
+ end
92
+
93
+ class Directory < Base
94
+ def list(path)
95
+ command("list", path: path.to_s)
96
+ end
97
+ alias :ls :list
98
+
99
+ def create(path)
100
+ command("create", path: path.to_s)
101
+ end
102
+ alias :mkdir :create
103
+
104
+ def exist?(path)
105
+ command("exist", path: path.to_s)
106
+ end
107
+
108
+ def delete(path)
109
+ command("delete", path: path.to_s)
110
+ end
111
+ alias :rm :delete
112
+ end
113
+
114
+ class Browser < Base
115
+ def launch(url)
116
+ command("launch", url: url)
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,69 @@
1
+ require 'thor'
2
+
3
+ module Terminalwire
4
+ module Server
5
+ module Thor
6
+ class Shell < ::Thor::Shell::Basic
7
+ extend Forwardable
8
+
9
+ # Encapsulates all of the IO resources for a Terminalwire adapter.
10
+ attr_reader :context, :session
11
+
12
+ def_delegators :context,
13
+ :stdin, :stdout, :stderr
14
+
15
+ def initialize(context, *, **, &)
16
+ @context = context
17
+ @session = Terminalwire::Rails::Session.new(context:)
18
+ super(*,**,&)
19
+ end
20
+ end
21
+
22
+ def self.included(base)
23
+ base.extend ClassMethods
24
+
25
+ # I have to do this in a block to deal with some of Thor's DSL
26
+ base.class_eval do
27
+ extend Forwardable
28
+
29
+ protected
30
+
31
+ no_commands do
32
+ def_delegators :shell,
33
+ :context, :session
34
+ def_delegators :context,
35
+ :stdout, :stdin, :stderr, :browser
36
+ def_delegators :stdout,
37
+ :puts, :print
38
+ def_delegators :stdin,
39
+ :gets, :getpass
40
+
41
+ # Prints text to the standard error stream.
42
+ def warn(...)
43
+ stderr.puts(...)
44
+ end
45
+
46
+ # Prints text to the standard error stream and exits the program.
47
+ def fail(...)
48
+ stderr.puts(...)
49
+ context.exit 1
50
+ ensure
51
+ super
52
+ end
53
+ # Feels more naturual to call `client.files` etc. from
54
+ # the serve since it's more apparent that it's a client.
55
+ alias :client :context
56
+ end
57
+ end
58
+ end
59
+
60
+ module ClassMethods
61
+ def start(given_args = ARGV, config = {})
62
+ context = config.delete(:context)
63
+ config[:shell] = Shell.new(context) if context
64
+ super(given_args, config)
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,27 @@
1
+ require "terminalwire"
2
+ require "terminalwire/logging"
3
+
4
+ require "zeitwerk"
5
+ Zeitwerk::Loader.for_gem_extension(Terminalwire).tap do |loader|
6
+ loader.setup
7
+ end
8
+
9
+ module Terminalwire
10
+ module Server
11
+ class WebSocket
12
+ include Logging
13
+
14
+ def call(env)
15
+ Async::WebSocket::Adapters::Rack.open(env, protocols: ['ws']) do |connection|
16
+ handle(Adapter::Socket.new(Terminalwire::Transport::WebSocket.new(connection)))
17
+ end or [200, { "Content-Type" => "text/plain" }, ["Connect via WebSockets"]]
18
+ end
19
+
20
+ def handle(adapter)
21
+ while message = adapter.read
22
+ puts message
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'terminalwire/server'
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: terminalwire-server
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0.alpha1
5
+ platform: ruby
6
+ authors:
7
+ - Brad Gessler
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-12-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: terminalwire-core
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 0.3.0.alpha1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 0.3.0.alpha1
41
+ description: Stream command-line apps from your server without a web API
42
+ email:
43
+ - brad@terminalwire.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - lib/terminalwire-server.rb
49
+ - lib/terminalwire/server.rb
50
+ - lib/terminalwire/server/context.rb
51
+ - lib/terminalwire/server/resource.rb
52
+ - lib/terminalwire/server/thor.rb
53
+ homepage: https://terminalwire.com/ruby
54
+ licenses:
55
+ - Proprietary (https://terminalwire.com/license)
56
+ metadata:
57
+ allowed_push_host: https://rubygems.org/
58
+ homepage_uri: https://terminalwire.com/ruby
59
+ source_code_uri: https://github.com/terminalwire/ruby/tree/main/terminalwire-server
60
+ changelog_uri: https://github.com/terminalwire/ruby/tags
61
+ funding_uri: https://terminalwire.com/funding
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: 3.0.0
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirements: []
77
+ rubygems_version: 3.5.9
78
+ signing_key:
79
+ specification_version: 4
80
+ summary: Ship a CLI for your web app. No API required.
81
+ test_files: []