factorix 0.5.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 +20 -0
- data/LICENSE.txt +21 -0
- data/README.md +105 -0
- data/completion/_factorix.bash +202 -0
- data/completion/_factorix.fish +197 -0
- data/completion/_factorix.zsh +376 -0
- data/doc/factorix.1 +377 -0
- data/exe/factorix +20 -0
- data/lib/factorix/api/category.rb +69 -0
- data/lib/factorix/api/image.rb +35 -0
- data/lib/factorix/api/license.rb +71 -0
- data/lib/factorix/api/mod_download_api.rb +66 -0
- data/lib/factorix/api/mod_info.rb +166 -0
- data/lib/factorix/api/mod_management_api.rb +237 -0
- data/lib/factorix/api/mod_portal_api.rb +204 -0
- data/lib/factorix/api/release.rb +49 -0
- data/lib/factorix/api/tag.rb +95 -0
- data/lib/factorix/api.rb +7 -0
- data/lib/factorix/api_credential.rb +54 -0
- data/lib/factorix/application.rb +218 -0
- data/lib/factorix/cache/file_system.rb +307 -0
- data/lib/factorix/cli/commands/backup_support.rb +46 -0
- data/lib/factorix/cli/commands/base.rb +90 -0
- data/lib/factorix/cli/commands/cache/evict.rb +180 -0
- data/lib/factorix/cli/commands/cache/stat.rb +201 -0
- data/lib/factorix/cli/commands/command_wrapper.rb +71 -0
- data/lib/factorix/cli/commands/completion.rb +83 -0
- data/lib/factorix/cli/commands/confirmable.rb +53 -0
- data/lib/factorix/cli/commands/download_support.rb +123 -0
- data/lib/factorix/cli/commands/launch.rb +79 -0
- data/lib/factorix/cli/commands/man.rb +29 -0
- data/lib/factorix/cli/commands/mod/check.rb +99 -0
- data/lib/factorix/cli/commands/mod/disable.rb +188 -0
- data/lib/factorix/cli/commands/mod/download.rb +291 -0
- data/lib/factorix/cli/commands/mod/edit.rb +114 -0
- data/lib/factorix/cli/commands/mod/enable.rb +216 -0
- data/lib/factorix/cli/commands/mod/image/add.rb +47 -0
- data/lib/factorix/cli/commands/mod/image/edit.rb +41 -0
- data/lib/factorix/cli/commands/mod/image/list.rb +74 -0
- data/lib/factorix/cli/commands/mod/install.rb +443 -0
- data/lib/factorix/cli/commands/mod/list.rb +372 -0
- data/lib/factorix/cli/commands/mod/search.rb +134 -0
- data/lib/factorix/cli/commands/mod/settings/dump.rb +88 -0
- data/lib/factorix/cli/commands/mod/settings/restore.rb +101 -0
- data/lib/factorix/cli/commands/mod/show.rb +202 -0
- data/lib/factorix/cli/commands/mod/sync.rb +299 -0
- data/lib/factorix/cli/commands/mod/uninstall.rb +325 -0
- data/lib/factorix/cli/commands/mod/update.rb +222 -0
- data/lib/factorix/cli/commands/mod/upload.rb +90 -0
- data/lib/factorix/cli/commands/path.rb +79 -0
- data/lib/factorix/cli/commands/requires_game_stopped.rb +32 -0
- data/lib/factorix/cli/commands/version.rb +25 -0
- data/lib/factorix/cli.rb +42 -0
- data/lib/factorix/dependency/edge.rb +89 -0
- data/lib/factorix/dependency/entry.rb +124 -0
- data/lib/factorix/dependency/graph/builder.rb +108 -0
- data/lib/factorix/dependency/graph.rb +210 -0
- data/lib/factorix/dependency/list.rb +244 -0
- data/lib/factorix/dependency/mod_version_requirement.rb +73 -0
- data/lib/factorix/dependency/node.rb +60 -0
- data/lib/factorix/dependency/parser.rb +148 -0
- data/lib/factorix/dependency/validation_result.rb +138 -0
- data/lib/factorix/dependency/validator.rb +190 -0
- data/lib/factorix/errors.rb +112 -0
- data/lib/factorix/formatting.rb +56 -0
- data/lib/factorix/game_version.rb +98 -0
- data/lib/factorix/http/cache_decorator.rb +106 -0
- data/lib/factorix/http/cached_response.rb +37 -0
- data/lib/factorix/http/client.rb +187 -0
- data/lib/factorix/http/response.rb +31 -0
- data/lib/factorix/http/retry_decorator.rb +59 -0
- data/lib/factorix/http/retry_strategy.rb +80 -0
- data/lib/factorix/info_json.rb +90 -0
- data/lib/factorix/installed_mod.rb +239 -0
- data/lib/factorix/mod.rb +55 -0
- data/lib/factorix/mod_list.rb +174 -0
- data/lib/factorix/mod_settings.rb +278 -0
- data/lib/factorix/mod_state.rb +34 -0
- data/lib/factorix/mod_version.rb +99 -0
- data/lib/factorix/portal.rb +185 -0
- data/lib/factorix/progress/download_handler.rb +46 -0
- data/lib/factorix/progress/multi_presenter.rb +45 -0
- data/lib/factorix/progress/presenter.rb +67 -0
- data/lib/factorix/progress/presenter_adapter.rb +46 -0
- data/lib/factorix/progress/scan_handler.rb +33 -0
- data/lib/factorix/progress/upload_handler.rb +33 -0
- data/lib/factorix/runtime/base.rb +233 -0
- data/lib/factorix/runtime/linux.rb +32 -0
- data/lib/factorix/runtime/mac_os.rb +53 -0
- data/lib/factorix/runtime/user_configurable.rb +69 -0
- data/lib/factorix/runtime/windows.rb +85 -0
- data/lib/factorix/runtime/wsl.rb +118 -0
- data/lib/factorix/runtime.rb +32 -0
- data/lib/factorix/save_file.rb +178 -0
- data/lib/factorix/ser_des/deserializer.rb +198 -0
- data/lib/factorix/ser_des/serializer.rb +231 -0
- data/lib/factorix/ser_des/signed_integer.rb +63 -0
- data/lib/factorix/ser_des/unsigned_integer.rb +65 -0
- data/lib/factorix/service_credential.rb +127 -0
- data/lib/factorix/transfer/downloader.rb +162 -0
- data/lib/factorix/transfer/uploader.rb +232 -0
- data/lib/factorix/version.rb +6 -0
- data/lib/factorix.rb +38 -0
- data/sig/dry/auto_inject.rbs +15 -0
- data/sig/dry/cli.rbs +19 -0
- data/sig/dry/configurable.rbs +13 -0
- data/sig/dry/core/container.rbs +17 -0
- data/sig/dry/events/publisher.rbs +22 -0
- data/sig/dry/logger.rbs +16 -0
- data/sig/factorix/api/category.rbs +15 -0
- data/sig/factorix/api/image.rbs +15 -0
- data/sig/factorix/api/license.rbs +20 -0
- data/sig/factorix/api/mod_download_api.rbs +18 -0
- data/sig/factorix/api/mod_info.rbs +67 -0
- data/sig/factorix/api/mod_management_api.rbs +25 -0
- data/sig/factorix/api/mod_portal_api.rbs +31 -0
- data/sig/factorix/api/release.rbs +27 -0
- data/sig/factorix/api/tag.rbs +15 -0
- data/sig/factorix/api.rbs +8 -0
- data/sig/factorix/api_credential.rbs +17 -0
- data/sig/factorix/application.rbs +86 -0
- data/sig/factorix/cache/file_system.rbs +35 -0
- data/sig/factorix/cli/commands/base.rbs +13 -0
- data/sig/factorix/cli/commands/cache/evict.rbs +17 -0
- data/sig/factorix/cli/commands/cache/stat.rbs +17 -0
- data/sig/factorix/cli/commands/command_wrapper.rbs +13 -0
- data/sig/factorix/cli/commands/completion/zsh.rbs +15 -0
- data/sig/factorix/cli/commands/confirmable.rbs +12 -0
- data/sig/factorix/cli/commands/download_support.rbs +12 -0
- data/sig/factorix/cli/commands/launch.rbs +15 -0
- data/sig/factorix/cli/commands/mod/check.rbs +18 -0
- data/sig/factorix/cli/commands/mod/disable.rbs +20 -0
- data/sig/factorix/cli/commands/mod/download.rbs +18 -0
- data/sig/factorix/cli/commands/mod/edit.rbs +30 -0
- data/sig/factorix/cli/commands/mod/enable.rbs +20 -0
- data/sig/factorix/cli/commands/mod/image/add.rbs +19 -0
- data/sig/factorix/cli/commands/mod/image/edit.rbs +19 -0
- data/sig/factorix/cli/commands/mod/image/list.rbs +19 -0
- data/sig/factorix/cli/commands/mod/install.rbs +19 -0
- data/sig/factorix/cli/commands/mod/list.rbs +30 -0
- data/sig/factorix/cli/commands/mod/search.rbs +18 -0
- data/sig/factorix/cli/commands/mod/settings/dump.rbs +17 -0
- data/sig/factorix/cli/commands/mod/settings/restore.rbs +17 -0
- data/sig/factorix/cli/commands/mod/sync.rbs +19 -0
- data/sig/factorix/cli/commands/mod/uninstall.rbs +20 -0
- data/sig/factorix/cli/commands/mod/update.rbs +19 -0
- data/sig/factorix/cli/commands/mod/upload.rbs +24 -0
- data/sig/factorix/cli/commands/path.rbs +18 -0
- data/sig/factorix/cli/commands/requires_game_stopped.rbs +13 -0
- data/sig/factorix/cli/commands/version.rbs +13 -0
- data/sig/factorix/cli.rbs +11 -0
- data/sig/factorix/dependency/edge.rbs +32 -0
- data/sig/factorix/dependency/entry.rbs +30 -0
- data/sig/factorix/dependency/graph/builder.rbs +17 -0
- data/sig/factorix/dependency/graph.rbs +39 -0
- data/sig/factorix/dependency/list.rbs +69 -0
- data/sig/factorix/dependency/mod_version_requirement.rbs +18 -0
- data/sig/factorix/dependency/node.rbs +24 -0
- data/sig/factorix/dependency/parser.rbs +11 -0
- data/sig/factorix/dependency/validation_result.rbs +56 -0
- data/sig/factorix/dependency/validator.rbs +13 -0
- data/sig/factorix/errors.rbs +132 -0
- data/sig/factorix/formatting.rbs +8 -0
- data/sig/factorix/game_version.rbs +24 -0
- data/sig/factorix/http/cache_decorator.rbs +64 -0
- data/sig/factorix/http/client.rbs +55 -0
- data/sig/factorix/http/response.rbs +28 -0
- data/sig/factorix/http/retry_decorator.rbs +44 -0
- data/sig/factorix/http/retry_strategy.rbs +42 -0
- data/sig/factorix/info_json.rbs +19 -0
- data/sig/factorix/installed_mod.rbs +34 -0
- data/sig/factorix/mod.rbs +20 -0
- data/sig/factorix/mod_list.rbs +44 -0
- data/sig/factorix/mod_settings.rbs +47 -0
- data/sig/factorix/mod_state.rbs +18 -0
- data/sig/factorix/mod_version.rbs +23 -0
- data/sig/factorix/portal.rbs +37 -0
- data/sig/factorix/progress/download_handler.rbs +19 -0
- data/sig/factorix/progress/multi_presenter.rbs +15 -0
- data/sig/factorix/progress/presenter.rbs +17 -0
- data/sig/factorix/progress/presenter_adapter.rbs +17 -0
- data/sig/factorix/progress/scan_handler.rbs +16 -0
- data/sig/factorix/progress/upload_handler.rbs +17 -0
- data/sig/factorix/runtime/base.rbs +45 -0
- data/sig/factorix/runtime/linux.rbs +15 -0
- data/sig/factorix/runtime/mac_os.rbs +15 -0
- data/sig/factorix/runtime/user_configurable.rbs +13 -0
- data/sig/factorix/runtime/windows.rbs +23 -0
- data/sig/factorix/runtime/wsl.rbs +19 -0
- data/sig/factorix/runtime.rbs +9 -0
- data/sig/factorix/save_file.rbs +40 -0
- data/sig/factorix/ser_des/deserializer.rbs +49 -0
- data/sig/factorix/ser_des/serializer.rbs +45 -0
- data/sig/factorix/ser_des/signed_integer.rbs +37 -0
- data/sig/factorix/ser_des/unsigned_integer.rbs +37 -0
- data/sig/factorix/service_credential.rbs +19 -0
- data/sig/factorix/transfer/downloader.rbs +15 -0
- data/sig/factorix/transfer/uploader.rbs +21 -0
- data/sig/factorix.rbs +9 -0
- data/sig/tty/progressbar.rbs +18 -0
- metadata +431 -0
data/doc/factorix.1
ADDED
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
.\" Generated by Claude Code
|
|
2
|
+
.TH FACTORIX 1 "November 2025" "Factorix 0.1.0" "User Commands"
|
|
3
|
+
.SH NAME
|
|
4
|
+
factorix \- Factorio MOD manager CLI tool
|
|
5
|
+
.SH SYNOPSIS
|
|
6
|
+
.B factorix
|
|
7
|
+
.RI [ command ]
|
|
8
|
+
.RI [ subcommand ]
|
|
9
|
+
.RI [ options ]
|
|
10
|
+
.RI [ arguments ]
|
|
11
|
+
.SH DESCRIPTION
|
|
12
|
+
.B factorix
|
|
13
|
+
is a command-line tool for managing Factorio MODs. It provides functionality
|
|
14
|
+
for discovering, installing, updating, and managing MODs from the Factorio
|
|
15
|
+
MOD Portal, as well as managing MOD settings and game launch.
|
|
16
|
+
.SH GLOBAL OPTIONS
|
|
17
|
+
The following options are available for all commands:
|
|
18
|
+
.TP
|
|
19
|
+
.BR \-c ", " \-\-config\-path =\fIVALUE\fR
|
|
20
|
+
Path to configuration file.
|
|
21
|
+
.TP
|
|
22
|
+
.BR \-\-log\-level =\fIVALUE\fR
|
|
23
|
+
Set log level: debug, info, warn, error, fatal.
|
|
24
|
+
.TP
|
|
25
|
+
.BR \-q ", " \-\-quiet
|
|
26
|
+
Suppress non-essential output.
|
|
27
|
+
.TP
|
|
28
|
+
.BR \-h ", " \-\-help
|
|
29
|
+
Print help information.
|
|
30
|
+
.SH COMMANDS
|
|
31
|
+
.SS factorix version
|
|
32
|
+
Display Factorix version.
|
|
33
|
+
.SS factorix man
|
|
34
|
+
Display this manual page using the system's man command.
|
|
35
|
+
.SS factorix path
|
|
36
|
+
Display Factorio and Factorix paths.
|
|
37
|
+
.TP
|
|
38
|
+
.B \-\-json
|
|
39
|
+
Output in JSON format.
|
|
40
|
+
.SS factorix launch
|
|
41
|
+
Launch Factorio game.
|
|
42
|
+
.TP
|
|
43
|
+
.BR \-w ", " \-\-wait
|
|
44
|
+
Wait for the game to finish.
|
|
45
|
+
.PP
|
|
46
|
+
Arguments after
|
|
47
|
+
.B \-\-
|
|
48
|
+
are passed directly to Factorio.
|
|
49
|
+
.SS factorix completion [SHELL]
|
|
50
|
+
Generate shell completion script. Output should be evaluated to enable completion.
|
|
51
|
+
.TP
|
|
52
|
+
.B SHELL
|
|
53
|
+
Shell type: zsh, bash, fish. If omitted, detects from SHELL environment variable.
|
|
54
|
+
.PP
|
|
55
|
+
.RS
|
|
56
|
+
eval "$(factorix completion)" # auto-detect
|
|
57
|
+
.br
|
|
58
|
+
eval "$(factorix completion zsh)" # zsh
|
|
59
|
+
.br
|
|
60
|
+
eval "$(factorix completion bash)" # bash
|
|
61
|
+
.br
|
|
62
|
+
factorix completion fish | source # fish
|
|
63
|
+
.RE
|
|
64
|
+
.SS factorix cache stat
|
|
65
|
+
Display cache statistics.
|
|
66
|
+
.TP
|
|
67
|
+
.B \-\-json
|
|
68
|
+
Output in JSON format.
|
|
69
|
+
.SS factorix cache evict [CACHES]
|
|
70
|
+
Evict cache entries. CACHES can be: download, api, info_json.
|
|
71
|
+
.TP
|
|
72
|
+
.B \-\-all
|
|
73
|
+
Remove all entries.
|
|
74
|
+
.TP
|
|
75
|
+
.B \-\-expired
|
|
76
|
+
Remove expired entries only.
|
|
77
|
+
.TP
|
|
78
|
+
.BR \-\-older\-than =\fIAGE\fR
|
|
79
|
+
Remove entries older than AGE (e.g., 30s, 5m, 2h, 7d).
|
|
80
|
+
.SH MOD COMMANDS
|
|
81
|
+
.SS factorix mod list
|
|
82
|
+
List installed MOD(s).
|
|
83
|
+
.TP
|
|
84
|
+
.B \-\-enabled
|
|
85
|
+
Show only enabled MOD(s).
|
|
86
|
+
.TP
|
|
87
|
+
.B \-\-disabled
|
|
88
|
+
Show only disabled MOD(s).
|
|
89
|
+
.TP
|
|
90
|
+
.B \-\-errors
|
|
91
|
+
Show only MOD(s) with dependency errors.
|
|
92
|
+
.TP
|
|
93
|
+
.B \-\-outdated
|
|
94
|
+
Show only MOD(s) with available updates.
|
|
95
|
+
.TP
|
|
96
|
+
.B \-\-json
|
|
97
|
+
Output in JSON format.
|
|
98
|
+
.SS factorix mod search [MOD_NAMES]
|
|
99
|
+
Search MOD(s) on Factorio MOD Portal.
|
|
100
|
+
.TP
|
|
101
|
+
.BR \-\-[no\-]hide\-deprecated
|
|
102
|
+
Hide deprecated MOD(s) (default: true).
|
|
103
|
+
.TP
|
|
104
|
+
.BR \-\-page =\fIVALUE\fR
|
|
105
|
+
Page number (default: 1).
|
|
106
|
+
.TP
|
|
107
|
+
.BR \-\-page\-size =\fIVALUE\fR
|
|
108
|
+
Results per page (max 500, default: 25).
|
|
109
|
+
.TP
|
|
110
|
+
.BR \-\-sort =\fIVALUE\fR
|
|
111
|
+
Sort field: name, created_at, updated_at.
|
|
112
|
+
.TP
|
|
113
|
+
.BR \-\-sort\-order =\fIVALUE\fR
|
|
114
|
+
Sort order: asc, desc.
|
|
115
|
+
.TP
|
|
116
|
+
.BR \-\-version =\fIVALUE\fR
|
|
117
|
+
Filter by Factorio version.
|
|
118
|
+
.TP
|
|
119
|
+
.B \-\-json
|
|
120
|
+
Output in JSON format.
|
|
121
|
+
.SS factorix mod show MOD_NAME
|
|
122
|
+
Show MOD details from Factorio MOD Portal.
|
|
123
|
+
.PP
|
|
124
|
+
Displays title, summary, version, author, category, license, Factorio version,
|
|
125
|
+
downloads count, links (portal, source, homepage), dependencies, and
|
|
126
|
+
incompatibilities. Shows installation status if the MOD is locally installed.
|
|
127
|
+
.SS factorix mod install MOD_SPECS
|
|
128
|
+
Install MOD(s) from Factorio MOD Portal. Downloads to MOD directory and enables.
|
|
129
|
+
.PP
|
|
130
|
+
MOD_SPECS format: name, name@version, or name@latest.
|
|
131
|
+
.TP
|
|
132
|
+
.BR \-y ", " \-\-yes
|
|
133
|
+
Skip confirmation prompts.
|
|
134
|
+
.TP
|
|
135
|
+
.BR \-j ", " \-\-jobs =\fIVALUE\fR
|
|
136
|
+
Number of parallel downloads (default: 4).
|
|
137
|
+
.SS factorix mod uninstall [MOD_SPECS]
|
|
138
|
+
Uninstall MOD(s) from MOD directory.
|
|
139
|
+
.TP
|
|
140
|
+
.BR \-y ", " \-\-yes
|
|
141
|
+
Skip confirmation prompts.
|
|
142
|
+
.TP
|
|
143
|
+
.B \-\-all
|
|
144
|
+
Uninstall all MOD(s).
|
|
145
|
+
.SS factorix mod update [MOD_NAMES]
|
|
146
|
+
Update MOD(s) to their latest versions. Updates all if no names specified.
|
|
147
|
+
.TP
|
|
148
|
+
.BR \-y ", " \-\-yes
|
|
149
|
+
Skip confirmation prompts.
|
|
150
|
+
.TP
|
|
151
|
+
.BR \-j ", " \-\-jobs =\fIVALUE\fR
|
|
152
|
+
Number of parallel downloads (default: 4).
|
|
153
|
+
.SS factorix mod download MOD_SPECS
|
|
154
|
+
Download MOD files from Factorio MOD Portal without installing.
|
|
155
|
+
.TP
|
|
156
|
+
.BR \-d ", " \-\-directory =\fIVALUE\fR
|
|
157
|
+
Download directory (default: current directory).
|
|
158
|
+
.TP
|
|
159
|
+
.BR \-j ", " \-\-jobs =\fIVALUE\fR
|
|
160
|
+
Number of parallel downloads (default: 4).
|
|
161
|
+
.TP
|
|
162
|
+
.BR \-r ", " \-\-recursive
|
|
163
|
+
Include required dependencies recursively.
|
|
164
|
+
.SS factorix mod enable MOD_NAMES
|
|
165
|
+
Enable MOD(s) in mod-list.json. Recursively enables dependencies.
|
|
166
|
+
.TP
|
|
167
|
+
.BR \-y ", " \-\-yes
|
|
168
|
+
Skip confirmation prompts.
|
|
169
|
+
.SS factorix mod disable [MOD_NAMES]
|
|
170
|
+
Disable MOD(s) in mod-list.json. Recursively disables dependent MOD(s).
|
|
171
|
+
.TP
|
|
172
|
+
.BR \-y ", " \-\-yes
|
|
173
|
+
Skip confirmation prompts.
|
|
174
|
+
.TP
|
|
175
|
+
.B \-\-all
|
|
176
|
+
Disable all MOD(s) except base.
|
|
177
|
+
.SS factorix mod check
|
|
178
|
+
Validate MOD dependencies. Reports missing, disabled, or incompatible dependencies.
|
|
179
|
+
.SS factorix mod sync SAVE_FILE
|
|
180
|
+
Sync MOD states and startup settings from a save file.
|
|
181
|
+
.TP
|
|
182
|
+
.BR \-y ", " \-\-yes
|
|
183
|
+
Skip confirmation prompts.
|
|
184
|
+
.TP
|
|
185
|
+
.BR \-j ", " \-\-jobs =\fIVALUE\fR
|
|
186
|
+
Number of parallel downloads (default: 4).
|
|
187
|
+
.SH MOD PORTAL COMMANDS
|
|
188
|
+
These commands interact with the Factorio MOD Portal and require authentication.
|
|
189
|
+
.SS factorix mod upload FILE
|
|
190
|
+
Upload MOD to Factorio MOD Portal. Handles both new MODs and updates.
|
|
191
|
+
.TP
|
|
192
|
+
.BR \-\-description =\fIVALUE\fR
|
|
193
|
+
Markdown description.
|
|
194
|
+
.TP
|
|
195
|
+
.BR \-\-category =\fIVALUE\fR
|
|
196
|
+
MOD category.
|
|
197
|
+
.TP
|
|
198
|
+
.BR \-\-license =\fIVALUE\fR
|
|
199
|
+
License identifier.
|
|
200
|
+
.TP
|
|
201
|
+
.BR \-\-source\-url =\fIVALUE\fR
|
|
202
|
+
Repository URL.
|
|
203
|
+
.SS factorix mod edit MOD_NAME
|
|
204
|
+
Edit MOD metadata on Factorio MOD Portal.
|
|
205
|
+
.TP
|
|
206
|
+
.BR \-\-title =\fIVALUE\fR
|
|
207
|
+
MOD title.
|
|
208
|
+
.TP
|
|
209
|
+
.BR \-\-summary =\fIVALUE\fR
|
|
210
|
+
Brief description.
|
|
211
|
+
.TP
|
|
212
|
+
.BR \-\-description =\fIVALUE\fR
|
|
213
|
+
Markdown description.
|
|
214
|
+
.TP
|
|
215
|
+
.BR \-\-category =\fIVALUE\fR
|
|
216
|
+
MOD category.
|
|
217
|
+
.TP
|
|
218
|
+
.BR \-\-tags =\fIVALUE1,VALUE2,..\fR
|
|
219
|
+
Array of tags.
|
|
220
|
+
.TP
|
|
221
|
+
.BR \-\-license =\fIVALUE\fR
|
|
222
|
+
License identifier.
|
|
223
|
+
.TP
|
|
224
|
+
.BR \-\-homepage =\fIVALUE\fR
|
|
225
|
+
Homepage URL.
|
|
226
|
+
.TP
|
|
227
|
+
.BR \-\-source\-url =\fIVALUE\fR
|
|
228
|
+
Repository URL.
|
|
229
|
+
.TP
|
|
230
|
+
.BR \-\-faq =\fIVALUE\fR
|
|
231
|
+
FAQ text.
|
|
232
|
+
.TP
|
|
233
|
+
.BR \-\-[no\-]deprecated
|
|
234
|
+
Deprecation flag.
|
|
235
|
+
.SS factorix mod image list MOD_NAME
|
|
236
|
+
List images for a MOD.
|
|
237
|
+
.TP
|
|
238
|
+
.B \-\-json
|
|
239
|
+
Output in JSON format.
|
|
240
|
+
.SS factorix mod image add MOD_NAME IMAGE_FILE
|
|
241
|
+
Add an image to a MOD.
|
|
242
|
+
.SS factorix mod image edit MOD_NAME IMAGE_IDS
|
|
243
|
+
Edit MOD's image list. Reorder or remove images by specifying IDs in desired order.
|
|
244
|
+
.SH SETTINGS COMMANDS
|
|
245
|
+
.SS factorix mod settings dump [SETTINGS_FILE]
|
|
246
|
+
Dump MOD settings to JSON format.
|
|
247
|
+
.TP
|
|
248
|
+
.BR \-o ", " \-\-output =\fIVALUE\fR
|
|
249
|
+
Output file path (default: stdout).
|
|
250
|
+
.SS factorix mod settings restore [SETTINGS_FILE]
|
|
251
|
+
Restore MOD settings from JSON format.
|
|
252
|
+
.TP
|
|
253
|
+
.BR \-i ", " \-\-input =\fIVALUE\fR
|
|
254
|
+
Input file path (default: stdin).
|
|
255
|
+
.TP
|
|
256
|
+
.BR \-\-backup\-extension =\fIVALUE\fR
|
|
257
|
+
Backup file extension (default: .bak).
|
|
258
|
+
.SH AUTHENTICATION
|
|
259
|
+
.SS Service Credentials (for MOD downloads)
|
|
260
|
+
Service credentials (username and token) are read from player-data.json
|
|
261
|
+
in the Factorio user data directory. These are automatically saved when
|
|
262
|
+
you log in to Factorio.
|
|
263
|
+
.PP
|
|
264
|
+
Alternatively, you can set environment variables:
|
|
265
|
+
.TP
|
|
266
|
+
.B FACTORIO_USERNAME
|
|
267
|
+
Factorio service username.
|
|
268
|
+
.TP
|
|
269
|
+
.B FACTORIO_TOKEN
|
|
270
|
+
Factorio service token.
|
|
271
|
+
.SS API Key (for MOD Portal management)
|
|
272
|
+
API key is required for upload, edit, and image operations.
|
|
273
|
+
Set the following environment variable:
|
|
274
|
+
.TP
|
|
275
|
+
.B FACTORIO_API_KEY
|
|
276
|
+
API key obtained from Factorio MOD Portal.
|
|
277
|
+
.SH ENVIRONMENT
|
|
278
|
+
.TP
|
|
279
|
+
.B FACTORIX_CONFIG
|
|
280
|
+
Path to configuration file. Overrides the default location.
|
|
281
|
+
.SH FILES
|
|
282
|
+
The paths below are XDG Base Directory defaults for Linux/WSL.
|
|
283
|
+
On macOS and Windows, these locations differ according to platform conventions.
|
|
284
|
+
Use
|
|
285
|
+
.B factorix path
|
|
286
|
+
to see actual paths for your system.
|
|
287
|
+
.TP
|
|
288
|
+
.I ~/.config/factorix/config.rb
|
|
289
|
+
User configuration file (Ruby DSL).
|
|
290
|
+
.TP
|
|
291
|
+
.I ~/.cache/factorix/
|
|
292
|
+
Cache directory for API responses and downloads.
|
|
293
|
+
.TP
|
|
294
|
+
.I ~/.local/state/factorix/
|
|
295
|
+
Log files.
|
|
296
|
+
.SH EXAMPLES
|
|
297
|
+
Enable shell completion for bash or zsh:
|
|
298
|
+
.PP
|
|
299
|
+
.RS
|
|
300
|
+
eval "$(factorix completion)"
|
|
301
|
+
.RE
|
|
302
|
+
.PP
|
|
303
|
+
Enable shell completion for fish:
|
|
304
|
+
.PP
|
|
305
|
+
.RS
|
|
306
|
+
factorix completion fish | source
|
|
307
|
+
.RE
|
|
308
|
+
.PP
|
|
309
|
+
List all installed MODs:
|
|
310
|
+
.PP
|
|
311
|
+
.RS
|
|
312
|
+
factorix mod list
|
|
313
|
+
.RE
|
|
314
|
+
.PP
|
|
315
|
+
Search for MODs on the portal:
|
|
316
|
+
.PP
|
|
317
|
+
.RS
|
|
318
|
+
factorix mod search logistic
|
|
319
|
+
.RE
|
|
320
|
+
.PP
|
|
321
|
+
Install a MOD with dependencies:
|
|
322
|
+
.PP
|
|
323
|
+
.RS
|
|
324
|
+
factorix mod install some-mod
|
|
325
|
+
.RE
|
|
326
|
+
.PP
|
|
327
|
+
Install a specific version:
|
|
328
|
+
.PP
|
|
329
|
+
.RS
|
|
330
|
+
factorix mod install some-mod@1.2.0
|
|
331
|
+
.RE
|
|
332
|
+
.PP
|
|
333
|
+
Update all installed MODs:
|
|
334
|
+
.PP
|
|
335
|
+
.RS
|
|
336
|
+
factorix mod update
|
|
337
|
+
.RE
|
|
338
|
+
.PP
|
|
339
|
+
Sync MODs from a save file:
|
|
340
|
+
.PP
|
|
341
|
+
.RS
|
|
342
|
+
factorix mod sync ~/factorio/saves/my-save.zip
|
|
343
|
+
.RE
|
|
344
|
+
.PP
|
|
345
|
+
Launch Factorio with custom arguments:
|
|
346
|
+
.PP
|
|
347
|
+
.RS
|
|
348
|
+
factorix launch -- --benchmark save.zip
|
|
349
|
+
.RE
|
|
350
|
+
.PP
|
|
351
|
+
Export MOD settings:
|
|
352
|
+
.PP
|
|
353
|
+
.RS
|
|
354
|
+
factorix mod settings dump -o settings.json
|
|
355
|
+
.RE
|
|
356
|
+
.SH EXIT STATUS
|
|
357
|
+
.TP
|
|
358
|
+
.B 0
|
|
359
|
+
Success.
|
|
360
|
+
.TP
|
|
361
|
+
.B 1
|
|
362
|
+
Expected error (e.g., MOD not found, validation failure).
|
|
363
|
+
.TP
|
|
364
|
+
.B 2
|
|
365
|
+
Unexpected error (e.g., network failure, internal error).
|
|
366
|
+
.SH SEE ALSO
|
|
367
|
+
.UR https://github.com/sakuro/factorix
|
|
368
|
+
Factorix on GitHub
|
|
369
|
+
.UE
|
|
370
|
+
.PP
|
|
371
|
+
.UR https://wiki.factorio.com/Mod_portal_API
|
|
372
|
+
Factorio MOD Portal API
|
|
373
|
+
.UE
|
|
374
|
+
.SH AUTHOR
|
|
375
|
+
OZAWA Sakuro
|
|
376
|
+
.SH COPYRIGHT
|
|
377
|
+
MIT License
|
data/exe/factorix
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "../lib/factorix"
|
|
5
|
+
require "dry/cli"
|
|
6
|
+
require "zip"
|
|
7
|
+
|
|
8
|
+
# Suppress warnings about invalid dates in ZIP files
|
|
9
|
+
Zip.warn_invalid_date = false
|
|
10
|
+
|
|
11
|
+
begin
|
|
12
|
+
Dry::CLI.new(Factorix::CLI).call
|
|
13
|
+
exit 0
|
|
14
|
+
rescue Factorix::Error
|
|
15
|
+
# Expected errors are already logged and displayed by CommandWrapper
|
|
16
|
+
exit 1
|
|
17
|
+
rescue
|
|
18
|
+
# Unexpected errors are already logged and displayed by CommandWrapper
|
|
19
|
+
exit 2
|
|
20
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Factorix
|
|
4
|
+
module API
|
|
5
|
+
Category = Data.define(:value, :name, :description)
|
|
6
|
+
|
|
7
|
+
# Category object from MOD Portal API
|
|
8
|
+
#
|
|
9
|
+
# Represents a MOD category with value, name, and description.
|
|
10
|
+
# Uses flyweight pattern - same category value returns same instance.
|
|
11
|
+
#
|
|
12
|
+
# @see https://wiki.factorio.com/Mod_details_API#Category
|
|
13
|
+
class Category
|
|
14
|
+
# @!attribute [r] value
|
|
15
|
+
# @return [String] category value (e.g., "content", "utilities", "" for no category)
|
|
16
|
+
# @!attribute [r] name
|
|
17
|
+
# @return [String] human-readable category name (e.g., "Content", "Utilities")
|
|
18
|
+
# @!attribute [r] description
|
|
19
|
+
# @return [String] category description
|
|
20
|
+
|
|
21
|
+
# Predefined category instances
|
|
22
|
+
NO_CATEGORY = new(value: "", name: "No category", description: "Unassigned category")
|
|
23
|
+
private_constant :NO_CATEGORY
|
|
24
|
+
CONTENT = new(value: "content", name: "Content", description: "Mods introducing new content into the game")
|
|
25
|
+
private_constant :CONTENT
|
|
26
|
+
OVERHAUL = new(value: "overhaul", name: "Overhaul", description: "Large total conversion mods")
|
|
27
|
+
private_constant :OVERHAUL
|
|
28
|
+
TWEAKS = new(value: "tweaks", name: "Tweaks", description: "Small changes concerning balance, gameplay, or graphics")
|
|
29
|
+
private_constant :TWEAKS
|
|
30
|
+
UTILITIES = new(value: "utilities", name: "Utilities", description: "Providing the player with new tools or adjusting the game interface")
|
|
31
|
+
private_constant :UTILITIES
|
|
32
|
+
SCENARIOS = new(value: "scenarios", name: "Scenarios", description: "Scenarios, maps, and puzzles")
|
|
33
|
+
private_constant :SCENARIOS
|
|
34
|
+
MOD_PACKS = new(value: "mod-packs", name: "Mod packs", description: "Collections of mods with tweaks to make them work together")
|
|
35
|
+
private_constant :MOD_PACKS
|
|
36
|
+
LOCALIZATIONS = new(value: "localizations", name: "Localizations", description: "Translations for other mods")
|
|
37
|
+
private_constant :LOCALIZATIONS
|
|
38
|
+
INTERNAL = new(value: "internal", name: "Internal", description: "Lua libraries for use by other mods")
|
|
39
|
+
private_constant :INTERNAL
|
|
40
|
+
|
|
41
|
+
# Lookup table for flyweight pattern
|
|
42
|
+
CATEGORIES = {
|
|
43
|
+
"" => NO_CATEGORY,
|
|
44
|
+
"no-category" => NO_CATEGORY,
|
|
45
|
+
"content" => CONTENT,
|
|
46
|
+
"overhaul" => OVERHAUL,
|
|
47
|
+
"tweaks" => TWEAKS,
|
|
48
|
+
"utilities" => UTILITIES,
|
|
49
|
+
"scenarios" => SCENARIOS,
|
|
50
|
+
"mod-packs" => MOD_PACKS,
|
|
51
|
+
"localizations" => LOCALIZATIONS,
|
|
52
|
+
"internal" => INTERNAL
|
|
53
|
+
}.freeze
|
|
54
|
+
private_constant :CATEGORIES
|
|
55
|
+
|
|
56
|
+
# Get Category instance for the given value
|
|
57
|
+
#
|
|
58
|
+
# Returns predefined instance for known categories (flyweight pattern).
|
|
59
|
+
# Raises an error for unknown category values.
|
|
60
|
+
#
|
|
61
|
+
# @param value [String] category value
|
|
62
|
+
# @return [Category] Category instance
|
|
63
|
+
# @raise [KeyError] if category value is unknown
|
|
64
|
+
def self.for(value) = CATEGORIES.fetch(value.to_s)
|
|
65
|
+
|
|
66
|
+
private_class_method :new, :[]
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "uri"
|
|
4
|
+
|
|
5
|
+
module Factorix
|
|
6
|
+
module API
|
|
7
|
+
Image = Data.define(:id, :thumbnail, :url)
|
|
8
|
+
|
|
9
|
+
# Image object from MOD Portal API
|
|
10
|
+
#
|
|
11
|
+
# Represents a MOD screenshot or image
|
|
12
|
+
#
|
|
13
|
+
# @see https://wiki.factorio.com/Mod_portal_API
|
|
14
|
+
class Image
|
|
15
|
+
# @!attribute [r] id
|
|
16
|
+
# @return [String] image ID
|
|
17
|
+
# @!attribute [r] thumbnail
|
|
18
|
+
# @return [URI::HTTPS] thumbnail URL
|
|
19
|
+
# @!attribute [r] url
|
|
20
|
+
# @return [URI::HTTPS] full-size image URL
|
|
21
|
+
|
|
22
|
+
# Create Image from API response hash
|
|
23
|
+
#
|
|
24
|
+
# @param id [String] image ID
|
|
25
|
+
# @param thumbnail [String] thumbnail URL
|
|
26
|
+
# @param url [String] full-size image URL
|
|
27
|
+
# @return [Image] new Image instance
|
|
28
|
+
def initialize(id:, thumbnail:, url:)
|
|
29
|
+
thumbnail = URI(thumbnail)
|
|
30
|
+
url = URI(url)
|
|
31
|
+
super
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "uri"
|
|
4
|
+
|
|
5
|
+
module Factorix
|
|
6
|
+
module API
|
|
7
|
+
License = Data.define(:id, :name, :title, :description, :url)
|
|
8
|
+
|
|
9
|
+
# License object from MOD Portal API
|
|
10
|
+
#
|
|
11
|
+
# Represents a MOD license information.
|
|
12
|
+
# Also provides valid license identifiers for edit_details API.
|
|
13
|
+
#
|
|
14
|
+
# @see https://wiki.factorio.com/Mod_portal_API
|
|
15
|
+
# @see https://wiki.factorio.com/Mod_details_API
|
|
16
|
+
class License
|
|
17
|
+
# @!attribute [r] id
|
|
18
|
+
# @return [String] license ID
|
|
19
|
+
# @!attribute [r] name
|
|
20
|
+
# @return [String] license name
|
|
21
|
+
# @!attribute [r] title
|
|
22
|
+
# @return [String] license title
|
|
23
|
+
# @!attribute [r] description
|
|
24
|
+
# @return [String] license description (long text)
|
|
25
|
+
# @!attribute [r] url
|
|
26
|
+
# @return [URI::HTTPS] license URL
|
|
27
|
+
|
|
28
|
+
# Valid license identifiers for edit_details API
|
|
29
|
+
# Custom licenses (custom_$ID) are not included
|
|
30
|
+
IDENTIFIERS = {
|
|
31
|
+
"default_mit" => "MIT",
|
|
32
|
+
"default_gnugplv3" => "GNU GPLv3",
|
|
33
|
+
"default_gnulgplv3" => "GNU LGPLv3",
|
|
34
|
+
"default_mozilla2" => "Mozilla Public License 2.0",
|
|
35
|
+
"default_apache2" => "Apache License 2.0",
|
|
36
|
+
"default_unlicense" => "The Unlicense"
|
|
37
|
+
}.freeze
|
|
38
|
+
private_constant :IDENTIFIERS
|
|
39
|
+
|
|
40
|
+
# Pattern for custom license identifiers (custom_ + 24 lowercase hex chars)
|
|
41
|
+
CUSTOM_LICENSE_PATTERN = /\Acustom_[0-9a-f]{24}\z/
|
|
42
|
+
private_constant :CUSTOM_LICENSE_PATTERN
|
|
43
|
+
|
|
44
|
+
# Check if the given value is a valid license identifier
|
|
45
|
+
#
|
|
46
|
+
# @param value [String] license identifier
|
|
47
|
+
# @return [Boolean] true if valid (standard or custom license)
|
|
48
|
+
def self.valid_identifier?(value)
|
|
49
|
+
IDENTIFIERS.key?(value) || CUSTOM_LICENSE_PATTERN.match?(value)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# List all valid license identifier values
|
|
53
|
+
#
|
|
54
|
+
# @return [Array<String>] array of license identifiers
|
|
55
|
+
def self.identifier_values = IDENTIFIERS.keys
|
|
56
|
+
|
|
57
|
+
# Create License from API response hash
|
|
58
|
+
#
|
|
59
|
+
# @param id [String] license ID
|
|
60
|
+
# @param name [String] license name
|
|
61
|
+
# @param title [String] license title
|
|
62
|
+
# @param description [String] license description
|
|
63
|
+
# @param url [String] license URL
|
|
64
|
+
# @return [License] new License instance
|
|
65
|
+
def initialize(id:, name:, title:, description:, url:)
|
|
66
|
+
url = URI(url)
|
|
67
|
+
super
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "uri"
|
|
4
|
+
|
|
5
|
+
module Factorix
|
|
6
|
+
module API
|
|
7
|
+
# API client for downloading MOD files with service authentication
|
|
8
|
+
#
|
|
9
|
+
# Requires username and token authentication via ServiceCredential.
|
|
10
|
+
class MODDownloadAPI
|
|
11
|
+
# NOTE: service_credential is NOT imported to avoid early evaluation errors
|
|
12
|
+
# when FACTORIO_USERNAME/FACTORIO_TOKEN environment variables are not set.
|
|
13
|
+
# It's resolved lazily via reader method instead.
|
|
14
|
+
# @!parse
|
|
15
|
+
# # @return [Transfer::Downloader]
|
|
16
|
+
# attr_reader :downloader
|
|
17
|
+
# # @return [Dry::Logger::Dispatcher]
|
|
18
|
+
# attr_reader :logger
|
|
19
|
+
include Import[:downloader, :logger]
|
|
20
|
+
|
|
21
|
+
BASE_URL = "https://mods.factorio.com"
|
|
22
|
+
private_constant :BASE_URL
|
|
23
|
+
|
|
24
|
+
# Initialize with thread-safe credential loading
|
|
25
|
+
#
|
|
26
|
+
# @param args [Hash] dependency injection arguments
|
|
27
|
+
def initialize(...)
|
|
28
|
+
super
|
|
29
|
+
@service_credential_mutex = Mutex.new
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Download a MOD file to the specified output path
|
|
33
|
+
#
|
|
34
|
+
# @param download_url [String] relative download URL from API response (e.g., "/download/mod-name/...")
|
|
35
|
+
# @param output [Pathname] output file path
|
|
36
|
+
# @param expected_sha1 [String, nil] expected SHA1 digest for verification (optional)
|
|
37
|
+
# @return [void]
|
|
38
|
+
# @raise [ArgumentError] if download_url is not a relative path starting with "/"
|
|
39
|
+
# @raise [DigestMismatchError] if SHA1 verification fails
|
|
40
|
+
def download(download_url, output, expected_sha1: nil)
|
|
41
|
+
unless download_url.start_with?("/")
|
|
42
|
+
logger.error("Invalid download_url", url: download_url)
|
|
43
|
+
raise ArgumentError, "download_url must be a relative path starting with '/'"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
uri = build_download_uri(download_url)
|
|
47
|
+
downloader.download(uri, output, expected_sha1:)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private def service_credential
|
|
51
|
+
return @service_credential if defined?(@service_credential)
|
|
52
|
+
|
|
53
|
+
@service_credential_mutex.synchronize do
|
|
54
|
+
@service_credential ||= Application[:service_credential]
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private def build_download_uri(download_url)
|
|
59
|
+
uri = URI.join(BASE_URL, download_url)
|
|
60
|
+
params = {username: service_credential.username, token: service_credential.token}
|
|
61
|
+
uri.query = URI.encode_www_form(params)
|
|
62
|
+
uri
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|