factorix 0.5.1 → 0.6.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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +19 -0
  3. data/README.md +1 -1
  4. data/lib/factorix/api/mod_download_api.rb +1 -1
  5. data/lib/factorix/api/mod_info.rb +2 -2
  6. data/lib/factorix/api/mod_management_api.rb +1 -1
  7. data/lib/factorix/api_credential.rb +1 -1
  8. data/lib/factorix/cli/commands/backup_support.rb +1 -1
  9. data/lib/factorix/cli/commands/base.rb +3 -3
  10. data/lib/factorix/cli/commands/cache/evict.rb +3 -3
  11. data/lib/factorix/cli/commands/cache/stat.rb +15 -15
  12. data/lib/factorix/cli/commands/command_wrapper.rb +5 -5
  13. data/lib/factorix/cli/commands/completion.rb +1 -2
  14. data/lib/factorix/cli/commands/confirmable.rb +1 -1
  15. data/lib/factorix/cli/commands/download_support.rb +2 -2
  16. data/lib/factorix/cli/commands/mod/check.rb +1 -1
  17. data/lib/factorix/cli/commands/mod/disable.rb +1 -1
  18. data/lib/factorix/cli/commands/mod/download.rb +5 -4
  19. data/lib/factorix/cli/commands/mod/edit.rb +9 -9
  20. data/lib/factorix/cli/commands/mod/enable.rb +1 -1
  21. data/lib/factorix/cli/commands/mod/image/add.rb +2 -2
  22. data/lib/factorix/cli/commands/mod/image/edit.rb +1 -1
  23. data/lib/factorix/cli/commands/mod/image/list.rb +4 -4
  24. data/lib/factorix/cli/commands/mod/install.rb +5 -4
  25. data/lib/factorix/cli/commands/mod/list.rb +7 -7
  26. data/lib/factorix/cli/commands/mod/search.rb +11 -9
  27. data/lib/factorix/cli/commands/mod/settings/dump.rb +3 -3
  28. data/lib/factorix/cli/commands/mod/settings/restore.rb +2 -2
  29. data/lib/factorix/cli/commands/mod/show.rb +20 -20
  30. data/lib/factorix/cli/commands/mod/sync.rb +6 -5
  31. data/lib/factorix/cli/commands/mod/uninstall.rb +1 -1
  32. data/lib/factorix/cli/commands/mod/update.rb +7 -6
  33. data/lib/factorix/cli/commands/mod/upload.rb +6 -6
  34. data/lib/factorix/cli/commands/path.rb +2 -2
  35. data/lib/factorix/cli/commands/version.rb +1 -1
  36. data/lib/factorix/{application.rb → container.rb} +8 -85
  37. data/lib/factorix/dependency/parser.rb +1 -1
  38. data/lib/factorix/http/client.rb +3 -3
  39. data/lib/factorix/info_json.rb +2 -2
  40. data/lib/factorix/mod_list.rb +2 -2
  41. data/lib/factorix/mod_settings.rb +2 -2
  42. data/lib/factorix/runtime/user_configurable.rb +9 -9
  43. data/lib/factorix/service_credential.rb +3 -3
  44. data/lib/factorix/version.rb +1 -1
  45. data/lib/factorix.rb +118 -1
  46. data/sig/factorix/container.rbs +15 -0
  47. data/sig/factorix.rbs +99 -0
  48. metadata +4 -4
  49. data/sig/factorix/application.rbs +0 -86
@@ -32,7 +32,7 @@ module Factorix
32
32
  "some-mod # Show details for some-mod"
33
33
  ]
34
34
 
35
- argument :mod_name, type: :string, required: true, desc: "MOD name to show"
35
+ argument :mod_name, required: true, desc: "MOD name to show"
36
36
 
37
37
  # Execute the show command
38
38
  #
@@ -75,10 +75,10 @@ module Factorix
75
75
  end
76
76
 
77
77
  private def display_header(mod_info)
78
- puts TITLE_STYLE[mod_info.title]
79
- puts
80
- puts mod_info.summary unless mod_info.summary.empty?
81
- puts
78
+ out.puts TITLE_STYLE[mod_info.title]
79
+ out.puts
80
+ out.puts mod_info.summary unless mod_info.summary.empty?
81
+ out.puts
82
82
  end
