better_auth-roda 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 77eb658098b1736ed8bfe2217147b77081c8d0503b546047d09d31c968ca2122
4
+ data.tar.gz: b852714e6e2a39c99b4ab79c61b85de9a98506edc759c16a029d517f3f338ed9
5
+ SHA512:
6
+ metadata.gz: 7a87f3f1b578f3f1a1feb6504408612f9b29ba6b5a5197152589e90fd1a8eb1bb13e813b5f387c0ba726a56eae888ba4988415a4c3871dd9f24986a5660d4bde
7
+ data.tar.gz: fc456faca0a278968ce208d3a2feb78e01a923be18c9eb2cbf281f5c14ac58ec93235bfadb26e9964e1970a4233f85be7c5e12afb16fa30484a3fd90e0731bf8
data/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ # Changelog
2
+
3
+ ## Unreleased
4
+
5
+ ## 0.10.0 - 2026-05-21
6
+
7
+ - Initial Roda integration package.
8
+ - Fixed nested auth mount handling and expanded plugin, configuration, and migration coverage.
data/README.md ADDED
@@ -0,0 +1,62 @@
1
+ # Better Auth Roda
2
+
3
+ Roda adapter for Better Auth Ruby. This package is a thin integration around
4
+ the core Rack auth object, with a Roda plugin, request helpers, and SQL
5
+ migration tasks.
6
+
7
+ ## Installation
8
+
9
+ ```ruby
10
+ gem "better_auth-roda"
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```ruby
16
+ require "roda"
17
+ require "better_auth/roda"
18
+
19
+ class App < Roda
20
+ plugin :better_auth
21
+
22
+ better_auth at: "/api/auth" do |config|
23
+ config.secret = ENV.fetch("BETTER_AUTH_SECRET")
24
+ config.base_url = ENV["BETTER_AUTH_URL"]
25
+ config.database = :memory
26
+ config.email_and_password = {enabled: true}
27
+ end
28
+
29
+ route do |r|
30
+ r.better_auth
31
+
32
+ r.get "dashboard" do
33
+ current_user.to_json
34
+ end
35
+ end
36
+ end
37
+ ```
38
+
39
+ ## Rake Tasks
40
+
41
+ ```ruby
42
+ require "better_auth/roda/tasks"
43
+ ```
44
+
45
+ ```bash
46
+ rake better_auth:install
47
+ rake better_auth:generate:migration
48
+ rake better_auth:migrate
49
+ rake better_auth:migrate:status
50
+ rake better_auth:doctor
51
+ rake better_auth:routes
52
+ ```
53
+
54
+ When a SQL adapter is configured, migration generation introspects the current
55
+ database and emits only missing Better Auth tables, columns, and indexes.
56
+
57
+ ## Development
58
+
59
+ ```bash
60
+ cd packages/better_auth-roda
61
+ bundle exec rake ci
62
+ ```
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BetterAuth
4
+ module Roda
5
+ class Configuration
6
+ AUTH_OPTION_NAMES = %i[
7
+ app_name
8
+ base_url
9
+ base_path
10
+ secret
11
+ secrets
12
+ database
13
+ plugins
14
+ trusted_origins
15
+ rate_limit
16
+ session
17
+ account
18
+ user
19
+ verification
20
+ advanced
21
+ email_and_password
22
+ password_hasher
23
+ email_verification
24
+ social_providers
25
+ experimental
26
+ secondary_storage
27
+ database_hooks
28
+ hooks
29
+ on_api_error
30
+ disabled_paths
31
+ logger
32
+ ].freeze
33
+
34
+ attr_accessor(*AUTH_OPTION_NAMES)
35
+
36
+ def initialize
37
+ @base_path = BetterAuth::Configuration::DEFAULT_BASE_PATH
38
+ @plugins = []
39
+ @trusted_origins = []
40
+ end
41
+
42
+ def to_auth_options
43
+ AUTH_OPTION_NAMES.each_with_object({}) do |name, options|
44
+ value = public_send(name)
45
+ next if value.nil?
46
+ next if value.respond_to?(:empty?) && value.empty?
47
+
48
+ options[name] = value
49
+ end
50
+ end
51
+
52
+ def copy
53
+ self.class.new.tap do |copy|
54
+ AUTH_OPTION_NAMES.each do |name|
55
+ value = public_send(name)
56
+ copy.public_send("#{name}=", deep_dup(value))
57
+ end
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def deep_dup(value)
64
+ case value
65
+ when Hash
66
+ value.transform_values { |entry| deep_dup(entry) }
67
+ when Array
68
+ value.map { |entry| deep_dup(entry) }
69
+ else
70
+ value
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "better_auth/sql_migration"
4
+
5
+ module BetterAuth
6
+ module Roda
7
+ module Migration
8
+ DEFAULT_MIGRATIONS_PATH = BetterAuth::SQLMigration::DEFAULT_MIGRATIONS_PATH
9
+ MISSING_MIGRATIONS_TABLE_MESSAGES = BetterAuth::SQLMigration::MISSING_MIGRATIONS_TABLE_MESSAGES
10
+ UnsupportedAdapterError = BetterAuth::SQLMigration::UnsupportedAdapterError
11
+ GENERATOR = "better_auth-roda"
12
+
13
+ module_function
14
+
15
+ def render(options, dialect:)
16
+ BetterAuth::SQLMigration.render(options, dialect: dialect, generator: GENERATOR)
17
+ end
18
+
19
+ def generate(options, dialect:, migrations_path: DEFAULT_MIGRATIONS_PATH, timestamp: Time.now.utc.strftime("%Y%m%d%H%M%S"), connection: nil)
20
+ BetterAuth::SQLMigration.generate(
21
+ options,
22
+ dialect: dialect,
23
+ generator: GENERATOR,
24
+ migrations_path: migrations_path,
25
+ timestamp: timestamp,
26
+ connection: connection
27
+ )
28
+ end
29
+
30
+ def migrate(auth_or_options, migrations_path: DEFAULT_MIGRATIONS_PATH)
31
+ BetterAuth::SQLMigration.migrate(auth_or_options, migrations_path: migrations_path)
32
+ end
33
+
34
+ def method_missing(name, *args, **kwargs, &block)
35
+ return BetterAuth::SQLMigration.public_send(name, *args, **kwargs, &block) if BetterAuth::SQLMigration.respond_to?(name)
36
+
37
+ super
38
+ end
39
+
40
+ def respond_to_missing?(name, include_private = false)
41
+ BetterAuth::SQLMigration.respond_to?(name, include_private) || super
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module BetterAuth
6
+ module Roda
7
+ class MountedApp
8
+ def initialize(auth, mount_path:)
9
+ @auth = auth
10
+ @mount_path = normalize_path(mount_path)
11
+ end
12
+
13
+ def mount_matches?(env)
14
+ return false if @mount_path == "/"
15
+
16
+ path_info = normalize_path(env["PATH_INFO"], trim: true)
17
+ return true if path_info == @mount_path || path_info.start_with?("#{@mount_path}/")
18
+ return true if script_mount_matches?(normalize_path(env["SCRIPT_NAME"], trim: true))
19
+
20
+ full = full_request_path(env)
21
+ full == @mount_path || full.start_with?("#{@mount_path}/")
22
+ end
23
+
24
+ def call(env)
25
+ @auth.call(next_env(env))
26
+ rescue BetterAuth::APIError, JSON::ParserError
27
+ raise
28
+ rescue => error
29
+ handle_unexpected_error(error, env)
30
+ end
31
+
32
+ private
33
+
34
+ def next_env(env)
35
+ rewritten_path = mounted_path_info(env)
36
+ env.merge("PATH_INFO" => rewritten_path).tap do |next_env|
37
+ next_env["SCRIPT_NAME"] = "" if shared_mount_rewrite?(env, rewritten_path)
38
+ end
39
+ end
40
+
41
+ def full_request_path(env)
42
+ script = env.fetch("SCRIPT_NAME", "").to_s
43
+ path = env.fetch("PATH_INFO", "").to_s
44
+ normalize_path("#{script}#{path}", trim: true)
45
+ end
46
+
47
+ def mounted_path_info(env)
48
+ path_info = normalize_path(env["PATH_INFO"], trim: false)
49
+ comparable_path = normalize_path(env["PATH_INFO"], trim: true)
50
+ return path_info if comparable_path == @mount_path || comparable_path.start_with?("#{@mount_path}/")
51
+
52
+ script_name = normalize_path(env["SCRIPT_NAME"], trim: true)
53
+ return normalize_path("#{@mount_path}/#{path_info.delete_prefix("/")}", trim: false) if script_mount_matches?(script_name)
54
+
55
+ prefix = (script_name == "/") ? @mount_path : script_name
56
+ return path_info if comparable_path == prefix || comparable_path.start_with?("#{prefix}/")
57
+
58
+ normalize_path("#{prefix}/#{path_info.delete_prefix("/")}", trim: false)
59
+ end
60
+
61
+ def script_mount_matches?(script_name)
62
+ script_name == @mount_path || script_name.end_with?(@mount_path)
63
+ end
64
+
65
+ def shared_mount_rewrite?(env, rewritten_path)
66
+ script_name = normalize_path(env["SCRIPT_NAME"], trim: true)
67
+ original_path = normalize_path(env["PATH_INFO"], trim: true)
68
+ script_name != "/" &&
69
+ !original_path.start_with?("#{@mount_path}/") &&
70
+ rewritten_path.start_with?("#{@mount_path}/")
71
+ end
72
+
73
+ def normalize_path(path, trim: true)
74
+ normalized = path.to_s
75
+ normalized = "/#{normalized}" unless normalized.start_with?("/")
76
+ normalized = normalized.squeeze("/")
77
+ normalized = normalized.delete_suffix("/") if trim && normalized != "/"
78
+ normalized.empty? ? "/" : normalized
79
+ end
80
+
81
+ def handle_unexpected_error(error, env)
82
+ options = @auth.options
83
+ on_api_error = options.on_api_error || {}
84
+ raise error if on_api_error[:throw] || on_api_error["throw"]
85
+
86
+ callback = on_api_error[:on_error] || on_api_error[:onError] || on_api_error["on_error"] || on_api_error["onError"]
87
+ callback.call(error, error_context(env)) if callback.respond_to?(:call)
88
+
89
+ api_error = BetterAuth::APIError.new("INTERNAL_SERVER_ERROR")
90
+ [
91
+ api_error.status_code,
92
+ {"content-type" => "application/json"},
93
+ [JSON.generate(api_error.to_h)]
94
+ ]
95
+ end
96
+
97
+ def error_context(env)
98
+ path = mounted_path_info(env)
99
+ route_path = if path == @mount_path
100
+ "/"
101
+ else
102
+ path.delete_prefix(@mount_path)
103
+ end
104
+ Struct.new(:path, :env).new(normalize_path(route_path), env)
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,166 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ class ::Roda
6
+ module RodaPlugins
7
+ module BetterAuthPlugin
8
+ def self.configure(app)
9
+ app.opts[:better_auth_configured] = false unless app.opts.key?(:better_auth_configured)
10
+ end
11
+
12
+ module ClassMethods
13
+ def better_auth(at: BetterAuth::Configuration::DEFAULT_BASE_PATH, auth: nil, **overrides)
14
+ mount_path = normalize_better_auth_mount_path(at)
15
+ if mount_path == "/"
16
+ raise ArgumentError,
17
+ "better_auth mount path cannot be '/' (it would capture every request). " \
18
+ "Use a prefix such as #{BetterAuth::Configuration::DEFAULT_BASE_PATH.inspect}."
19
+ end
20
+ if opts[:better_auth_configured] && opts[:better_auth_owner].equal?(self)
21
+ raise ArgumentError, "better_auth is already configured for this app"
22
+ end
23
+
24
+ config = BetterAuth::Roda.configuration.copy
25
+ yield config if block_given?
26
+ config.base_path = mount_path
27
+ options = config.to_auth_options.merge(overrides).merge(base_path: mount_path)
28
+ auth_instance = auth || BetterAuth.auth(options)
29
+
30
+ opts[:better_auth_auth] = auth_instance
31
+ opts[:better_auth_mount_path] = mount_path
32
+ opts[:better_auth_mounted_app] = BetterAuth::Roda::MountedApp.new(auth_instance, mount_path: mount_path)
33
+ opts[:better_auth_owner] = self
34
+ opts[:better_auth_configured] = true
35
+ end
36
+
37
+ private
38
+
39
+ def normalize_better_auth_mount_path(path)
40
+ normalized = path.to_s
41
+ normalized = "/#{normalized}" unless normalized.start_with?("/")
42
+ normalized = normalized.squeeze("/")
43
+ (normalized == "/") ? normalized : normalized.delete_suffix("/")
44
+ end
45
+ end
46
+
47
+ module RequestMethods
48
+ def better_auth
49
+ app = scope.opts[:better_auth_mounted_app]
50
+ return unless app&.mount_matches?(env)
51
+
52
+ halt app.call(env)
53
+ end
54
+ end
55
+
56
+ module InstanceMethods
57
+ def current_session
58
+ data = better_auth_session_data
59
+ data&.fetch(:session, nil) || data&.fetch("session", nil)
60
+ end
61
+
62
+ def current_user
63
+ data = better_auth_session_data
64
+ data&.fetch(:user, nil) || data&.fetch("user", nil)
65
+ end
66
+
67
+ def authenticated?
68
+ !current_user.nil?
69
+ end
70
+
71
+ def require_authentication
72
+ return true if authenticated?
73
+
74
+ if prefers_json_response?
75
+ error = BetterAuth::APIError.new("UNAUTHORIZED")
76
+ request.halt [
77
+ 401,
78
+ {"content-type" => "application/json"},
79
+ [JSON.generate(error.to_h)]
80
+ ]
81
+ end
82
+
83
+ request.halt [401, {}, [""]]
84
+ end
85
+
86
+ private
87
+
88
+ def prefers_json_response?
89
+ accept = request.env["HTTP_ACCEPT"].to_s
90
+ return false if accept.empty? || accept == "*/*"
91
+
92
+ preferred = accept.split(",").filter_map do |entry|
93
+ media_type, *params = entry.split(";").map(&:strip)
94
+ next unless media_type == "application/json" || media_type.end_with?("+json") || media_type == "text/html"
95
+
96
+ q = params.find { |param| param.start_with?("q=") }&.split("=", 2)&.last&.to_f || 1.0
97
+ [media_type, q]
98
+ end.max_by { |_media_type, q| q }
99
+
100
+ if preferred
101
+ media_type, q = preferred
102
+ return q.positive? && (media_type == "application/json" || media_type.end_with?("+json"))
103
+ end
104
+
105
+ accept.split(",").any? do |entry|
106
+ media_type = entry.split(";", 2).first.to_s.strip
107
+ media_type == "application/json" || media_type.end_with?("+json")
108
+ end
109
+ end
110
+
111
+ def better_auth_session_data
112
+ return request.env["better_auth.session"] if request.env.key?("better_auth.session")
113
+
114
+ request.env["better_auth.session"] = resolve_better_auth_session
115
+ end
116
+
117
+ def resolve_better_auth_session
118
+ auth = better_auth_auth
119
+ result = auth.api.get_session(
120
+ request: Rack::Request.new(request.env),
121
+ method: "GET",
122
+ as_response: true
123
+ )
124
+ return resolve_better_auth_response(result) if result.respond_to?(:headers) && result.respond_to?(:body)
125
+
126
+ apply_better_auth_response_headers(result[:headers] || result["headers"] || {})
127
+ result[:response] || result["response"]
128
+ end
129
+
130
+ def resolve_better_auth_response(auth_response)
131
+ apply_better_auth_response_headers(auth_response.headers || {})
132
+ body = auth_response.body.respond_to?(:join) ? auth_response.body.join : auth_response.body.to_s
133
+ payload = body.empty? ? nil : JSON.parse(body)
134
+ raise_better_auth_response_error(auth_response, payload) if auth_response.status.to_i >= 400
135
+
136
+ payload
137
+ end
138
+
139
+ def raise_better_auth_response_error(auth_response, payload)
140
+ payload = payload.is_a?(Hash) ? payload : {}
141
+ status = BetterAuth::APIError::STATUS_CODES.key(auth_response.status.to_i) || "INTERNAL_SERVER_ERROR"
142
+ raise BetterAuth::APIError.new(
143
+ status,
144
+ message: payload["message"],
145
+ code: payload["code"],
146
+ headers: auth_response.headers || {}
147
+ )
148
+ end
149
+
150
+ def apply_better_auth_response_headers(headers)
151
+ set_cookie = headers["set-cookie"] || headers["Set-Cookie"] || headers[:set_cookie]
152
+ return if set_cookie.to_s.empty?
153
+
154
+ existing = response.headers["set-cookie"].to_s
155
+ response.headers["set-cookie"] = [existing, set_cookie.to_s].reject(&:empty?).join("\n")
156
+ end
157
+
158
+ def better_auth_auth
159
+ opts[:better_auth_auth] || BetterAuth::Roda.auth
160
+ end
161
+ end
162
+ end
163
+
164
+ register_plugin(:better_auth, BetterAuthPlugin)
165
+ end
166
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "fileutils"
4
+ require "rake"
5
+ require "better_auth/roda"
6
+
7
+ namespace :better_auth do
8
+ desc "Create the Better Auth Roda config and migration directory"
9
+ task :install do
10
+ config_path = "config/better_auth.rb"
11
+ FileUtils.mkdir_p(File.dirname(config_path))
12
+ if File.exist?(config_path)
13
+ puts "skip #{config_path} already exists"
14
+ else
15
+ File.write(config_path, BetterAuth::Roda.default_config_template)
16
+ puts "create #{config_path}"
17
+ end
18
+
19
+ FileUtils.mkdir_p(BetterAuth::Roda::Migration::DEFAULT_MIGRATIONS_PATH)
20
+ end
21
+
22
+ namespace :generate do
23
+ desc "Create the Better Auth SQL migration"
24
+ task :migration do
25
+ BetterAuth::Roda.load_app_config!
26
+ dialect = BetterAuth::Roda::Migration.normalize_dialect(BetterAuth::Env.get("BETTER_AUTH_DIALECT") || BetterAuth::Env.get("BETTER_AUTH_DATABASE_DIALECT") || "postgres")
27
+ config = BetterAuth::Roda.migration_configuration
28
+ adapter = begin
29
+ BetterAuth::Roda.auth.context.adapter
30
+ rescue
31
+ nil
32
+ end
33
+ connection = if adapter&.respond_to?(:connection) && adapter.respond_to?(:dialect) && BetterAuth::Roda::Migration.normalize_dialect(adapter.dialect) == dialect
34
+ adapter.connection
35
+ end
36
+ path = BetterAuth::Roda::Migration.generate(config, dialect: dialect, connection: connection)
37
+ puts(path ? "create #{path}" : "no migrations needed")
38
+ end
39
+ end
40
+
41
+ desc "Run pending Better Auth SQL migrations"
42
+ task :migrate do
43
+ BetterAuth::Roda.load_app_config!
44
+ BetterAuth::Roda::Migration.migrate(BetterAuth::Roda.auth)
45
+ end
46
+
47
+ namespace :migrate do
48
+ desc "Print pending Better Auth SQL migration status"
49
+ task :status do
50
+ BetterAuth::Roda.load_app_config!
51
+ auth = BetterAuth::Roda.auth
52
+ adapter = auth.context.adapter
53
+ unless adapter.respond_to?(:connection) && adapter.respond_to?(:dialect)
54
+ raise BetterAuth::Roda::Migration::UnsupportedAdapterError, "Better Auth SQL migrations require core SQL adapters with connection and dialect support"
55
+ end
56
+ plan = BetterAuth::Roda::Migration.plan(auth.options, connection: adapter.connection, dialect: adapter.dialect)
57
+ if plan.empty?
58
+ puts "No migrations needed."
59
+ else
60
+ plan.to_create.each { |change| puts "create table #{change.table_name}" }
61
+ plan.to_add.each { |change| puts "add #{change.fields.keys.join(", ")} to #{change.table_name}" }
62
+ plan.to_index.each { |change| puts "create index #{change.name}" }
63
+ plan.warnings.each { |warning| puts "warning: #{warning}" }
64
+ end
65
+ end
66
+ end
67
+
68
+ desc "Check Better Auth configuration and schema health"
69
+ task :doctor do
70
+ BetterAuth::Roda.load_app_config!
71
+ exit_code = BetterAuth::Doctor.print(BetterAuth::Doctor.check(BetterAuth::Roda.migration_configuration), stdout: $stdout, stderr: $stderr)
72
+ abort if exit_code != 0
73
+ end
74
+
75
+ desc "Print Better Auth Roda mount information"
76
+ task :routes do
77
+ BetterAuth::Roda.load_app_config!
78
+ mount_path = BetterAuth::Roda.configuration.base_path
79
+ puts "#{mount_path}/* -> BetterAuth.auth"
80
+ puts "Core routes are handled by Better Auth; use the OpenAPI plugin or HTTP API docs for endpoint details."
81
+ end
82
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BetterAuth
4
+ module Roda
5
+ VERSION = "0.10.0"
6
+ end
7
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "better_auth"
4
+ require "roda"
5
+ require_relative "roda/version"
6
+ require_relative "roda/configuration"
7
+ require_relative "roda/mounted_app"
8
+ require_relative "roda/migration"
9
+ require_relative "roda/plugin"
10
+
11
+ module BetterAuth
12
+ module Roda
13
+ class << self
14
+ def configuration
15
+ @configuration ||= Configuration.new
16
+ end
17
+
18
+ def configure
19
+ yield configuration
20
+ @auth = nil
21
+ self
22
+ end
23
+
24
+ def reset!
25
+ @configuration = nil
26
+ @auth = nil
27
+ end
28
+
29
+ def auth(overrides = nil)
30
+ options = configuration.to_auth_options
31
+ return @auth ||= BetterAuth.auth(options) if overrides.nil? || overrides.empty?
32
+
33
+ BetterAuth.auth(options.merge(overrides))
34
+ end
35
+
36
+ def migration_configuration
37
+ options = configuration.to_auth_options
38
+ options[:secret] ||= BetterAuth::Configuration::DEFAULT_SECRET
39
+ BetterAuth::Configuration.new(options)
40
+ end
41
+
42
+ def app_config_path(path = nil)
43
+ path || BetterAuth::Env.get("BETTER_AUTH_CONFIG") || "config/better_auth.rb"
44
+ end
45
+
46
+ def load_app_config(path = nil)
47
+ config_path = app_config_path(path)
48
+ return false unless File.exist?(config_path)
49
+
50
+ load config_path
51
+ true
52
+ end
53
+
54
+ def load_app_config!(path = nil)
55
+ config_path = app_config_path(path)
56
+ return true if load_app_config(config_path)
57
+
58
+ raise ArgumentError,
59
+ "Better Auth Roda config not found at #{config_path.inspect}. " \
60
+ "Run `rake better_auth:install` or set BETTER_AUTH_CONFIG to a shared config file."
61
+ end
62
+
63
+ def default_config_template
64
+ <<~RUBY
65
+ # frozen_string_literal: true
66
+
67
+ require "better_auth/roda"
68
+
69
+ BetterAuth::Roda.configure do |config|
70
+ config.secret = BetterAuth::Env.fetch("BETTER_AUTH_SECRET", "change-me-roda-secret-12345678901234567890")
71
+ config.base_url = BetterAuth::Env.get("BETTER_AUTH_URL")
72
+ config.base_path = "/api/auth"
73
+
74
+ config.database = ->(options) do
75
+ case BetterAuth::Env.fetch("BETTER_AUTH_DATABASE_DIALECT", "postgres")
76
+ when "postgres", "postgresql"
77
+ BetterAuth::Adapters::Postgres.new(options, url: ENV.fetch("DATABASE_URL"))
78
+ when "mysql"
79
+ BetterAuth::Adapters::MySQL.new(options, url: ENV.fetch("DATABASE_URL"))
80
+ when "sqlite", "sqlite3"
81
+ BetterAuth::Adapters::SQLite.new(options, path: ENV.fetch("DATABASE_URL", "db/better_auth.sqlite3"))
82
+ else
83
+ raise "Unsupported BETTER_AUTH_DATABASE_DIALECT for better_auth-roda"
84
+ end
85
+ end
86
+
87
+ config.email_and_password = {
88
+ enabled: true
89
+ }
90
+
91
+ config.plugins = []
92
+ end
93
+ RUBY
94
+ end
95
+ end
96
+ end
97
+ end
metadata ADDED
@@ -0,0 +1,159 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: better_auth-roda
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.1'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '0.1'
26
+ - !ruby/object:Gem::Dependency
27
+ name: roda
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '3.0'
33
+ - - "<"
34
+ - !ruby/object:Gem::Version
35
+ version: '4'
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '3.0'
43
+ - - "<"
44
+ - !ruby/object:Gem::Version
45
+ version: '4'
46
+ - !ruby/object:Gem::Dependency
47
+ name: bundler
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - "~>"
51
+ - !ruby/object:Gem::Version
52
+ version: '2.5'
53
+ type: :development
54
+ prerelease: false
55
+ version_requirements: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '2.5'
60
+ - !ruby/object:Gem::Dependency
61
+ name: rack-test
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - "~>"
65
+ - !ruby/object:Gem::Version
66
+ version: '2.2'
67
+ type: :development
68
+ prerelease: false
69
+ version_requirements: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - "~>"
72
+ - !ruby/object:Gem::Version
73
+ version: '2.2'
74
+ - !ruby/object:Gem::Dependency
75
+ name: rake
76
+ requirement: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - "~>"
79
+ - !ruby/object:Gem::Version
80
+ version: '13.2'
81
+ type: :development
82
+ prerelease: false
83
+ version_requirements: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: '13.2'
88
+ - !ruby/object:Gem::Dependency
89
+ name: rspec
90
+ requirement: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - "~>"
93
+ - !ruby/object:Gem::Version
94
+ version: '3.13'
95
+ type: :development
96
+ prerelease: false
97
+ version_requirements: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - "~>"
100
+ - !ruby/object:Gem::Version
101
+ version: '3.13'
102
+ - !ruby/object:Gem::Dependency
103
+ name: standardrb
104
+ requirement: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - "~>"
107
+ - !ruby/object:Gem::Version
108
+ version: '1.0'
109
+ type: :development
110
+ prerelease: false
111
+ version_requirements: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - "~>"
114
+ - !ruby/object:Gem::Version
115
+ version: '1.0'
116
+ description: Roda integration for Better Auth Ruby. Better Auth Ruby is an independent
117
+ modern authentication framework for Ruby inspired by Better Auth. Provides a Roda
118
+ plugin, request helpers, and SQL migration tasks.
119
+ email:
120
+ - sebastian.sala.tech@gmail.com
121
+ executables: []
122
+ extensions: []
123
+ extra_rdoc_files: []
124
+ files:
125
+ - CHANGELOG.md
126
+ - README.md
127
+ - lib/better_auth/roda.rb
128
+ - lib/better_auth/roda/configuration.rb
129
+ - lib/better_auth/roda/migration.rb
130
+ - lib/better_auth/roda/mounted_app.rb
131
+ - lib/better_auth/roda/plugin.rb
132
+ - lib/better_auth/roda/tasks.rb
133
+ - lib/better_auth/roda/version.rb
134
+ homepage: https://github.com/sebasxsala/better-auth-rb
135
+ licenses:
136
+ - MIT
137
+ metadata:
138
+ homepage_uri: https://github.com/sebasxsala/better-auth-rb
139
+ source_code_uri: https://github.com/sebasxsala/better-auth-rb
140
+ changelog_uri: https://github.com/sebasxsala/better-auth-rb/blob/main/packages/better_auth-roda/CHANGELOG.md
141
+ bug_tracker_uri: https://github.com/sebasxsala/better-auth-rb/issues
142
+ rdoc_options: []
143
+ require_paths:
144
+ - lib
145
+ required_ruby_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: 3.2.0
150
+ required_rubygems_version: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ requirements: []
156
+ rubygems_version: 3.6.9
157
+ specification_version: 4
158
+ summary: Roda adapter for Better Auth
159
+ test_files: []