terminalwire 0.1.11 → 0.1.13
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/LICENSE.txt +9 -1
- data/lib/generators/terminalwire/install/install_generator.rb +2 -1
- data/lib/generators/terminalwire/install/templates/application_terminal.rb.tt +2 -35
- data/lib/generators/terminalwire/install/templates/main_terminal.rb +40 -0
- data/lib/terminalwire/client.rb +9 -21
- data/lib/terminalwire/licensing.rb +183 -0
- data/lib/terminalwire/logging.rb +1 -1
- data/lib/terminalwire/server.rb +3 -77
- data/lib/terminalwire/transport.rb +0 -65
- data/lib/terminalwire/version.rb +1 -1
- data/lib/terminalwire.rb +0 -5
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1b3e02592c8154c835d32f4dc149d47212665f5dd2974d2634746207ced582b3
|
4
|
+
data.tar.gz: 0a4b15090653b5b54a10a215db6a39ee5465cac9a10c4e1cd29ba7fc0622822a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d74b1186e46a73eb62de35f0624f20a4f3f90aa8bf24137b772423a87a09bea920886824d7175c5b08bd18c963b3823c4cccbff0e7abd44120bfe186edda84e6
|
7
|
+
data.tar.gz: 9997f63145801d3ca47476ead70f49ac001f77765cb777063b44b62d96e1b3dfdf266f42897fae01eb0a9a224e8fddeb5e878533e773f11aaafe2e81512a48f4
|
data/LICENSE.txt
CHANGED
@@ -1 +1,9 @@
|
|
1
|
-
Copyright (c) 2024 Brad Gessler.
|
1
|
+
Copyright (c) 2024 Brad Gessler.
|
2
|
+
|
3
|
+
License is propietary. Here's the deal:
|
4
|
+
|
5
|
+
* You need to pay for Terminalwire if your organization has more than $1m in assets or makes more than $100k/year in revenue.
|
6
|
+
* Terminalwire is free for personal use, hobbyists, or businesses that are just starting out, but server licenses still need to be registered at https://terminalwire.com/developers/licenses.
|
7
|
+
* You can only use the Terminalwire client with licensed Terminalwire servers.
|
8
|
+
|
9
|
+
This list is not exhaustive, please read the full license text at https://terminalwire.com/license.
|
@@ -7,6 +7,7 @@ class Terminalwire::InstallGenerator < Rails::Generators::Base
|
|
7
7
|
|
8
8
|
def create_terminal_files
|
9
9
|
template "application_terminal.rb.tt", Rails.root.join("app/terminal/application_terminal.rb")
|
10
|
+
template "main_terminal.rb", Rails.root.join("app/terminal/main_terminal.rb")
|
10
11
|
end
|
11
12
|
|
12
13
|
def create_binary_files
|
@@ -17,7 +18,7 @@ class Terminalwire::InstallGenerator < Rails::Generators::Base
|
|
17
18
|
def add_route
|
18
19
|
route <<~ROUTE
|
19
20
|
match "/terminal",
|
20
|
-
to: Terminalwire::Server::Thor.new(
|
21
|
+
to: Terminalwire::Server::Thor.new(MainTerminal),
|
21
22
|
via: [:get, :connect]
|
22
23
|
ROUTE
|
23
24
|
end
|
@@ -1,44 +1,11 @@
|
|
1
1
|
# Learn how to use Thor at http://whatisthor.com.
|
2
2
|
class ApplicationTerminal < Thor
|
3
|
+
# Enables IO Streaming.
|
3
4
|
include Terminalwire::Thor
|
4
5
|
|
6
|
+
# The name of your binary. Thor uses this for its help output.
|
5
7
|
def self.basename = "<%= binary_name %>"
|
6
8
|
|
7
|
-
desc "hello NAME", "say hello to NAME"
|
8
|
-
def hello(name)
|
9
|
-
puts "Hello #{name}"
|
10
|
-
end
|
11
|
-
|
12
|
-
desc "login", "Login to your account"
|
13
|
-
def login
|
14
|
-
print "Email: "
|
15
|
-
email = gets.chomp
|
16
|
-
|
17
|
-
print "Password: "
|
18
|
-
password = getpass
|
19
|
-
|
20
|
-
if self.current_user = User.authenticate(email, password)
|
21
|
-
puts "Successfully logged in as #{current_user.email}."
|
22
|
-
else
|
23
|
-
puts "Could not find a user with that email and password."
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
desc "whoami", "Displays current user information."
|
28
|
-
def whoami
|
29
|
-
if self.current_user
|
30
|
-
puts "Logged in as #{current_user.email}."
|
31
|
-
else
|
32
|
-
puts "Not logged in. Run `#{self.class.basename} login` to login."
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
desc "logout", "Logout of your account"
|
37
|
-
def logout
|
38
|
-
session.reset
|
39
|
-
puts "Successfully logged out."
|
40
|
-
end
|
41
|
-
|
42
9
|
private
|
43
10
|
|
44
11
|
def current_user=(user)
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class MainTerminal < ApplicationTerminal
|
2
|
+
desc "hello NAME", "say hello to NAME"
|
3
|
+
def hello(name)
|
4
|
+
puts "Hello #{name}"
|
5
|
+
end
|
6
|
+
|
7
|
+
desc "login", "Login to your account"
|
8
|
+
def login
|
9
|
+
print "Email: "
|
10
|
+
email = gets.chomp
|
11
|
+
|
12
|
+
print "Password: "
|
13
|
+
password = getpass
|
14
|
+
|
15
|
+
# Replace this with your own authentication logic; this is an example
|
16
|
+
# of how you might do this with Devise.
|
17
|
+
user = User.find_for_authentication(email: email)
|
18
|
+
if user && user.valid_password?(password)
|
19
|
+
self.current_user = user
|
20
|
+
puts "Successfully logged in as #{current_user.email}."
|
21
|
+
else
|
22
|
+
puts "Could not find a user with that email and password."
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "whoami", "Displays current user information."
|
27
|
+
def whoami
|
28
|
+
if self.current_user
|
29
|
+
puts "Logged in as #{current_user.email}."
|
30
|
+
else
|
31
|
+
puts "Not logged in. Run `#{self.class.basename} login` to login."
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "logout", "Logout of your account"
|
36
|
+
def logout
|
37
|
+
session.reset
|
38
|
+
puts "Successfully logged out."
|
39
|
+
end
|
40
|
+
end
|
data/lib/terminalwire/client.rb
CHANGED
@@ -28,13 +28,15 @@ module Terminalwire
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def connect
|
31
|
-
@adapter.write(
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
31
|
+
@adapter.write(
|
32
|
+
event: "initialization",
|
33
|
+
protocol: { version: VERSION },
|
34
|
+
entitlement: @entitlement.serialize,
|
35
|
+
program: {
|
36
|
+
name: @program_name,
|
37
|
+
arguments: @program_arguments
|
38
|
+
}
|
39
|
+
)
|
38
40
|
|
39
41
|
loop do
|
40
42
|
handle @adapter.read
|
@@ -51,20 +53,6 @@ module Terminalwire
|
|
51
53
|
end
|
52
54
|
end
|
53
55
|
|
54
|
-
def self.tcp(...)
|
55
|
-
socket = TCPSocket.new(...)
|
56
|
-
transport = Terminalwire::Transport::Socket.new(socket)
|
57
|
-
adapter = Terminalwire::Adapter::Socket.new(transport)
|
58
|
-
Terminalwire::Client::Handler.new(adapter)
|
59
|
-
end
|
60
|
-
|
61
|
-
def self.socket(...)
|
62
|
-
socket = UNIXSocket.new(...)
|
63
|
-
transport = Terminalwire::Transport::Socket.new(socket)
|
64
|
-
adapter = Terminalwire::Adapter::Socket.new(transport)
|
65
|
-
Terminalwire::Client::Handler.new(adapter)
|
66
|
-
end
|
67
|
-
|
68
56
|
# Extracted from HTTP. This is so we can
|
69
57
|
def self.authority(url)
|
70
58
|
if url.port == url.default_port
|
@@ -0,0 +1,183 @@
|
|
1
|
+
require "msgpack"
|
2
|
+
require "openssl"
|
3
|
+
require "base64"
|
4
|
+
require "uri"
|
5
|
+
|
6
|
+
module Terminalwire::Licensing
|
7
|
+
PRIVATE_KEY_LENGTH = 2048
|
8
|
+
|
9
|
+
def self.generate_private_key
|
10
|
+
OpenSSL::PKey::RSA.new(PRIVATE_KEY_LENGTH)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.generate_private_pem
|
14
|
+
generate_private_key.to_pem
|
15
|
+
end
|
16
|
+
|
17
|
+
# Handles encoding data into a license key with prefixes that can be packed and unpacked.
|
18
|
+
module Key
|
19
|
+
# Mix into classes that need to generate or read keys
|
20
|
+
module Serialization
|
21
|
+
# This is called when the module is included in a class
|
22
|
+
def self.included(base)
|
23
|
+
# Extend the class with the class methods when the module is included
|
24
|
+
base.extend(ClassMethods)
|
25
|
+
end
|
26
|
+
|
27
|
+
def serialize(...)
|
28
|
+
self.class.serialize(...)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Define the class methods that will be available on the including class
|
32
|
+
module ClassMethods
|
33
|
+
def serializer
|
34
|
+
Key::Serializer.new(prefix: self::PREFIX)
|
35
|
+
end
|
36
|
+
|
37
|
+
def serialize(...)
|
38
|
+
serializer.serialize(...)
|
39
|
+
end
|
40
|
+
|
41
|
+
def deserialize(...)
|
42
|
+
serializer.deserialize(...)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class Serializer
|
48
|
+
attr_reader :prefix
|
49
|
+
|
50
|
+
def initialize(prefix:)
|
51
|
+
@prefix = prefix
|
52
|
+
end
|
53
|
+
|
54
|
+
def serialize(data)
|
55
|
+
prepend_prefix Base64.urlsafe_encode64 MessagePack.pack data
|
56
|
+
end
|
57
|
+
|
58
|
+
def deserialize(data)
|
59
|
+
MessagePack.unpack Base64.urlsafe_decode64 unshift_prefix data
|
60
|
+
end
|
61
|
+
|
62
|
+
protected
|
63
|
+
|
64
|
+
def prepend_prefix(key)
|
65
|
+
[prefix, key].join
|
66
|
+
end
|
67
|
+
|
68
|
+
def unshift_prefix(key)
|
69
|
+
head, prefix, tail = key.partition(@prefix)
|
70
|
+
# Check if partition successfully split the string with the correct prefix
|
71
|
+
raise RuntimeError, "Expected prefix #{@prefix.inspect} on #{key.inspect}" if prefix.empty?
|
72
|
+
tail
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# This code all runs on Terminalwire servers.
|
78
|
+
module Issuer
|
79
|
+
# Generates license keys that developers use to activate their software.
|
80
|
+
class ServerKeyGenerator
|
81
|
+
include Key::Serialization
|
82
|
+
|
83
|
+
PREFIX = "server_key_".freeze
|
84
|
+
|
85
|
+
VERSION = "1.0".freeze
|
86
|
+
|
87
|
+
def initialize(public_key:, license_url:)
|
88
|
+
@public_key = public_key
|
89
|
+
@license_url = URI(license_url)
|
90
|
+
@generated_at = Time.now.utc
|
91
|
+
end
|
92
|
+
|
93
|
+
def to_h
|
94
|
+
{
|
95
|
+
version: VERSION,
|
96
|
+
generated_at: @generated_at.iso8601,
|
97
|
+
public_key: @public_key.to_pem,
|
98
|
+
license_url: @license_url.to_s
|
99
|
+
}
|
100
|
+
end
|
101
|
+
|
102
|
+
def server_key
|
103
|
+
serialize to_h
|
104
|
+
end
|
105
|
+
alias :to_s :server_key
|
106
|
+
end
|
107
|
+
|
108
|
+
class ClientKeyVerifier
|
109
|
+
# Time variance the server will tolerate from the client.
|
110
|
+
DRIFT_SECONDS = 600 # 600 seconds, or 10 minutes.
|
111
|
+
|
112
|
+
# This means the server will tolerate a 10 minute drift in the generated_at time.
|
113
|
+
def self.drift
|
114
|
+
now = Time.now.utc
|
115
|
+
(now - DRIFT_SECONDS)...(now + DRIFT_SECONDS)
|
116
|
+
end
|
117
|
+
|
118
|
+
def initialize(client_key:, private_key:, drift: self.class.drift)
|
119
|
+
@data = Server::ClientKeyGenerator.deserialize client_key
|
120
|
+
@private_key = private_key
|
121
|
+
@drift = drift
|
122
|
+
end
|
123
|
+
|
124
|
+
def server_attestation
|
125
|
+
@server_attestation ||= decrypt @data.fetch("server_attestation")
|
126
|
+
end
|
127
|
+
|
128
|
+
def decrypt(data)
|
129
|
+
MessagePack.unpack @private_key.private_decrypt Base64.urlsafe_decode64 data
|
130
|
+
end
|
131
|
+
|
132
|
+
def generated_at
|
133
|
+
@generated_at ||= Time.parse(server_attestation.fetch("generated_at"))
|
134
|
+
end
|
135
|
+
|
136
|
+
def valid?
|
137
|
+
@drift.include? generated_at
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# Those code runs on customer servers
|
143
|
+
module Server
|
144
|
+
class ClientKeyGenerator
|
145
|
+
VERSION = "1.0".freeze
|
146
|
+
|
147
|
+
include Key::Serialization
|
148
|
+
PREFIX = "client_key_".freeze
|
149
|
+
|
150
|
+
def initialize(server_key:)
|
151
|
+
@data = Issuer::ServerKeyGenerator.deserialize server_key
|
152
|
+
@generated_at = Time.now.utc
|
153
|
+
@license_url = URI(@data.fetch("license_url"))
|
154
|
+
end
|
155
|
+
|
156
|
+
def to_h
|
157
|
+
{
|
158
|
+
version: VERSION,
|
159
|
+
license_url: @license_url.to_s,
|
160
|
+
server_attestation: attest(
|
161
|
+
version: VERSION,
|
162
|
+
generated_at: @generated_at.iso8601,
|
163
|
+
)
|
164
|
+
}
|
165
|
+
end
|
166
|
+
|
167
|
+
def client_key
|
168
|
+
serialize to_h
|
169
|
+
end
|
170
|
+
alias :to_s :client_key
|
171
|
+
|
172
|
+
protected
|
173
|
+
|
174
|
+
def attest(data)
|
175
|
+
Base64.urlsafe_encode64 public_key.public_encrypt MessagePack.pack data
|
176
|
+
end
|
177
|
+
|
178
|
+
def public_key
|
179
|
+
@public_key ||= OpenSSL::PKey::RSA.new(@data.fetch("public_key"))
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
data/lib/terminalwire/logging.rb
CHANGED
data/lib/terminalwire/server.rb
CHANGED
@@ -2,57 +2,16 @@ require "thor"
|
|
2
2
|
|
3
3
|
module Terminalwire
|
4
4
|
module Server
|
5
|
-
class MyCLI < ::Thor
|
6
|
-
include Terminalwire::Thor
|
7
|
-
|
8
|
-
desc "greet NAME", "Greet a person"
|
9
|
-
def greet(name)
|
10
|
-
name = ask "What's your name?"
|
11
|
-
say "Hello, #{name}!"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
class Socket
|
16
|
-
include Logging
|
17
|
-
|
18
|
-
def initialize(server_socket)
|
19
|
-
@server_socket = server_socket
|
20
|
-
end
|
21
|
-
|
22
|
-
def listen
|
23
|
-
logger.info "Socket: Listening..."
|
24
|
-
loop do
|
25
|
-
client_socket = @server_socket.accept
|
26
|
-
logger.debug "Socket: Client #{client_socket.inspect} connected"
|
27
|
-
handle_client(client_socket)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
|
33
|
-
def handle_client(socket)
|
34
|
-
transport = Transport::Socket.new(socket)
|
35
|
-
adapter = Adapter.new(transport)
|
36
|
-
|
37
|
-
Thread.new do
|
38
|
-
handler = Handler.new(adapter)
|
39
|
-
handler.run
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
5
|
class WebSocket
|
45
6
|
include Logging
|
46
7
|
|
47
8
|
def call(env)
|
48
9
|
Async::WebSocket::Adapters::Rack.open(env, protocols: ['ws']) do |connection|
|
49
|
-
|
10
|
+
handle(Adapter::Socket.new(Terminalwire::Transport::WebSocket.new(connection)))
|
50
11
|
end or [200, { "Content-Type" => "text/plain" }, ["Connect via WebSockets"]]
|
51
12
|
end
|
52
13
|
|
53
|
-
|
54
|
-
|
55
|
-
def run(adapter)
|
14
|
+
def handle(adapter)
|
56
15
|
while message = adapter.read
|
57
16
|
puts message
|
58
17
|
end
|
@@ -76,7 +35,7 @@ module Terminalwire
|
|
76
35
|
"An error occurred. Please try again."
|
77
36
|
end
|
78
37
|
|
79
|
-
def
|
38
|
+
def handle(adapter)
|
80
39
|
logger.info "ThorServer: Running #{@cli_class.inspect}"
|
81
40
|
while message = adapter.read
|
82
41
|
case message
|
@@ -100,38 +59,5 @@ module Terminalwire
|
|
100
59
|
end
|
101
60
|
end
|
102
61
|
end
|
103
|
-
|
104
|
-
class Handler
|
105
|
-
include Logging
|
106
|
-
|
107
|
-
def initialize(adapter)
|
108
|
-
@adapter = adapter
|
109
|
-
end
|
110
|
-
|
111
|
-
def run
|
112
|
-
logger.info "Server Handler: Running"
|
113
|
-
loop do
|
114
|
-
message = @adapter.read
|
115
|
-
case message
|
116
|
-
in { event: "initialization", protocol:, program: { arguments: }, entitlement: }
|
117
|
-
Context.new(adapter: @adapter) do |context|
|
118
|
-
MyCLI.start(arguments, context:)
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
rescue EOFError, Errno::ECONNRESET
|
123
|
-
logger.info "Server Handler: Client disconnected"
|
124
|
-
ensure
|
125
|
-
@adapter.close
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
def self.tcp(...)
|
130
|
-
Server::Socket.new(TCPServer.new(...))
|
131
|
-
end
|
132
|
-
|
133
|
-
def self.socket(...)
|
134
|
-
Server::Socket.new(UNIXServer.new(...))
|
135
|
-
end
|
136
62
|
end
|
137
63
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'uri'
|
2
|
-
require 'socket'
|
3
2
|
require 'async/websocket/client'
|
4
3
|
|
5
4
|
module Terminalwire
|
@@ -26,70 +25,6 @@ module Terminalwire
|
|
26
25
|
end
|
27
26
|
end
|
28
27
|
|
29
|
-
class TCP < Base
|
30
|
-
def self.connect(url)
|
31
|
-
uri = URI(url)
|
32
|
-
new(TCPSocket.new(uri.host, uri.port))
|
33
|
-
end
|
34
|
-
|
35
|
-
def self.listen(url)
|
36
|
-
uri = URI(url)
|
37
|
-
new(TCPServer.new(uri.host, uri.port))
|
38
|
-
end
|
39
|
-
|
40
|
-
def initialize(socket)
|
41
|
-
@socket = socket
|
42
|
-
end
|
43
|
-
|
44
|
-
def read
|
45
|
-
length = @socket.read(4)
|
46
|
-
return nil if length.nil?
|
47
|
-
length = length.unpack('L>')[0]
|
48
|
-
@socket.read(length)
|
49
|
-
end
|
50
|
-
|
51
|
-
def write(data)
|
52
|
-
length = [data.bytesize].pack('L>')
|
53
|
-
@socket.write(length + data)
|
54
|
-
end
|
55
|
-
|
56
|
-
def close
|
57
|
-
@socket.close
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
class Unix < Base
|
62
|
-
def self.connect(url)
|
63
|
-
uri = URI(url)
|
64
|
-
new(UNIXSocket.new(uri.path))
|
65
|
-
end
|
66
|
-
|
67
|
-
def self.listen(url)
|
68
|
-
uri = URI(url)
|
69
|
-
new(UNIXServer.new(uri.path))
|
70
|
-
end
|
71
|
-
|
72
|
-
def initialize(socket)
|
73
|
-
@socket = socket
|
74
|
-
end
|
75
|
-
|
76
|
-
def read
|
77
|
-
length = @socket.read(4)
|
78
|
-
return nil if length.nil?
|
79
|
-
length = length.unpack('L>')[0]
|
80
|
-
@socket.read(length)
|
81
|
-
end
|
82
|
-
|
83
|
-
def write(data)
|
84
|
-
length = [data.bytesize].pack('L>')
|
85
|
-
@socket.write(length + data)
|
86
|
-
end
|
87
|
-
|
88
|
-
def close
|
89
|
-
@socket.close
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
28
|
class WebSocket < Base
|
94
29
|
def self.connect(url)
|
95
30
|
uri = URI(url)
|
data/lib/terminalwire/version.rb
CHANGED
data/lib/terminalwire.rb
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
require_relative "terminalwire/version"
|
4
4
|
|
5
|
-
require 'socket'
|
6
5
|
require 'forwardable'
|
7
6
|
require 'uri'
|
8
7
|
require 'zeitwerk'
|
@@ -40,10 +39,6 @@ module Terminalwire
|
|
40
39
|
respond(status: "success", response:, **data)
|
41
40
|
end
|
42
41
|
|
43
|
-
def self.protocol_key
|
44
|
-
name.split("::").last.downcase
|
45
|
-
end
|
46
|
-
|
47
42
|
private
|
48
43
|
|
49
44
|
def respond(**response)
|
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.13
|
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-10-
|
11
|
+
date: 2024-10-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: async-websocket
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0.
|
19
|
+
version: '0.30'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0.
|
26
|
+
version: '0.30'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: zeitwerk
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -158,12 +158,14 @@ files:
|
|
158
158
|
- lib/generators/terminalwire/install/install_generator.rb
|
159
159
|
- lib/generators/terminalwire/install/templates/application_terminal.rb.tt
|
160
160
|
- lib/generators/terminalwire/install/templates/bin/terminalwire
|
161
|
+
- lib/generators/terminalwire/install/templates/main_terminal.rb
|
161
162
|
- lib/terminalwire.rb
|
162
163
|
- lib/terminalwire/adapter.rb
|
163
164
|
- lib/terminalwire/client.rb
|
164
165
|
- lib/terminalwire/client/entitlement.rb
|
165
166
|
- lib/terminalwire/client/exec.rb
|
166
167
|
- lib/terminalwire/client/resource.rb
|
168
|
+
- lib/terminalwire/licensing.rb
|
167
169
|
- lib/terminalwire/logging.rb
|
168
170
|
- lib/terminalwire/rails.rb
|
169
171
|
- lib/terminalwire/server.rb
|
@@ -175,7 +177,7 @@ files:
|
|
175
177
|
- sig/terminalwire.rbs
|
176
178
|
homepage: https://terminalwire.com/ruby
|
177
179
|
licenses:
|
178
|
-
- Proprietary
|
180
|
+
- Proprietary (https://terminalwire.com/license)
|
179
181
|
metadata:
|
180
182
|
allowed_push_host: https://rubygems.org/
|
181
183
|
homepage_uri: https://terminalwire.com/ruby
|