83
83
 
84
84
  private def display_basic_info(mod_info, local_status)
@@ -103,9 +103,9 @@ module Factorix
103
103
 
104
104
  max_label_width = rows.map {|label, _| label.length }.max
105
105
  rows.each do |label, value|
106
- puts "#{label.ljust(max_label_width)} #{value}"
106
+ out.puts "#{label.ljust(max_label_width)} #{value}"
107
107
  end
108
- puts
108
+ out.puts
109
109
  end
110
110
 
111
111
  private def format_status(local_status)
@@ -123,18 +123,18 @@ module Factorix
123
123
  end
124
124
 
125
125
  private def display_links(mod_info)
126
- puts HEADER_STYLE["Links"]
127
- puts " MOD Portal: https://mods.factorio.com/mod/#{mod_info.name}"
126
+ out.puts HEADER_STYLE["Links"]
127
+ out.puts " MOD Portal: https://mods.factorio.com/mod/#{mod_info.name}"
128
128
 
129
129
  if mod_info.detail
130
130
  if mod_info.detail.source_url
131
- puts " Source: #{mod_info.detail.source_url}"
131
+ out.puts " Source: #{mod_info.detail.source_url}"
132
132
  end
133
133
  if mod_info.detail.homepage
134
- puts " Homepage: #{mod_info.detail.homepage}"
134
+ out.puts " Homepage: #{mod_info.detail.homepage}"
135
135
  end
136
136
  end
137
- puts
137
+ out.puts
138
138
  end
139
139
 
140
140
  private def display_dependencies(mod_info)
@@ -149,16 +149,16 @@ module Factorix
149
149
  optional = parsed.select {|d| d[:type] == :optional }
150
150
 
151
151
  unless required.empty?
152
- puts HEADER_STYLE["Dependencies"]
152
+ out.puts HEADER_STYLE["Dependencies"]
153
153
  required.each {|dep| display_dependency(dep) }
154
- puts
154
+ out.puts
155
155
  end
156
156
 
157
157
  return if optional.empty?
158
158
 
159
- puts HEADER_STYLE["Optional Dependencies"]
159
+ out.puts HEADER_STYLE["Optional Dependencies"]
160
160
  optional.each {|dep| display_dependency(dep) }
161
- puts
161
+ out.puts
162
162
  end
163
163
 
164
164
  private def parse_dependency(dep_str)
@@ -178,7 +178,7 @@ module Factorix
178
178
  end
179
179
 
180
180
  private def display_dependency(dep)
181
- puts " #{dep[:spec]}"
181
+ out.puts " #{dep[:spec]}"
182
182
  end
183
183
 
184
184
  private def display_incompatibilities(mod_info)
@@ -191,9 +191,9 @@ module Factorix
191
191
 
192
192
  return if incompatible.empty?
193
193
 
194
- puts HEADER_STYLE["Incompatibilities"]
195
- incompatible.each {|dep| puts " #{INCOMPATIBLE_MOD_STYLE[dep[:spec]]}" }
196
- puts
194
+ out.puts HEADER_STYLE["Incompatibilities"]
195
+ incompatible.each {|dep| out.puts " #{INCOMPATIBLE_MOD_STYLE[dep[:spec]]}" }
196
+ out.puts
197
197
  end
198
198
  end
199
199
  end
@@ -31,15 +31,16 @@ module Factorix
31
31
  "-j 8 save.zip # Use 8 parallel downloads"
32
32
  ]
33
33
 
34
- argument :save_file, type: :string, required: true, desc: "Path to Factorio save file (.zip)"
35
- option :jobs, type: :integer, aliases: ["-j"], default: 4, desc: "Number of parallel downloads"
34
+ argument :save_file, required: true, desc: "Path to Factorio save file (.zip)"
35
+ option :jobs, aliases: ["-j"], default: "4", desc: "Number of parallel downloads"
36
36
 
37
37
  # Execute the sync command
38
38
  #
39
39
  # @param save_file [String] Path to save file
40
40
  # @param jobs [Integer] Number of parallel downloads
41
41
  # @return [void]
42
- def call(save_file:, jobs: 4, **)
42
+ def call(save_file:, jobs: "4", **)
43
+ jobs = Integer(jobs)
43
44
  # Load save file
