better_auth-cli 0.10.0
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/CHANGELOG.md +9 -0
- data/README.md +19 -0
- data/exe/better-auth +6 -0
- data/lib/better_auth/cli/version.rb +7 -0
- data/lib/better_auth/cli.rb +240 -0
- metadata +104 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 6f43bdbfe1ccede48e41d7ea7ff77f974ad177daec7f1b3e41925009a638d23d
|
|
4
|
+
data.tar.gz: aadb7a3c1aee35097385d9e9a27c437312d3c38673bd8c70ff74b4e2292459ec
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: ee5873d758ffdb11eabf209cc80de5052929035775493fb9e46bf981260ba360877aa52b763ed39ff9c0266b80cecdec42517078fa8d0d30f5d63fc57a03c9d0
|
|
7
|
+
data.tar.gz: b2b28e050690c78559ac01ae3235b02a7509d018c6583dc87fc899a44b54af0a8d4234e1e31b283c23803b1a8abb384adf8e8e2c4dea29e72bc0e2f5651de1db
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.10.0
|
|
4
|
+
|
|
5
|
+
- Improved CLI error handling and expanded command coverage.
|
|
6
|
+
|
|
7
|
+
## 0.9.0
|
|
8
|
+
|
|
9
|
+
- Initial Better Auth CLI package with `better-auth generate`, `better-auth migrate`, `better-auth migrate status`, `better-auth doctor`, and `better-auth mongo indexes`.
|
data/README.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# better_auth-cli
|
|
2
|
+
|
|
3
|
+
Command-line tools for Better Auth Ruby.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
better-auth generate --config config/better_auth.rb --dialect postgres --output db/better_auth/schema.sql
|
|
7
|
+
better-auth migrate --config config/better_auth.rb --yes
|
|
8
|
+
better-auth migrate status --config config/better_auth.rb
|
|
9
|
+
better-auth doctor --config config/better_auth.rb
|
|
10
|
+
better-auth mongo indexes --config config/better_auth.rb
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The config file should return a `Hash` or `BetterAuth::Configuration`.
|
|
14
|
+
`doctor` validates the config, secret strength, HTTPS base URL, rate-limit
|
|
15
|
+
storage, SQL adapter support, and pending Better Auth migrations.
|
|
16
|
+
`mongo indexes` is for MongoDB adapters and idempotently ensures the indexes
|
|
17
|
+
declared by the active Better Auth schema.
|
|
18
|
+
|
|
19
|
+
Install `openauth-cli` for the `openauth` executable alias.
|
data/exe/better-auth
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "better_auth"
|
|
4
|
+
require "better_auth/cli/version"
|
|
5
|
+
require "better_auth/doctor"
|
|
6
|
+
require "better_auth/sql_migration"
|
|
7
|
+
require "fileutils"
|
|
8
|
+
require "optparse"
|
|
9
|
+
|
|
10
|
+
module BetterAuth
|
|
11
|
+
class CLI
|
|
12
|
+
class Error < StandardError; end
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
attr_accessor :configuration
|
|
16
|
+
|
|
17
|
+
def configure(value = nil)
|
|
18
|
+
@configuration = block_given? ? yield : value
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def run(argv = ARGV, stdout: $stdout, stderr: $stderr)
|
|
22
|
+
new(argv, stdout: stdout, stderr: stderr).run
|
|
23
|
+
rescue Error, BetterAuth::SQLMigration::UnsupportedAdapterError, BetterAuth::Error, OptionParser::ParseError => error
|
|
24
|
+
stderr.puts error.message
|
|
25
|
+
1
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def initialize(argv, stdout:, stderr:)
|
|
30
|
+
@argv = argv.dup
|
|
31
|
+
@stdout = stdout
|
|
32
|
+
@stderr = stderr
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def run
|
|
36
|
+
command = argv.shift
|
|
37
|
+
case command
|
|
38
|
+
when "generate"
|
|
39
|
+
generate(argv)
|
|
40
|
+
when "migrate"
|
|
41
|
+
migrate(argv)
|
|
42
|
+
when "doctor"
|
|
43
|
+
doctor(argv)
|
|
44
|
+
when "mongo"
|
|
45
|
+
mongo(argv)
|
|
46
|
+
when "-h", "--help", "help", nil
|
|
47
|
+
stdout.puts usage
|
|
48
|
+
0
|
|
49
|
+
else
|
|
50
|
+
raise Error, "Unknown command: #{command}"
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
attr_reader :argv, :stdout, :stderr
|
|
57
|
+
|
|
58
|
+
def generate(args)
|
|
59
|
+
options = parse_generate_options(args)
|
|
60
|
+
config = load_config(options.fetch(:config))
|
|
61
|
+
adapter = sql_adapter_for(config)
|
|
62
|
+
connection = adapter&.connection
|
|
63
|
+
dialect = BetterAuth::SQLMigration.normalize_dialect(options[:dialect] || adapter&.dialect || "postgres")
|
|
64
|
+
sql = if connection
|
|
65
|
+
BetterAuth::SQLMigration.render_pending(config, connection: connection, dialect: dialect, generator: "better_auth-cli")
|
|
66
|
+
else
|
|
67
|
+
BetterAuth::SQLMigration.render(config, dialect: dialect, generator: "better_auth-cli")
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
if sql.empty?
|
|
71
|
+
stdout.puts "No migrations needed."
|
|
72
|
+
return 0
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
output = options.fetch(:output)
|
|
76
|
+
FileUtils.mkdir_p(File.dirname(output))
|
|
77
|
+
File.write(output, sql)
|
|
78
|
+
stdout.puts "generated #{output}"
|
|
79
|
+
0
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def migrate(args)
|
|
83
|
+
if args.first == "status"
|
|
84
|
+
args.shift
|
|
85
|
+
return migration_status(args)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
options = parse_migrate_options(args)
|
|
89
|
+
raise Error, "Pass --yes to apply migrations." unless options[:yes]
|
|
90
|
+
|
|
91
|
+
auth = auth_for(load_config(options.fetch(:config)))
|
|
92
|
+
migrated = BetterAuth::SQLMigration.migrate_pending(auth)
|
|
93
|
+
stdout.puts(migrated ? "migration completed successfully." : "No migrations needed.")
|
|
94
|
+
0
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def migration_status(args)
|
|
98
|
+
options = parse_config_options(args, "migrate status --config PATH is required")
|
|
99
|
+
config = load_config(options.fetch(:config))
|
|
100
|
+
adapter = required_sql_adapter_for(config)
|
|
101
|
+
plan = BetterAuth::SQLMigration.plan(config, connection: adapter.connection, dialect: adapter.dialect)
|
|
102
|
+
|
|
103
|
+
if plan.empty?
|
|
104
|
+
stdout.puts "No migrations needed."
|
|
105
|
+
else
|
|
106
|
+
plan.to_create.each { |change| stdout.puts "create table #{change.table_name}" }
|
|
107
|
+
plan.to_add.each { |change| stdout.puts "add #{change.fields.keys.join(", ")} to #{change.table_name}" }
|
|
108
|
+
plan.to_index.each { |change| stdout.puts "create index #{change.name}" }
|
|
109
|
+
plan.warnings.each { |warning| stdout.puts "warning: #{warning}" }
|
|
110
|
+
end
|
|
111
|
+
0
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def doctor(args)
|
|
115
|
+
options = parse_config_options(args, "doctor --config PATH is required")
|
|
116
|
+
config = load_config(options.fetch(:config))
|
|
117
|
+
BetterAuth::Doctor.print(BetterAuth::Doctor.check(config), stdout: stdout, stderr: stderr)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def mongo(args)
|
|
121
|
+
command = args.shift
|
|
122
|
+
case command
|
|
123
|
+
when "indexes"
|
|
124
|
+
mongo_indexes(args)
|
|
125
|
+
else
|
|
126
|
+
raise Error, "Unknown mongo command: #{command || "(none)"}"
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def mongo_indexes(args)
|
|
131
|
+
options = parse_config_options(args, "mongo indexes --config PATH is required")
|
|
132
|
+
auth = auth_for(load_config(options.fetch(:config)))
|
|
133
|
+
adapter = auth.context.adapter
|
|
134
|
+
unless adapter.respond_to?(:ensure_indexes!)
|
|
135
|
+
raise Error, "MongoDB index setup requires an adapter that supports ensure_indexes!"
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
indexes = adapter.ensure_indexes!
|
|
139
|
+
if indexes.empty?
|
|
140
|
+
stdout.puts "No MongoDB indexes needed."
|
|
141
|
+
else
|
|
142
|
+
indexes.each do |index|
|
|
143
|
+
validate_mongo_index!(index)
|
|
144
|
+
unique = index[:unique] ? " unique" : ""
|
|
145
|
+
stdout.puts "ensured#{unique} index #{index[:collection]}.#{index[:field]}"
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
0
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def parse_generate_options(args)
|
|
152
|
+
options = {}
|
|
153
|
+
OptionParser.new do |parser|
|
|
154
|
+
parser.on("--config PATH") { |value| options[:config] = value }
|
|
155
|
+
parser.on("--dialect DIALECT") { |value| options[:dialect] = value }
|
|
156
|
+
parser.on("--output PATH") { |value| options[:output] = value }
|
|
157
|
+
end.parse!(args)
|
|
158
|
+
require_option!(options, :config, "generate --config PATH is required")
|
|
159
|
+
require_option!(options, :output, "generate --output PATH is required")
|
|
160
|
+
options
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def parse_migrate_options(args)
|
|
164
|
+
options = {yes: false}
|
|
165
|
+
OptionParser.new do |parser|
|
|
166
|
+
parser.on("--config PATH") { |value| options[:config] = value }
|
|
167
|
+
parser.on("--yes", "-y") { options[:yes] = true }
|
|
168
|
+
end.parse!(args)
|
|
169
|
+
require_option!(options, :config, "migrate --config PATH is required")
|
|
170
|
+
options
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def parse_config_options(args, missing_message)
|
|
174
|
+
options = {}
|
|
175
|
+
OptionParser.new do |parser|
|
|
176
|
+
parser.on("--config PATH") { |value| options[:config] = value }
|
|
177
|
+
end.parse!(args)
|
|
178
|
+
require_option!(options, :config, missing_message)
|
|
179
|
+
options
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def require_option!(options, key, message)
|
|
183
|
+
raise Error, message unless options[key]
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def load_config(path)
|
|
187
|
+
raise Error, "Config file not found: #{path}" unless File.exist?(path)
|
|
188
|
+
|
|
189
|
+
self.class.configure(nil)
|
|
190
|
+
result = TOPLEVEL_BINDING.eval(File.read(path), path)
|
|
191
|
+
value = normalize_config_value(result) || self.class.configuration
|
|
192
|
+
raise Error, "Config file must return a Hash, BetterAuth::Configuration, or BetterAuth::Auth" unless value
|
|
193
|
+
|
|
194
|
+
BetterAuth::SQLMigration.configuration_for(value)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def normalize_config_value(value)
|
|
198
|
+
value if value.is_a?(Hash) || value.is_a?(BetterAuth::Configuration) || value.is_a?(BetterAuth::Auth)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def validate_mongo_index!(index)
|
|
202
|
+
return if index[:collection] && index[:field]
|
|
203
|
+
|
|
204
|
+
raise Error, "MongoDB index metadata must include collection and field"
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def sql_adapter_for(config)
|
|
208
|
+
required_sql_adapter_for(config)
|
|
209
|
+
rescue BetterAuth::SQLMigration::UnsupportedAdapterError
|
|
210
|
+
nil
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def required_sql_adapter_for(config)
|
|
214
|
+
adapter = auth_for(config).context.adapter
|
|
215
|
+
unless adapter.respond_to?(:dialect) && adapter.respond_to?(:connection)
|
|
216
|
+
raise BetterAuth::SQLMigration::UnsupportedAdapterError,
|
|
217
|
+
"Better Auth SQL migrations require core SQL adapters with connection and dialect support"
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
adapter
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def auth_for(config)
|
|
224
|
+
return config if config.is_a?(BetterAuth::Auth)
|
|
225
|
+
|
|
226
|
+
BetterAuth.auth(config.to_h)
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def usage
|
|
230
|
+
<<~TEXT
|
|
231
|
+
Usage:
|
|
232
|
+
better-auth generate --config PATH --dialect DIALECT --output PATH
|
|
233
|
+
better-auth migrate --config PATH --yes
|
|
234
|
+
better-auth migrate status --config PATH
|
|
235
|
+
better-auth doctor --config PATH
|
|
236
|
+
better-auth mongo indexes --config PATH
|
|
237
|
+
TEXT
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: better_auth-cli
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.10.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Sebastian Sala
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: better_auth
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - '='
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: 0.10.0
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - '='
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: 0.10.0
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: minitest
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '5.25'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '5.25'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: rake
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '13.2'
|
|
47
|
+
type: :development
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '13.2'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: sqlite3
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '2.0'
|
|
61
|
+
type: :development
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '2.0'
|
|
68
|
+
description: Generates and applies Better Auth Ruby database migrations from app configuration.
|
|
69
|
+
email:
|
|
70
|
+
- sebastian.sala.tech@gmail.com
|
|
71
|
+
executables:
|
|
72
|
+
- better-auth
|
|
73
|
+
extensions: []
|
|
74
|
+
extra_rdoc_files: []
|
|
75
|
+
files:
|
|
76
|
+
- CHANGELOG.md
|
|
77
|
+
- README.md
|
|
78
|
+
- exe/better-auth
|
|
79
|
+
- lib/better_auth/cli.rb
|
|
80
|
+
- lib/better_auth/cli/version.rb
|
|
81
|
+
homepage: https://github.com/sebasxsala/better-auth-rb
|
|
82
|
+
licenses:
|
|
83
|
+
- MIT
|
|
84
|
+
metadata:
|
|
85
|
+
homepage_uri: https://github.com/sebasxsala/better-auth-rb
|
|
86
|
+
source_code_uri: https://github.com/sebasxsala/better-auth-rb
|
|
87
|
+
rdoc_options: []
|
|
88
|
+
require_paths:
|
|
89
|
+
- lib
|
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
91
|
+
requirements:
|
|
92
|
+
- - ">="
|
|
93
|
+
- !ruby/object:Gem::Version
|
|
94
|
+
version: 3.2.0
|
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
96
|
+
requirements:
|
|
97
|
+
- - ">="
|
|
98
|
+
- !ruby/object:Gem::Version
|
|
99
|
+
version: '0'
|
|
100
|
+
requirements: []
|
|
101
|
+
rubygems_version: 3.6.9
|
|
102
|
+
specification_version: 4
|
|
103
|
+
summary: Command-line tools for Better Auth Ruby
|
|
104
|
+
test_files: []
|