terminalwire-rails 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 +7 -0
- data/lib/generators/terminalwire/install/USAGE +9 -0
- data/lib/generators/terminalwire/install/install_generator.rb +43 -0
- data/lib/generators/terminalwire/install/templates/application_terminal.rb.tt +21 -0
- data/lib/generators/terminalwire/install/templates/bin/terminalwire +2 -0
- data/lib/generators/terminalwire/install/templates/main_terminal.rb +40 -0
- data/lib/terminalwire/rails.rb +116 -0
- data/lib/terminalwire-rails.rb +3 -0
- metadata +97 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6ba7bd27bf86aee365f4f45139d8a125e08fa01295d872a059570de818b834f9
|
4
|
+
data.tar.gz: 9f71189cbd898c0c4b5033e1dcaadec72126e96f35e5860fa58e6711189a7982
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 49fe21592da92e7587a2c2bd93f920d1bde2b2e4d40af8076a4d43a9405497c58e7fe343d50f4a6e831a7ea1c6f0106466904127ad2a575492c13cf7d4edcedc
|
7
|
+
data.tar.gz: 0fe43f8b5f6658131efe122161d5700bccdf8e4d958da4ba7c9cd6d72c2e9dc62cc490b2141b2cd8d26ad3068bd4683bf14274e493fb2230d2d034e0222de96d
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require "bundler"
|
2
|
+
|
3
|
+
class Terminalwire::InstallGenerator < Rails::Generators::Base
|
4
|
+
source_root File.expand_path("templates", __dir__)
|
5
|
+
|
6
|
+
argument :binary_name, type: :string, required: true, banner: "binary_name"
|
7
|
+
|
8
|
+
def create_terminal_files
|
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")
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_binary_files
|
14
|
+
copy_file "bin/terminalwire", binary_path
|
15
|
+
chmod binary_path, 0755, verbose: false
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_route
|
19
|
+
route <<~ROUTE
|
20
|
+
match "/terminal",
|
21
|
+
to: Terminalwire::Rails::Thor.new(MainTerminal),
|
22
|
+
via: [:get, :connect]
|
23
|
+
ROUTE
|
24
|
+
end
|
25
|
+
|
26
|
+
def bundle_development_dependencies
|
27
|
+
# Add the terminalwire gem to the development group in the Gemfile.
|
28
|
+
gem "terminalwire", group: :development
|
29
|
+
end
|
30
|
+
|
31
|
+
def print_post_install_message
|
32
|
+
say ""
|
33
|
+
say "Terminalwire has been successfully installed!", :green
|
34
|
+
say "Run `#{binary_path.relative_path_from(Rails.root)}` to verify everything is in working order. For support visit https://terminalwire.com."
|
35
|
+
say ""
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def binary_path
|
41
|
+
Rails.root.join("bin", binary_name)
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Learn how to use Thor at http://whatisthor.com.
|
2
|
+
class ApplicationTerminal < Thor
|
3
|
+
# Enables IO Streaming.
|
4
|
+
include Terminalwire::Thor
|
5
|
+
|
6
|
+
# The name of your binary. Thor uses this for its help output.
|
7
|
+
def self.basename = "<%= binary_name %>"
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def current_user=(user)
|
12
|
+
# The Session object is a hash-like object that encrypts and signs a hash that's
|
13
|
+
# stored on the client's file sytem. Conceptually, it's similar to Rails signed
|
14
|
+
# and encrypted client-side cookies.
|
15
|
+
session["user_id"] = user.id
|
16
|
+
end
|
17
|
+
|
18
|
+
def current_user
|
19
|
+
@current_user ||= User.find(session["user_id"])
|
20
|
+
end
|
21
|
+
end
|
@@ -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
|
+
fail "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
|
+
fail "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
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require "terminalwire-server"
|
2
|
+
require "thor"
|
3
|
+
require "rails"
|
4
|
+
require "jwt"
|
5
|
+
|
6
|
+
module Terminalwire
|
7
|
+
module Rails
|
8
|
+
class Session
|
9
|
+
# JWT file name for the session file.
|
10
|
+
FILENAME = "session.jwt"
|
11
|
+
|
12
|
+
# Empty dictionary the user can stash all their session data into.
|
13
|
+
EMPTY_SESSION = {}.freeze
|
14
|
+
|
15
|
+
extend Forwardable
|
16
|
+
|
17
|
+
# Delegate `dig` and `fetch` to the `read` method
|
18
|
+
def_delegators :read,
|
19
|
+
:dig, :fetch, :[]
|
20
|
+
|
21
|
+
def initialize(context:, path: nil, secret_key: self.class.secret_key)
|
22
|
+
@context = context
|
23
|
+
@path = Pathname.new(path || context.storage_path)
|
24
|
+
@config_file_path = @path.join(FILENAME)
|
25
|
+
@secret_key = secret_key
|
26
|
+
|
27
|
+
ensure_file
|
28
|
+
end
|
29
|
+
|
30
|
+
def read
|
31
|
+
jwt_token = @context.file.read(@config_file_path)
|
32
|
+
decoded_data = JWT.decode(jwt_token, @secret_key, true, algorithm: 'HS256')
|
33
|
+
decoded_data[0] # JWT payload is the first element in the array
|
34
|
+
rescue JWT::DecodeError => e
|
35
|
+
raise "Invalid or tampered file: #{e.message}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def reset
|
39
|
+
@context.file.delete @config_file_path
|
40
|
+
end
|
41
|
+
|
42
|
+
def edit
|
43
|
+
config = read
|
44
|
+
yield config
|
45
|
+
write(config)
|
46
|
+
end
|
47
|
+
|
48
|
+
def []=(key, value)
|
49
|
+
edit { |config| config[key] = value }
|
50
|
+
end
|
51
|
+
|
52
|
+
def write(config)
|
53
|
+
token = JWT.encode(config, @secret_key, 'HS256')
|
54
|
+
@context.file.write(@config_file_path, token)
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def ensure_file
|
60
|
+
return true if @context.file.exist? @config_file_path
|
61
|
+
# Create the path if it doesn't exist on the client.
|
62
|
+
@context.directory.create @path
|
63
|
+
# Write an empty configuration on initialization
|
64
|
+
write(EMPTY_SESSION)
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.secret_key
|
68
|
+
::Rails.application.secret_key_base
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class Thor < Server::WebSocket
|
73
|
+
include Logging
|
74
|
+
|
75
|
+
def initialize(cli_class)
|
76
|
+
@cli_class = cli_class
|
77
|
+
|
78
|
+
unless @cli_class.included_modules.include?(Terminalwire::Server::Thor)
|
79
|
+
raise 'Add `include Terminalwire::Server::Thor` to the #{@cli_class.inspect} class.'
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def error_message
|
84
|
+
"An error occurred. Please try again."
|
85
|
+
end
|
86
|
+
|
87
|
+
def handle(adapter)
|
88
|
+
logger.info "ThorServer: Running #{@cli_class.inspect}"
|
89
|
+
while message = adapter.read
|
90
|
+
case message
|
91
|
+
in { event: "initialization", protocol:, program: { arguments: }, entitlement: }
|
92
|
+
context = Terminalwire::Server::Context.new(adapter:, entitlement:)
|
93
|
+
|
94
|
+
begin
|
95
|
+
@cli_class.start(arguments, context:)
|
96
|
+
context.exit
|
97
|
+
rescue StandardError => e
|
98
|
+
if ::Rails.application.config.consider_all_requests_local
|
99
|
+
# Show the full error message with stack trace in development
|
100
|
+
context.stderr.puts "#{e.inspect}\n#{e.backtrace.join("\n")}"
|
101
|
+
else
|
102
|
+
# Show a generic message in production
|
103
|
+
context.stderr.puts error_message
|
104
|
+
end
|
105
|
+
context.exit 1
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Alias so we can put off breaking `include Terminalwire::Thor`
|
114
|
+
# in the ApplicationTerminal class.
|
115
|
+
Thor = Terminalwire::Server::Thor
|
116
|
+
end
|
metadata
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: terminalwire-rails
|
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: terminalwire-server
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.3.0.alpha1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.3.0.alpha1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rails
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '7.2'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '7.2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: jwt
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.0'
|
55
|
+
description: Stream command-line apps from your server without a web API
|
56
|
+
email:
|
57
|
+
- brad@terminalwire.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- lib/generators/terminalwire/install/USAGE
|
63
|
+
- lib/generators/terminalwire/install/install_generator.rb
|
64
|
+
- lib/generators/terminalwire/install/templates/application_terminal.rb.tt
|
65
|
+
- lib/generators/terminalwire/install/templates/bin/terminalwire
|
66
|
+
- lib/generators/terminalwire/install/templates/main_terminal.rb
|
67
|
+
- lib/terminalwire-rails.rb
|
68
|
+
- lib/terminalwire/rails.rb
|
69
|
+
homepage: https://terminalwire.com/ruby
|
70
|
+
licenses:
|
71
|
+
- Proprietary (https://terminalwire.com/license)
|
72
|
+
metadata:
|
73
|
+
allowed_push_host: https://rubygems.org/
|
74
|
+
homepage_uri: https://terminalwire.com/ruby
|
75
|
+
source_code_uri: https://github.com/terminalwire/ruby/tree/main/terminalwire-rails
|
76
|
+
changelog_uri: https://github.com/terminalwire/ruby/tags
|
77
|
+
funding_uri: https://terminalwire.com/funding
|
78
|
+
post_install_message:
|
79
|
+
rdoc_options: []
|
80
|
+
require_paths:
|
81
|
+
- lib
|
82
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: 3.0.0
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
requirements: []
|
93
|
+
rubygems_version: 3.5.9
|
94
|
+
signing_key:
|
95
|
+
specification_version: 4
|
96
|
+
summary: Ship a CLI for your web app. No API required.
|
97
|
+
test_files: []
|