44
45
  say "Loading save file: #{save_file}", prefix: :info
45
46
  save_data = SaveFile.load(Pathname(save_file))
@@ -47,7 +48,7 @@ module Factorix
47
48
 
48
49
  # Load current state
49
50
  mod_list = MODList.load
50
- presenter = Progress::Presenter.new(title: "\u{1F50D}\u{FE0E} Scanning MOD(s)", output: $stderr)
51
+ presenter = Progress::Presenter.new(title: "\u{1F50D}\u{FE0E} Scanning MOD(s)", output: err)
51
52
  handler = Progress::ScanHandler.new(presenter)
52
53
  installed_mods = InstalledMOD.all(handler:)
53
54
  graph = Dependency::Graph::Builder.build(installed_mods:, mod_list:)
@@ -109,7 +110,7 @@ module Factorix
109
110
  # @return [Array<Hash>] Installation targets with MOD info and releases
110
111
  private def plan_installation(mods_to_install, graph, jobs)
111
112
  # Create progress presenter for info fetching
112
- presenter = Progress::Presenter.new(title: "\u{1F50D}\u{FE0E} Fetching MOD info", output: $stderr)
113
+ presenter = Progress::Presenter.new(title: "\u{1F50D}\u{FE0E} Fetching MOD info", output: err)
113
114
 
114
115
  # Fetch info for MODs to install
115
116
  target_infos = fetch_target_mod_info(mods_to_install, jobs, presenter)
@@ -45,7 +45,7 @@ module Factorix
45
45
 
46
46
  # Load current state (without validation to allow fixing issues)
47
47
  mod_list = MODList.load
48
- presenter = Progress::Presenter.new(title: "\u{1F50D}\u{FE0E} Scanning MOD(s)", output: $stderr)
48
+ presenter = Progress::Presenter.new(title: "\u{1F50D}\u{FE0E} Scanning MOD(s)", output: err)
49
49
  handler = Progress::ScanHandler.new(presenter)
50
50
  installed_mods = InstalledMOD.all(handler:)
51
51
  graph = Dependency::Graph::Builder.build(installed_mods:, mod_list:)
@@ -32,15 +32,16 @@ module Factorix
32
32
  ]
33
33
 
34
34
  argument :mod_names, type: :array, required: false, desc: "MOD names to update (all if not specified)"
35
- option :jobs, type: :integer, aliases: ["-j"], default: 4, desc: "Number of parallel downloads"
35
+ option :jobs, aliases: ["-j"], default: "4", desc: "Number of parallel downloads"
36
36
 
37
37
  # Execute the update command
38
38
  #
39
39
  # @param mod_names [Array<String>] MOD names to update
40
40
  # @param jobs [Integer] Number of parallel downloads
41
41
  # @return [void]
42
- def call(mod_names: [], jobs: 4, **)
43
- presenter = Progress::Presenter.new(title: "\u{1F50D}\u{FE0E} Scanning MOD(s)", output: $stderr)
42
+ def call(mod_names: [], jobs: "4", **)
43
+ jobs = Integer(jobs)
44
+ presenter = Progress::Presenter.new(title: "\u{1F50D}\u{FE0E} Scanning MOD(s)", output: err)
44
45
  handler = Progress::ScanHandler.new(presenter)
45
46
  installed_mods = InstalledMOD.all(handler:)
46
47
  mod_list = MODList.load
@@ -98,7 +99,7 @@ module Factorix
98
99
  # @param jobs [Integer] Number of parallel jobs
99
100
  # @return [Array<Hash>] Update targets with current and latest versions
100
101
  private def find_update_targets(target_mods, installed_mods, jobs)
101
- presenter = Progress::Presenter.new(title: "\u{1F50D}\u{FE0E} Checking for updates", output: $stderr)
102
+ presenter = Progress::Presenter.new(title: "\u{1F50D}\u{FE0E} Checking for updates", output: err)
102
103
  presenter.start(total: target_mods.size)
103
104
 
104
105
  pool = Concurrent::FixedThreadPool.new(jobs)
@@ -189,13 +190,13 @@ module Factorix
189
190
  # @param jobs [Integer] Number of parallel jobs
