terminalwire-server 0.3.0.alpha1

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 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: []