terminalwire 0.1.7 → 0.1.8
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 +4 -4
- data/lib/terminalwire/adapter.rb +24 -3
- data/lib/terminalwire/client/entitlement.rb +93 -12
- data/lib/terminalwire/client/resource.rb +35 -16
- data/lib/terminalwire/client.rb +4 -3
- data/lib/terminalwire/server/context.rb +42 -0
- data/lib/terminalwire/server/resource.rb +100 -0
- data/lib/terminalwire/server.rb +1 -116
- data/lib/terminalwire/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 021c12812432f96320c0ba322f4aa71e1b1cfb60c52b77bc6cd78013da78c517
|
4
|
+
data.tar.gz: b5f13d773a7c7bc4d7f5e358c2fb0d498a9061fb6cb191f9ab55bc6fe3131767
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f3206e529d8628243061e87cf4b1782e4d61a368333627e2526f5e251e25daefec1f8a4e24fb71e85c5aa3f1114138eb99100877c029668913fc93230d626eaa
|
7
|
+
data.tar.gz: c5ae063fc7eb0f17fe6a6da9b18d79cf5f5c039262849bbb24bc33add9276294f78335a262247c86cab2a8667494de9411532f4bcd983425cdeecc3e5d51d83e
|
data/lib/terminalwire/adapter.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
require 'msgpack'
|
2
2
|
|
3
|
-
module Terminalwire
|
4
|
-
|
5
|
-
|
3
|
+
module Terminalwire::Adapter
|
4
|
+
# Works with TCP, Unix, WebSocket, and other socket-like abstractions.
|
5
|
+
class Socket
|
6
|
+
include Terminalwire::Logging
|
6
7
|
|
7
8
|
attr_reader :transport
|
8
9
|
|
@@ -29,4 +30,24 @@ module Terminalwire
|
|
29
30
|
@transport.close
|
30
31
|
end
|
31
32
|
end
|
33
|
+
|
34
|
+
# This is a test adapter that can be used for testing purposes.
|
35
|
+
class Test
|
36
|
+
attr_reader :responses
|
37
|
+
|
38
|
+
def initialize(responses = [])
|
39
|
+
@responses = responses
|
40
|
+
end
|
41
|
+
|
42
|
+
def write(**data)
|
43
|
+
@responses << data
|
44
|
+
end
|
45
|
+
|
46
|
+
def response
|
47
|
+
@responses.pop
|
48
|
+
end
|
49
|
+
|
50
|
+
def close
|
51
|
+
end
|
52
|
+
end
|
32
53
|
end
|
@@ -3,6 +3,73 @@ require "pathname"
|
|
3
3
|
module Terminalwire::Client
|
4
4
|
module Entitlement
|
5
5
|
class Paths
|
6
|
+
class Permit
|
7
|
+
attr_reader :path, :mode
|
8
|
+
# Ensure the default file mode is read/write for owner only. This ensures
|
9
|
+
# that if the server tries uploading an executable file, it won't be when it
|
10
|
+
# lands on the client.
|
11
|
+
#
|
12
|
+
# Eventually we'll move this into entitlements so the client can set maximum
|
13
|
+
# permissions for files and directories.
|
14
|
+
MODE = 0o600 # rw-------
|
15
|
+
|
16
|
+
# Constants for permission bit masks
|
17
|
+
OWNER_PERMISSIONS = 0o700 # rwx------
|
18
|
+
GROUP_PERMISSIONS = 0o070 # ---rwx---
|
19
|
+
OTHERS_PERMISSIONS = 0o007 # ------rwx
|
20
|
+
|
21
|
+
# We'll validate that modes are within this range.
|
22
|
+
MODE_RANGE = 0o000..0o777
|
23
|
+
|
24
|
+
def initialize(path:, mode: MODE)
|
25
|
+
@path = Pathname.new(path).expand_path
|
26
|
+
@mode = convert(mode)
|
27
|
+
end
|
28
|
+
|
29
|
+
def permitted_path?(path)
|
30
|
+
# This MUST be done via File.fnmatch because Pathname#fnmatch does not work. If you
|
31
|
+
# try changing this 🚨 YOU MAY CIRCUMVENT THE SECURITY MEASURES IN PLACE. 🚨
|
32
|
+
File.fnmatch @path.to_s, File.expand_path(path), File::FNM_PATHNAME
|
33
|
+
end
|
34
|
+
|
35
|
+
def permitted_mode?(value)
|
36
|
+
# Ensure the mode is at least as permissive as the permitted mode.
|
37
|
+
mode = convert(value)
|
38
|
+
|
39
|
+
# Extract permission bits for owner, group, and others
|
40
|
+
owner_bits = mode & OWNER_PERMISSIONS
|
41
|
+
group_bits = mode & GROUP_PERMISSIONS
|
42
|
+
others_bits = mode & OTHERS_PERMISSIONS
|
43
|
+
|
44
|
+
# Ensure that the mode doesn't grant more permissions than @mode in any class (owner, group, others)
|
45
|
+
(owner_bits <= @mode & OWNER_PERMISSIONS) &&
|
46
|
+
(group_bits <= @mode & GROUP_PERMISSIONS) &&
|
47
|
+
(others_bits <= @mode & OTHERS_PERMISSIONS)
|
48
|
+
end
|
49
|
+
|
50
|
+
def permitted?(path:, mode: @mode)
|
51
|
+
permitted_path?(path) && permitted_mode?(mode)
|
52
|
+
end
|
53
|
+
|
54
|
+
def serialize
|
55
|
+
{
|
56
|
+
location: @path.to_s,
|
57
|
+
mode: @mode
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
protected
|
62
|
+
def convert(value)
|
63
|
+
mode = Integer(value)
|
64
|
+
raise ArgumentError, "The mode #{format_octet value} must be an octet value between #{format_octet MODE_RANGE.first} and #{format_octet MODE_RANGE.last}" unless MODE_RANGE.cover?(mode)
|
65
|
+
mode
|
66
|
+
end
|
67
|
+
|
68
|
+
def format_octet(value)
|
69
|
+
format("0o%03o", value)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
6
73
|
include Enumerable
|
7
74
|
|
8
75
|
def initialize
|
@@ -13,23 +80,20 @@ module Terminalwire::Client
|
|
13
80
|
@permitted.each(&)
|
14
81
|
end
|
15
82
|
|
16
|
-
def permit(path)
|
17
|
-
@permitted.append
|
83
|
+
def permit(path, **)
|
84
|
+
@permitted.append Permit.new(path:, **)
|
18
85
|
end
|
19
86
|
|
20
|
-
def permitted?(path)
|
21
|
-
|
87
|
+
def permitted?(path, mode: nil)
|
88
|
+
if mode
|
89
|
+
find { |it| it.permitted_path?(path) and it.permitted_mode?(mode) }
|
90
|
+
else
|
91
|
+
find { |it| it.permitted_path?(path) }
|
92
|
+
end
|
22
93
|
end
|
23
94
|
|
24
95
|
def serialize
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
def matches?(permitted:, path:)
|
30
|
-
# This MUST be done via File.fnmatch because Pathname#fnmatch does not work. If you
|
31
|
-
# try changing this 🚨 YOU MAY CIRCUMVENT THE SECURITY MEASURES IN PLACE. 🚨
|
32
|
-
File.fnmatch permitted.to_s, File.expand_path(path), File::FNM_PATHNAME
|
96
|
+
map(&:serialize)
|
33
97
|
end
|
34
98
|
end
|
35
99
|
|
@@ -105,6 +169,10 @@ module Terminalwire::Client
|
|
105
169
|
class RootPolicy < Policy
|
106
170
|
HOST = "terminalwire.com".freeze
|
107
171
|
|
172
|
+
# Ensure the binary stubs are executable. This increases the
|
173
|
+
# file mode entitlement so that stubs created in ./bin are executable.
|
174
|
+
BINARY_PATH_FILE_MODE = 0o755
|
175
|
+
|
108
176
|
def initialize(*, **, &)
|
109
177
|
# Make damn sure the authority is set to Terminalwire.
|
110
178
|
super(*, authority: HOST, **, &)
|
@@ -112,6 +180,9 @@ module Terminalwire::Client
|
|
112
180
|
# Now setup special permitted paths.
|
113
181
|
@paths.permit root_path
|
114
182
|
@paths.permit root_pattern
|
183
|
+
|
184
|
+
# Permit terminalwire to grant execute permissions to the binary stubs.
|
185
|
+
@paths.permit binary_pattern, mode: BINARY_PATH_FILE_MODE
|
115
186
|
end
|
116
187
|
|
117
188
|
# Grant access to the `~/.terminalwire/**/*` path so users can install
|
@@ -119,6 +190,16 @@ module Terminalwire::Client
|
|
119
190
|
def root_pattern
|
120
191
|
root_path.join("**/*")
|
121
192
|
end
|
193
|
+
|
194
|
+
# Path where the terminalwire binary stubs are stored.
|
195
|
+
def binary_path
|
196
|
+
root_path.join("bin")
|
197
|
+
end
|
198
|
+
|
199
|
+
# Pattern for the binary path.
|
200
|
+
def binary_pattern
|
201
|
+
binary_path.join("*")
|
202
|
+
end
|
122
203
|
end
|
123
204
|
|
124
205
|
def self.from_url(url)
|
@@ -102,28 +102,16 @@ module Terminalwire::Client::Resource
|
|
102
102
|
class File < Base
|
103
103
|
File = ::File
|
104
104
|
|
105
|
-
# Ensure the default file mode is read/write for owner only. This ensures
|
106
|
-
# that if the server tries uploading an executable file, it won't be when it
|
107
|
-
# lands on the client.
|
108
|
-
#
|
109
|
-
# Eventually we'll move this into entitlements so the client can set maximum
|
110
|
-
# permissions for files and directories.
|
111
|
-
FILE_PERMISSIONS = 0o600 # rw-------
|
112
|
-
|
113
105
|
def read(path:)
|
114
106
|
File.read File.expand_path(path)
|
115
107
|
end
|
116
108
|
|
117
|
-
def write(path:, content:)
|
118
|
-
File.open(File.expand_path(path), "w",
|
119
|
-
end
|
120
|
-
|
121
|
-
def append(path:, content:)
|
122
|
-
File.open(File.expand_path(path), "a", FILE_PERMISSIONS) { |f| f.write(content) }
|
109
|
+
def write(path:, content:, mode: nil)
|
110
|
+
File.open(File.expand_path(path), "w", mode) { |f| f.write(content) }
|
123
111
|
end
|
124
112
|
|
125
|
-
def
|
126
|
-
|
113
|
+
def append(path:, content:, mode: nil)
|
114
|
+
File.open(File.expand_path(path), "a", mode) { |f| f.write(content) }
|
127
115
|
end
|
128
116
|
|
129
117
|
def delete(path:)
|
@@ -134,6 +122,37 @@ module Terminalwire::Client::Resource
|
|
134
122
|
File.exist? File.expand_path(path)
|
135
123
|
end
|
136
124
|
|
125
|
+
def change_mode(path:, mode:)
|
126
|
+
File.chmod(mode, File.expand_path(path))
|
127
|
+
end
|
128
|
+
|
129
|
+
protected
|
130
|
+
def permit(command, path:, mode: nil, **)
|
131
|
+
@entitlement.paths.permitted? path, mode:
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
class Directory < Base
|
136
|
+
File = ::File
|
137
|
+
|
138
|
+
def list(path:)
|
139
|
+
Dir.glob(File.expand_path(path))
|
140
|
+
end
|
141
|
+
|
142
|
+
def create(path:)
|
143
|
+
Dir.mkdir(File.expand_path(path))
|
144
|
+
rescue Errno::EEXIST
|
145
|
+
# Do nothing
|
146
|
+
end
|
147
|
+
|
148
|
+
def exist(path:)
|
149
|
+
Dir.exist? File.expand_path(path)
|
150
|
+
end
|
151
|
+
|
152
|
+
def delete(path:)
|
153
|
+
Dir.delete(File.expand_path(path))
|
154
|
+
end
|
155
|
+
|
137
156
|
def permit(command, path:, **)
|
138
157
|
@entitlement.paths.permitted? path
|
139
158
|
end
|
data/lib/terminalwire/client.rb
CHANGED
@@ -23,6 +23,7 @@ module Terminalwire
|
|
23
23
|
it << Resource::STDERR.new("stderr", @adapter, entitlement:)
|
24
24
|
it << Resource::Browser.new("browser", @adapter, entitlement:)
|
25
25
|
it << Resource::File.new("file", @adapter, entitlement:)
|
26
|
+
it << Resource::Directory.new("directory", @adapter, entitlement:)
|
26
27
|
end
|
27
28
|
end
|
28
29
|
|
@@ -53,14 +54,14 @@ module Terminalwire
|
|
53
54
|
def self.tcp(...)
|
54
55
|
socket = TCPSocket.new(...)
|
55
56
|
transport = Terminalwire::Transport::Socket.new(socket)
|
56
|
-
adapter = Terminalwire::Adapter.new(transport)
|
57
|
+
adapter = Terminalwire::Adapter::Socket.new(transport)
|
57
58
|
Terminalwire::Client::Handler.new(adapter)
|
58
59
|
end
|
59
60
|
|
60
61
|
def self.socket(...)
|
61
62
|
socket = UNIXSocket.new(...)
|
62
63
|
transport = Terminalwire::Transport::Socket.new(socket)
|
63
|
-
adapter = Terminalwire::Adapter.new(transport)
|
64
|
+
adapter = Terminalwire::Adapter::Socket.new(transport)
|
64
65
|
Terminalwire::Client::Handler.new(adapter)
|
65
66
|
end
|
66
67
|
|
@@ -84,7 +85,7 @@ module Terminalwire
|
|
84
85
|
|
85
86
|
Async::WebSocket::Client.connect(endpoint) do |adapter|
|
86
87
|
transport = Terminalwire::Transport::WebSocket.new(adapter)
|
87
|
-
adapter = Terminalwire::Adapter.new(transport)
|
88
|
+
adapter = Terminalwire::Adapter::Socket.new(transport)
|
88
89
|
entitlement ||= Entitlement.from_url(url)
|
89
90
|
Terminalwire::Client::Handler.new(adapter, arguments:, entitlement:).connect
|
90
91
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
|
3
|
+
module Terminalwire::Server
|
4
|
+
class Context
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
attr_reader :stdout, :stdin, :stderr, :browser, :file, :directory, :storage_path
|
8
|
+
|
9
|
+
def_delegators :@stdout, :puts, :print
|
10
|
+
def_delegators :@stdin, :gets, :getpass
|
11
|
+
|
12
|
+
def initialize(adapter:, entitlement:)
|
13
|
+
@adapter = adapter
|
14
|
+
|
15
|
+
@entitlement = entitlement
|
16
|
+
@storage_path = Pathname.new(entitlement.fetch(:storage_path))
|
17
|
+
|
18
|
+
@stdout = Resource::STDOUT.new("stdout", @adapter)
|
19
|
+
@stdin = Resource::STDIN.new("stdin", @adapter)
|
20
|
+
@stderr = Resource::STDERR.new("stderr", @adapter)
|
21
|
+
@browser = Resource::Browser.new("browser", @adapter)
|
22
|
+
@file = Resource::File.new("file", @adapter)
|
23
|
+
@directory = Resource::Directory.new("directory", @adapter)
|
24
|
+
|
25
|
+
if block_given?
|
26
|
+
begin
|
27
|
+
yield self
|
28
|
+
ensure
|
29
|
+
exit
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def exit(status = 0)
|
35
|
+
@adapter.write(event: "exit", status: status)
|
36
|
+
end
|
37
|
+
|
38
|
+
def close
|
39
|
+
@adapter.close
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module Terminalwire::Server
|
2
|
+
module Resource
|
3
|
+
class Base < Terminalwire::Resource::Base
|
4
|
+
private
|
5
|
+
|
6
|
+
def command(command, **parameters)
|
7
|
+
@adapter.write(
|
8
|
+
event: "resource",
|
9
|
+
name: @name,
|
10
|
+
action: "command",
|
11
|
+
command: command,
|
12
|
+
parameters: parameters
|
13
|
+
)
|
14
|
+
@adapter.recv&.fetch(:response)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class STDOUT < Base
|
19
|
+
def puts(data)
|
20
|
+
command("print_line", data: data)
|
21
|
+
end
|
22
|
+
|
23
|
+
def print(data)
|
24
|
+
command("print", data: data)
|
25
|
+
end
|
26
|
+
|
27
|
+
def flush
|
28
|
+
# Do nothing
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class STDERR < STDOUT
|
33
|
+
end
|
34
|
+
|
35
|
+
class STDIN < Base
|
36
|
+
def getpass
|
37
|
+
command("read_password")
|
38
|
+
end
|
39
|
+
|
40
|
+
def gets
|
41
|
+
command("read_line")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class File < Base
|
46
|
+
def read(path)
|
47
|
+
command("read", path: path.to_s)
|
48
|
+
end
|
49
|
+
|
50
|
+
def write(path, content)
|
51
|
+
command("write", path: path.to_s, content:)
|
52
|
+
end
|
53
|
+
|
54
|
+
def append(path, content)
|
55
|
+
command("append", path: path.to_s, content:)
|
56
|
+
end
|
57
|
+
|
58
|
+
def delete(path)
|
59
|
+
command("delete", path: path.to_s)
|
60
|
+
end
|
61
|
+
alias :rm :delete
|
62
|
+
|
63
|
+
def exist?(path)
|
64
|
+
command("exist", path: path.to_s)
|
65
|
+
end
|
66
|
+
|
67
|
+
def change_mode(path, mode)
|
68
|
+
command("change_mode", path: path.to_s, mode:)
|
69
|
+
end
|
70
|
+
alias :chmod :change_mode
|
71
|
+
end
|
72
|
+
|
73
|
+
class Directory < Base
|
74
|
+
def list(path)
|
75
|
+
command("list", path: path.to_s)
|
76
|
+
end
|
77
|
+
alias :ls :list
|
78
|
+
|
79
|
+
def create(path)
|
80
|
+
command("create", path: path.to_s)
|
81
|
+
end
|
82
|
+
alias :mkdir :create
|
83
|
+
|
84
|
+
def exist?(path)
|
85
|
+
command("exist", path: path.to_s)
|
86
|
+
end
|
87
|
+
|
88
|
+
def delete(path)
|
89
|
+
command("delete", path: path.to_s)
|
90
|
+
end
|
91
|
+
alias :rm :delete
|
92
|
+
end
|
93
|
+
|
94
|
+
class Browser < Base
|
95
|
+
def launch(url)
|
96
|
+
command("launch", url: url)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
data/lib/terminalwire/server.rb
CHANGED
@@ -2,121 +2,6 @@ require "thor"
|
|
2
2
|
|
3
3
|
module Terminalwire
|
4
4
|
module Server
|
5
|
-
module Resource
|
6
|
-
class Base < Terminalwire::Resource::Base
|
7
|
-
private
|
8
|
-
|
9
|
-
def command(command, **parameters)
|
10
|
-
@adapter.write(
|
11
|
-
event: "resource",
|
12
|
-
name: @name,
|
13
|
-
action: "command",
|
14
|
-
command: command,
|
15
|
-
parameters: parameters
|
16
|
-
)
|
17
|
-
@adapter.recv&.fetch(:response)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
class STDOUT < Base
|
22
|
-
def puts(data)
|
23
|
-
command("print_line", data: data)
|
24
|
-
end
|
25
|
-
|
26
|
-
def print(data)
|
27
|
-
command("print", data: data)
|
28
|
-
end
|
29
|
-
|
30
|
-
def flush
|
31
|
-
# Do nothing
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
class STDERR < STDOUT
|
36
|
-
end
|
37
|
-
|
38
|
-
class STDIN < Base
|
39
|
-
def getpass
|
40
|
-
command("read_password")
|
41
|
-
end
|
42
|
-
|
43
|
-
def gets
|
44
|
-
command("read_line")
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
class File < Base
|
49
|
-
def read(path)
|
50
|
-
command("read", path: path.to_s)
|
51
|
-
end
|
52
|
-
|
53
|
-
def write(path, content)
|
54
|
-
command("write", path: path.to_s, content:)
|
55
|
-
end
|
56
|
-
|
57
|
-
def append(path, content)
|
58
|
-
command("append", path: path.to_s, content:)
|
59
|
-
end
|
60
|
-
|
61
|
-
def mkdir(path)
|
62
|
-
command("mkdir", path: path.to_s)
|
63
|
-
end
|
64
|
-
|
65
|
-
def delete(path)
|
66
|
-
command("delete", path: path.to_s)
|
67
|
-
end
|
68
|
-
|
69
|
-
def exist?(path)
|
70
|
-
command("exist", path: path.to_s)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
class Browser < Base
|
75
|
-
def launch(url)
|
76
|
-
command("launch", url: url)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
class Context
|
82
|
-
extend Forwardable
|
83
|
-
|
84
|
-
attr_reader :stdout, :stdin, :stderr, :browser, :file, :storage_path
|
85
|
-
|
86
|
-
def_delegators :@stdout, :puts, :print
|
87
|
-
def_delegators :@stdin, :gets, :getpass
|
88
|
-
|
89
|
-
def initialize(adapter:, entitlement:)
|
90
|
-
@adapter = adapter
|
91
|
-
|
92
|
-
# TODO: Encapsulate entitlement in a class instead of a hash.
|
93
|
-
@entitlement = entitlement
|
94
|
-
@storage_path = Pathname.new(entitlement.fetch(:storage_path))
|
95
|
-
|
96
|
-
@stdout = Server::Resource::STDOUT.new("stdout", @adapter)
|
97
|
-
@stdin = Server::Resource::STDIN.new("stdin", @adapter)
|
98
|
-
@stderr = Server::Resource::STDERR.new("stderr", @adapter)
|
99
|
-
@browser = Server::Resource::Browser.new("browser", @adapter)
|
100
|
-
@file = Server::Resource::File.new("file", @adapter)
|
101
|
-
|
102
|
-
if block_given?
|
103
|
-
begin
|
104
|
-
yield self
|
105
|
-
ensure
|
106
|
-
exit
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
def exit(status = 0)
|
112
|
-
@adapter.write(event: "exit", status: status)
|
113
|
-
end
|
114
|
-
|
115
|
-
def close
|
116
|
-
@adapter.close
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
5
|
class MyCLI < ::Thor
|
121
6
|
include Terminalwire::Thor
|
122
7
|
|
@@ -161,7 +46,7 @@ module Terminalwire
|
|
161
46
|
|
162
47
|
def call(env)
|
163
48
|
Async::WebSocket::Adapters::Rack.open(env, protocols: ['ws']) do |connection|
|
164
|
-
run(Adapter.new(Terminalwire::Transport::WebSocket.new(connection)))
|
49
|
+
run(Adapter::Socket.new(Terminalwire::Transport::WebSocket.new(connection)))
|
165
50
|
end or [200, { "Content-Type" => "text/plain" }, ["Connect via WebSockets"]]
|
166
51
|
end
|
167
52
|
|
data/lib/terminalwire/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: terminalwire
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brad Gessler
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-09-
|
11
|
+
date: 2024-09-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: async-websocket
|
@@ -167,6 +167,8 @@ files:
|
|
167
167
|
- lib/terminalwire/logging.rb
|
168
168
|
- lib/terminalwire/rails.rb
|
169
169
|
- lib/terminalwire/server.rb
|
170
|
+
- lib/terminalwire/server/context.rb
|
171
|
+
- lib/terminalwire/server/resource.rb
|
170
172
|
- lib/terminalwire/thor.rb
|
171
173
|
- lib/terminalwire/transport.rb
|
172
174
|
- lib/terminalwire/version.rb
|