190
191
  # @return [void]
191
192
  private def download_mods(targets, jobs)
192
- multi_presenter = Progress::MultiPresenter.new(title: "\u{1F4E5}\u{FE0E} Downloads")
193
+ multi_presenter = Progress::MultiPresenter.new(title: "\u{1F4E5}\u{FE0E} Downloads", output: err)
193
194
 
194
195
  pool = Concurrent::FixedThreadPool.new(jobs)
195
196
 
196
197
  futures = targets.map {|target|
197
198
  Concurrent::Future.execute(executor: pool) do
198
- thread_portal = Application[:portal]
199
+ thread_portal = Container[:portal]
199
200
  thread_downloader = thread_portal.mod_download_api.downloader
200
201
 
201
202
  presenter = multi_presenter.register(
@@ -18,11 +18,11 @@ module Factorix
18
18
  "my-mod_1.0.0.zip --category automation # Upload with category"
19
19
  ]
20
20
 
21
- argument :file, type: :string, required: true, desc: "Path to MOD zip file"
22
- option :description, type: :string, desc: "Markdown description"
23
- option :category, type: :string, desc: "MOD category"
24
- option :license, type: :string, desc: "License identifier"
25
- option :source_url, type: :string, desc: "Repository URL"
21
+ argument :file, required: true, desc: "Path to MOD zip file"
22
+ option :description, desc: "Markdown description"
23
+ option :category, desc: "MOD category"
24
+ option :license, desc: "License identifier"
25
+ option :source_url, desc: "Repository URL"
26
26
 
27
27
  # Execute the upload command
28
28
  #
@@ -44,7 +44,7 @@ module Factorix
44
44
  mod_name = extract_mod_name(file_path)
45
45
  metadata = build_metadata(description:, category:, license:, source_url:)
46
46
 
47
- presenter = Progress::Presenter.new(title: "\u{1F4E4} Uploading #{file_path.basename}", output: $stderr)
47
+ presenter = Progress::Presenter.new(title: "\u{1F4E4} Uploading #{file_path.basename}", output: err)
48
48
 
49
49
  uploader = portal.mod_management_api.uploader
50
50
  handler = Progress::UploadHandler.new(presenter)
@@ -61,7 +61,7 @@ module Factorix
61
61
  result = PATH_TYPES.transform_values {|method_name| runtime.public_send(method_name).to_s }
62
62
 
63
63
  if json
64
- puts JSON.pretty_generate(result)
64
+ out.puts JSON.pretty_generate(result)
65
65
  else
66
66
  output_table(result)
67
67
  end
@@ -70,7 +70,7 @@ module Factorix
70
70
  private def output_table(result)
71
71
  key_width = result.keys.map(&:length).max
72
72
  result.each do |key, value|
73
- puts "%-#{key_width}s %s" % [key, value]
73
+ out.puts "%-#{key_width}s %s" % [key, value]
74
74
  end
75
75
  end
76
76
  end
@@ -18,7 +18,7 @@ module Factorix
18
18
  # Outputs the current version of the Factorix gem to stdout.
19
19
  #
20
20
  # @return [void]
21
- def call(**) = puts VERSION
21
+ def call(**) = out.puts VERSION
22
22
  end
23
23
  end
24
24
  end
@@ -1,26 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "dry/configurable"
4
3
  require "dry/core"
5
4
  require "dry/logger"
6
5
 
7
6
  module Factorix
8
- # Application container and configuration
7
+ # DI container for dependency injection
9
8
  #
10
- # Provides dependency injection container and configuration management
11
- # using dry-core's Container and dry-configurable.
12
- #
13
- # @example Configure the application
14
- # Factorix::Application.configure do |config|
15
- # config.log_level = :debug
16
- # config.http.connect_timeout = 10
17
- # end
9
+ # Provides dependency injection container using dry-core's Container.
18
10
  #
19
11
  # @example Resolve dependencies
20
- # runtime = Factorix::Application[:runtime]
21
- class Application
12
+ # runtime = Factorix::Container[:runtime]
13
+ class Container
22
14
  extend Dry::Core::Container::Mixin
23
- extend Dry::Configurable
24
15
 
25
16
  # Some items are registered with memoize: false to support independent event handlers
26
17
  # for each parallel download task (e.g., progress tracking).
@@ -46,7 +37,7 @@ module Factorix
46
37
  # Dispatcher level set to DEBUG to allow all messages through
47
38
  # Backend controls filtering based on --log-level option
48
39
  Dry.Logger(:factorix, level: :debug) do |dispatcher|
49
- dispatcher.add_backend(level: config.log_level, stream: log_path.to_s, template: "[%<time>s] %<severity>s: %<message>s %<payload>s")
40
+ dispatcher.add_backend(level: Factorix.config.log_level, stream: log_path.to_s, template: "[%<time>s] %<severity>s: %<message>s %<payload>s")
50
41
  end
51
42
  end
52
43
 
@@ -57,19 +48,19 @@ module Factorix
57
48
 
58
49
  # Register download cache
59
50
  register(:download_cache, memoize: true) do
60
- c = config.cache.download
51
+ c = Factorix.config.cache.download
61
52
  Cache::FileSystem.new(c.dir, **c.to_h.except(:dir))
62
53
  end
63
54
 
64
55
  # Register API cache (with compression for JSON responses)
65
56
  register(:api_cache, memoize: true) do
66
- c = config.cache.api
57
+ c = Factorix.config.cache.api
67
58
  Cache::FileSystem.new(c.dir, **c.to_h.except(:dir))
68
59
  end
69
60
 
70
61
  # Register info.json cache (for MOD metadata from ZIP files)
71
62
  register(:info_json_cache, memoize: true) do
72
- c = config.cache.info_json
63
+ c = Factorix.config.cache.info_json
73
64
  Cache::FileSystem.new(c.dir, **c.to_h.except(:dir))
74
65
  end
75
66
 
@@ -146,73 +137,5 @@ module Factorix
146
137
  register(:portal, memoize: false) do
147
138
  Portal.new
148
139
  end
149
-
150
- # Log level (:debug, :info, :warn, :error, :fatal)
151
- setting :log_level, default: :info
152
-
153
- # Runtime settings (optional overrides for auto-detection)
154
- setting :runtime do
155
- setting :executable_path, constructor: ->(v) { v ? Pathname(v) : nil }
156
- setting :user_dir, constructor: ->(v) { v ? Pathname(v) : nil }
157
- setting :data_dir, constructor: ->(v) { v ? Pathname(v) : nil }
158
- end
159
-
160
- # HTTP timeout settings
161
- setting :http do
162
- setting :connect_timeout, default: 5
163
- setting :read_timeout, default: 30
164
- setting :write_timeout, default: 30
165
- end
166
-
167
- # Cache settings
168
- setting :cache do
169
- # Download cache settings (for MOD files)
170
- setting :download do
171
- setting :dir, constructor: ->(value) { Pathname(value) }
172
- setting :ttl, default: nil # nil for unlimited (MOD files are immutable)
173
- setting :max_file_size, default: nil # nil for unlimited
174
- setting :compression_threshold, default: nil # nil for no compression (binary files)
175
- end
176
-
177
- # API cache settings (for API responses)
178
- setting :api do
179
- setting :dir, constructor: ->(value) { Pathname(value) }
180
- setting :ttl, default: 3600 # 1 hour (API responses may change)
181
- setting :max_file_size, default: 10 * 1024 * 1024 # 10MiB (JSON responses)
182
- setting :compression_threshold, default: 0 # always compress (JSON is highly compressible)
183
- end
184
-
185
- # info.json cache settings (for MOD metadata from ZIP files)
186
- setting :info_json do
187
- setting :dir, constructor: ->(value) { Pathname(value) }
188
- setting :ttl, default: nil # nil for unlimited (info.json is immutable within a MOD ZIP)
189
- setting :max_file_size, default: nil # nil for unlimited (info.json is small)
190
- setting :compression_threshold, default: 0 # always compress (JSON is highly compressible)
191
- end
192
- end
193
-
194
- # Load configuration from file
195
- #
196
- # @param path [Pathname, String, nil] configuration file path
197
- # @return [void]
198
- # @raise [ConfigurationError] if explicitly specified path does not exist
199
- def self.load_config(path=nil)
200
- if path
201
- # Explicitly specified path must exist
202
- config_path = Pathname(path)
203
- raise ConfigurationError, "Configuration file not found: #{config_path}" unless config_path.exist?
204
- else
205
- # Default path is optional
206
- config_path = resolve(:runtime).factorix_config_path
207
- return unless config_path.exist?
208
- end
209
-
210
- instance_eval(config_path.read, config_path.to_s)
211
- end
212
-
213
- runtime = resolve(:runtime)
214
- config.cache.download.dir = runtime.factorix_cache_dir / "download"
215
- config.cache.api.dir = runtime.factorix_cache_dir / "api"
216
- config.cache.info_json.dir = runtime.factorix_cache_dir / "info_json"
217
140
  end
218
141
  end
@@ -128,7 +128,7 @@ module Factorix
128
128
  MODVersionRequirement[operator:, version:]
129
129
  rescue VersionParseError => e
130
130
  # Skip version requirements with out-of-range version components
131
- Application[:logger].warn("Skipping version requirement '#{version_string}': #{e.message}")
131
+ Container[:logger].warn("Skipping version requirement '#{version_string}': #{e.message}")
132
132
  nil
133
133
  end
134
134
 
@@ -162,9 +162,9 @@ module Factorix
162
162
  Net::HTTP.new(uri.host, uri.port).tap do |http|
163
163
  http.use_ssl = uri.scheme == "https"
164
164
  http.verify_mode = OpenSSL::SSL::VERIFY_PEER
165
- http.open_timeout = Application.config.http.connect_timeout
166
- http.read_timeout = Application.config.http.read_timeout
167
- http.write_timeout = Application.config.http.write_timeout if http.respond_to?(:write_timeout=)
165
+ http.open_timeout = Factorix.config.http.connect_timeout
166
+ http.read_timeout = Factorix.config.http.read_timeout
167
+ http.write_timeout = Factorix.config.http.write_timeout if http.respond_to?(:write_timeout=)
168
168
  end
169
169
  end
170
170
 
@@ -47,8 +47,8 @@ module Factorix
47
47
  # @return [InfoJSON] parsed info.json from zip
48
48
  # @raise [FileFormatError] if zip is invalid or info.json not found
49
49
  def self.from_zip(zip_path)
50
- cache = Application.resolve(:info_json_cache)
51
- logger = Application.resolve(:logger)
50
+ cache = Container.resolve(:info_json_cache)
51
+ logger = Container.resolve(:logger)
52
52
  cache_key = cache.key_for(zip_path.to_s)
53
53
 
54
54
  if (cached_json = cache.read(cache_key, encoding: Encoding::UTF_8))
@@ -18,7 +18,7 @@ module Factorix
18
18
  # @param path [Pathname] the path to the file to load the MOD list from (default: runtime.mod_list_path)
19
19
  # @return [Factorix::MODList] the loaded MOD list
20
20
  # @raise [MODSettingsError] if the base MOD is disabled
21
- def self.load(path=Application[:runtime].mod_list_path)
21
+ def self.load(path=Container[:runtime].mod_list_path)
22
22
  raw_data = JSON.parse(path.read, symbolize_names: true)
23
23
  mods_hash = raw_data[:mods].to_h {|entry|
24
24
  mod = MOD[name: entry[:name]]
@@ -50,7 +50,7 @@ module Factorix
50
50
  #
51
51
  # @param path [Pathname] the path to the file to save the MOD list to (default: runtime.mod_list_path)
52
52
  # @return [void]
53
- def save(path=Application[:runtime].mod_list_path)
53
+ def save(path=Container[:runtime].mod_list_path)
54
54
  mods_data = @mods.map {|mod, state|
55
55
  data = {name: mod.name, enabled: state.enabled?}
56
56
  # Only include version in the output if it exists
@@ -108,7 +108,7 @@ module Factorix
108
108
  #
109
109
  # @param path [Pathname] Path to the MOD settings file (default: runtime.mod_settings_path)
110
110
  # @return [MODSettings] New MODSettings instance
111
- def self.load(path=Application[:runtime].mod_settings_path)
111
+ def self.load(path=Container[:runtime].mod_settings_path)
112
112
  path.open("rb") do |io|
113
113
  game_version, sections = load_settings_from_io(io)
114
114
  new(game_version, sections)
@@ -244,7 +244,7 @@ module Factorix
244
244
  #
245
245
  # @param path [Pathname] Path to save the MOD settings file (default: runtime.mod_settings_path)
246
246
  # @return [void]
247
- def save(path=Application[:runtime].mod_settings_path)
247
+ def save(path=Container[:runtime].mod_settings_path)
248
248
  path.open("wb") do |file|
249
249
  serializer = SerDes::Serializer.new(file)
250
250
 
@@ -8,10 +8,10 @@ module Factorix
8
8
  # auto-detected paths via configuration. When a configured path is available,
9
9
  # it is used instead of platform-specific auto-detection.
10
10
  #
11
- # Configuration is done via Application.config:
11
+ # Configuration is done via Factorix.config:
12
12
  #
13
13
  # @example Configure paths in config file
14
- # Factorix::Application.configure do |config|
14
+ # Factorix.configure do |config|
15
15
  # config.runtime.executable_path = "/opt/factorio/bin/x64/factorio"
16
16
  # config.runtime.user_dir = "/home/user/.factorio"
17
17
  # end
@@ -46,20 +46,20 @@ module Factorix
46
46
  def data_dir = configurable_path(:data_dir, example_path: "/path/to/factorio/data") { super }
47
47
 
48
48
  private def configurable_path(name, example_path:)
49
- if (configured = Application.config.runtime.public_send(name))
50
- Application[:logger].debug("Using configured #{name}", path: configured.to_s)
49
+ if (configured = Factorix.config.runtime.public_send(name))
50
+ Container[:logger].debug("Using configured #{name}", path: configured.to_s)
51
51
  configured
52
52
  else
53
- Application[:logger].debug("No configuration for #{name}, using auto-detection")
54
- yield.tap {|path| Application[:logger].debug("Auto-detected #{name}", path: path.to_s) }
53
+ Container[:logger].debug("No configuration for #{name}, using auto-detection")
54
+ yield.tap {|path| Container[:logger].debug("Auto-detected #{name}", path: path.to_s) }
55
55
  end
56
56
  rescue NotImplementedError => e
57
- Application[:logger].error("Auto-detection failed and no configuration provided", error: e.message)
57
+ Container[:logger].error("Auto-detection failed and no configuration provided", error: e.message)
58
58
  raise ConfigurationError, <<~MESSAGE
59
59
  #{name} not configured and auto-detection is not supported for this platform.
60
- Please configure it in #{Application[:runtime].factorix_config_path}:
60
+ Please configure it in #{Container[:runtime].factorix_config_path}:
61
61
 
62
- Factorix::Application.configure do |config|
62
+ Factorix.configure do |config|
63
63
  config.runtime.#{name} = "#{example_path}"
64
64
  end
65
65
  MESSAGE
@@ -39,7 +39,7 @@ module Factorix
39
39
  elsif username_env || token_env
40
40
  raise CredentialError, "Both #{ENV_USERNAME} and #{ENV_TOKEN} must be set (or neither)"
41
41
  else
42
- runtime = Application[:runtime]
42
+ runtime = Container[:runtime]
43
43
  from_player_data(runtime:)
44
44
  end
45
45
  end
@@ -49,7 +49,7 @@ module Factorix
49
49
  # @return [ServiceCredential] new instance with credentials from environment
50
50
  # @raise [CredentialError] if username or token is not set or empty
51
51
  def self.from_env
52
- logger = Application["logger"]
52
+ logger = Container["logger"]
53
53
  logger.debug "Loading service credentials from environment"
54
54
 
55
55
  username = ENV.fetch(ENV_USERNAME, nil)
@@ -83,7 +83,7 @@ module Factorix
83
83
  # @raise [Errno::ENOENT] if player-data.json does not exist
84
84
  # @raise [CredentialError] if username or token is missing in player-data.json
85
85
  def self.from_player_data(runtime:)
86
- logger = Application["logger"]
86
+ logger = Container["logger"]
87
87
  logger.debug "Loading service credentials from player-data.json"
88
88
 
89
89
  player_data_path = runtime.player_data_path
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Factorix
4
- VERSION = "0.5.1"
4
+ VERSION = "0.6.0"
5
5
  public_constant :VERSION
6
6
  end