@bobschlowinskii/clicraft 0.4.4 ā 0.4.5
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.
- package/CHANGELOG.md +15 -1
- package/commands/create.js +11 -2
- package/commands/install.js +69 -18
- package/docs/commands/create.md +2 -0
- package/docs/commands/install.md +14 -18
- package/helpers/versions.js +1 -0
- package/index.js +4 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
-
## [0.4.
|
|
5
|
+
## [0.4.5] - 2026-01-31
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **Added `force` option to `create` command**
|
|
9
|
+
- Overwrites existing instance if folder already exists in path
|
|
10
|
+
- call with `--force` or `-f`
|
|
11
|
+
- **Added `path` option to `create` command**
|
|
12
|
+
- Specifies a path other than the working directory to install the instance
|
|
13
|
+
- call with `--path` or `-p`
|
|
14
|
+
- **Multi-mod installation support**
|
|
15
|
+
- Install multiple mods in a single command: `clicraft install mod1 mod2 mod3`
|
|
16
|
+
- Shows installation summary when installing multiple mods
|
|
17
|
+
- Tracks success/failure count for batch installations
|
|
18
|
+
|
|
19
|
+
## [0.4.4] - 2026-01-29
|
|
6
20
|
|
|
7
21
|
### Added
|
|
8
22
|
|
package/commands/create.js
CHANGED
|
@@ -482,7 +482,7 @@ export async function createInstance(options) {
|
|
|
482
482
|
message: 'Instance Name:',
|
|
483
483
|
validate: (input) => {
|
|
484
484
|
if (!input.trim()) return 'Instance name is required';
|
|
485
|
-
if (fs.existsSync(input.trim())) return 'A folder with this name already exists';
|
|
485
|
+
if (fs.existsSync(input.trim()) && !options.force) return 'A folder with this name already exists';
|
|
486
486
|
return true;
|
|
487
487
|
}
|
|
488
488
|
}]);
|
|
@@ -526,7 +526,16 @@ export async function createInstance(options) {
|
|
|
526
526
|
loaderVersion = await paginatedSelect('Forge Version:', forgeChoices);
|
|
527
527
|
}
|
|
528
528
|
|
|
529
|
-
const instancePath = path
|
|
529
|
+
const instancePath = options.path
|
|
530
|
+
? path.resolve(options.path) + path.resolve(instanceName.trim())
|
|
531
|
+
: path.resolve(instanceName.trim())
|
|
532
|
+
;
|
|
533
|
+
if (fs.existsSync(instancePath) && !options.force) {
|
|
534
|
+
console.log(chalk.red(`A folder already exists at ${instancePath}. Use --force to overwrite.`));
|
|
535
|
+
return;
|
|
536
|
+
} else if (fs.existsSync(instancePath) && options.force) {
|
|
537
|
+
fs.rmSync(instancePath, { recursive: true, force: true });
|
|
538
|
+
}
|
|
530
539
|
fs.mkdirSync(instancePath, { recursive: true });
|
|
531
540
|
fs.mkdirSync(path.join(instancePath, 'mods'), { recursive: true });
|
|
532
541
|
|
package/commands/install.js
CHANGED
|
@@ -5,12 +5,41 @@ import { downloadFile, loadConfig, saveConfig, getInstancePath, requireConfig }
|
|
|
5
5
|
import { getProject, getProjectVersions } from '../helpers/modrinth.js';
|
|
6
6
|
import { callPostCommandActions } from '../helpers/post-command.js';
|
|
7
7
|
|
|
8
|
-
export async function installMod(
|
|
8
|
+
export async function installMod(modSlugs, options) {
|
|
9
9
|
const instancePath = getInstancePath(options);
|
|
10
10
|
|
|
11
11
|
const config = requireConfig(instancePath);
|
|
12
12
|
if (!config) return;
|
|
13
13
|
|
|
14
|
+
// Handle multiple mods
|
|
15
|
+
const slugs = Array.isArray(modSlugs) ? modSlugs : [modSlugs];
|
|
16
|
+
|
|
17
|
+
let successCount = 0;
|
|
18
|
+
let failCount = 0;
|
|
19
|
+
|
|
20
|
+
for (const modSlug of slugs) {
|
|
21
|
+
const success = await installSingleMod(modSlug, instancePath, config, options);
|
|
22
|
+
if (success) {
|
|
23
|
+
successCount++;
|
|
24
|
+
} else {
|
|
25
|
+
failCount++;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Show summary if multiple mods were requested
|
|
30
|
+
if (slugs.length > 1) {
|
|
31
|
+
console.log(chalk.cyan('\nš Installation Summary:'));
|
|
32
|
+
console.log(chalk.green(` ā
${successCount} mod(s) installed successfully`));
|
|
33
|
+
if (failCount > 0) {
|
|
34
|
+
console.log(chalk.red(` ā ${failCount} mod(s) failed to install`));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
callPostCommandActions();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async function installSingleMod(modSlug, instancePath, config, options) {
|
|
42
|
+
|
|
14
43
|
console.log(chalk.cyan(`\nš¦ Installing "${modSlug}" to ${config.name}...\n`));
|
|
15
44
|
|
|
16
45
|
try {
|
|
@@ -19,12 +48,12 @@ export async function installMod(modSlug, options) {
|
|
|
19
48
|
if (!project) {
|
|
20
49
|
console.log(chalk.red(`Error: Mod "${modSlug}" not found on Modrinth.`));
|
|
21
50
|
console.log(chalk.gray('Use "clicraft search <query>" to find available mods.'));
|
|
22
|
-
return;
|
|
51
|
+
return false;
|
|
23
52
|
}
|
|
24
53
|
|
|
25
54
|
if (project.project_type !== 'mod') {
|
|
26
55
|
console.log(chalk.red(`Error: "${modSlug}" is a ${project.project_type}, not a mod.`));
|
|
27
|
-
return;
|
|
56
|
+
return false;
|
|
28
57
|
}
|
|
29
58
|
|
|
30
59
|
console.log(chalk.gray(`Found: ${project.title}`));
|
|
@@ -44,7 +73,7 @@ export async function installMod(modSlug, options) {
|
|
|
44
73
|
console.log(chalk.gray(`\nAvailable loaders: ${loaders.join(', ')}`));
|
|
45
74
|
console.log(chalk.gray(`Recent game versions: ${gameVersions.join(', ')}`));
|
|
46
75
|
}
|
|
47
|
-
return;
|
|
76
|
+
return false;
|
|
48
77
|
}
|
|
49
78
|
|
|
50
79
|
// Use the latest compatible version
|
|
@@ -53,7 +82,7 @@ export async function installMod(modSlug, options) {
|
|
|
53
82
|
|
|
54
83
|
if (!file) {
|
|
55
84
|
console.log(chalk.red('Error: No downloadable file found for this version.'));
|
|
56
|
-
return;
|
|
85
|
+
return false;
|
|
57
86
|
}
|
|
58
87
|
|
|
59
88
|
// Check if already installed
|
|
@@ -61,7 +90,7 @@ export async function installMod(modSlug, options) {
|
|
|
61
90
|
if (existingMod && !options.force) {
|
|
62
91
|
console.log(chalk.yellow(`\nā ļø ${project.title} is already installed (version ${existingMod.versionNumber})`));
|
|
63
92
|
console.log(chalk.gray('Use --force to reinstall or update.'));
|
|
64
|
-
return;
|
|
93
|
+
return false;
|
|
65
94
|
}
|
|
66
95
|
|
|
67
96
|
// Create mods folder if needed
|
|
@@ -104,30 +133,52 @@ export async function installMod(modSlug, options) {
|
|
|
104
133
|
// Show dependencies if any
|
|
105
134
|
if (version.dependencies?.length > 0) {
|
|
106
135
|
const requiredDeps = version.dependencies.filter(d => d.dependency_type === 'required');
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
136
|
+
let totalDeps = [];
|
|
137
|
+
let notInstalledDeps = [];
|
|
138
|
+
|
|
139
|
+
for (const dep of requiredDeps) {
|
|
140
|
+
if (dep.project_id) {
|
|
141
|
+
const depProject = await getProject(dep.project_id);
|
|
142
|
+
if (depProject) {
|
|
143
|
+
const isInstalled = config.mods.some(m => m.projectId === dep.project_id);
|
|
144
|
+
// const status = isInstalled ? chalk.green('ā') : chalk.red('ā');
|
|
145
|
+
totalDeps.push({ project: depProject, title: depProject.title, slug: depProject.slug, installed: isInstalled });
|
|
117
146
|
}
|
|
118
147
|
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
for (const dep of totalDeps) {
|
|
151
|
+
if (!dep.installed) {
|
|
152
|
+
notInstalledDeps.push(dep);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (notInstalledDeps.length > 0) {
|
|
157
|
+
console.log(chalk.yellow(`\nā ļø This mod has ${notInstalledDeps.length} dependencies which are not installed:`));
|
|
158
|
+
totalDeps.forEach(dep => {
|
|
159
|
+
if(dep.installed)
|
|
160
|
+
console.log(chalk.green(` - ${dep.title} (${dep.slug})`));
|
|
161
|
+
if(!dep.installed)
|
|
162
|
+
console.log(chalk.yellow(` - ${dep.title} (${dep.slug})`));
|
|
163
|
+
});
|
|
119
164
|
console.log(chalk.gray('\nInstall dependencies with: clicraft install <slug>'));
|
|
120
165
|
}
|
|
166
|
+
|
|
167
|
+
if (notInstalledDeps.length === 0) {
|
|
168
|
+
console.log(chalk.green('\nā
All dependencies are already installed.'));
|
|
169
|
+
|
|
170
|
+
}
|
|
121
171
|
}
|
|
122
172
|
|
|
173
|
+
return true;
|
|
174
|
+
|
|
123
175
|
} catch (error) {
|
|
124
176
|
console.error(chalk.red('Error installing mod:'), error.message);
|
|
125
177
|
if (options.verbose) {
|
|
126
178
|
console.error(error);
|
|
127
179
|
}
|
|
180
|
+
return false;
|
|
128
181
|
}
|
|
129
|
-
|
|
130
|
-
callPostCommandActions();
|
|
131
182
|
}
|
|
132
183
|
|
|
133
184
|
export default { installMod };
|
package/docs/commands/create.md
CHANGED
|
@@ -47,6 +47,8 @@ This is perfect for sharing modpack configurations or replicating setups across
|
|
|
47
47
|
| Option | Description |
|
|
48
48
|
|--------|-------------|
|
|
49
49
|
| `--verbose` | Enable verbose output to see detailed progress |
|
|
50
|
+
| `--force, -f` | Overwrites existing instance folder if necessary |
|
|
51
|
+
| `--path, -p <path>` | Specifies path in which to install instance |
|
|
50
52
|
|
|
51
53
|
## š” Interactive Prompts
|
|
52
54
|
|
package/docs/commands/install.md
CHANGED
|
@@ -14,12 +14,12 @@ Install mods from Modrinth directly to your Minecraft instance.
|
|
|
14
14
|
## š Synopsis
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
|
-
clicraft install <
|
|
17
|
+
clicraft install <mods...> [options]
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
## š Description
|
|
21
21
|
|
|
22
|
-
The `install` command downloads and installs mods from Modrinth to your Minecraft instance. It automatically:
|
|
22
|
+
The `install` command downloads and installs one or more mods from Modrinth to your Minecraft instance. It automatically:
|
|
23
23
|
|
|
24
24
|
1. Searches for the mod on Modrinth
|
|
25
25
|
2. Finds the correct version for your Minecraft version and loader
|
|
@@ -31,7 +31,7 @@ The `install` command downloads and installs mods from Modrinth to your Minecraf
|
|
|
31
31
|
|
|
32
32
|
| Argument | Description | Required |
|
|
33
33
|
|----------|-------------|----------|
|
|
34
|
-
| `<
|
|
34
|
+
| `<mods...>` | One or more mod names or Modrinth project IDs | Yes (at least one) |
|
|
35
35
|
|
|
36
36
|
## šÆ Options
|
|
37
37
|
|
|
@@ -69,9 +69,13 @@ Use the project ID from `clicraft search` results.
|
|
|
69
69
|
### Install multiple mods
|
|
70
70
|
```bash
|
|
71
71
|
cd my-instance
|
|
72
|
-
clicraft install sodium
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
clicraft install sodium lithium iris
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
When installing multiple mods, you'll see a summary at the end:
|
|
76
|
+
```
|
|
77
|
+
š Installation Summary:
|
|
78
|
+
ā
3 mod(s) installed successfully
|
|
75
79
|
```
|
|
76
80
|
|
|
77
81
|
### Verbose installation
|
|
@@ -130,33 +134,25 @@ instance-directory/
|
|
|
130
134
|
### Building a Performance Pack
|
|
131
135
|
```bash
|
|
132
136
|
cd my-instance
|
|
133
|
-
clicraft install sodium
|
|
134
|
-
clicraft install lithium # Server optimization
|
|
135
|
-
clicraft install starlight # Lighting engine
|
|
136
|
-
clicraft install ferritecore # Memory optimization
|
|
137
|
+
clicraft install sodium lithium starlight ferritecore
|
|
137
138
|
```
|
|
138
139
|
|
|
139
140
|
### Adding Quality of Life Mods
|
|
140
141
|
```bash
|
|
141
142
|
cd my-instance
|
|
142
|
-
clicraft install
|
|
143
|
-
clicraft install "journeymap" # Minimap
|
|
144
|
-
clicraft install "appleskin" # Food info
|
|
143
|
+
clicraft install jei journeymap appleskin
|
|
145
144
|
```
|
|
146
145
|
|
|
147
146
|
### Installing Shader Support
|
|
148
147
|
```bash
|
|
149
148
|
cd my-instance
|
|
150
|
-
clicraft install sodium
|
|
151
|
-
clicraft install iris # Shader loader
|
|
149
|
+
clicraft install sodium iris
|
|
152
150
|
```
|
|
153
151
|
|
|
154
152
|
### Server Mods
|
|
155
153
|
```bash
|
|
156
154
|
cd my-server
|
|
157
|
-
clicraft install lithium
|
|
158
|
-
clicraft install starlight
|
|
159
|
-
clicraft install "fabric api"
|
|
155
|
+
clicraft install lithium starlight fabric-api
|
|
160
156
|
```
|
|
161
157
|
|
|
162
158
|
## ā ļø Important Notes
|
package/helpers/versions.js
CHANGED
package/index.js
CHANGED
|
@@ -31,11 +31,13 @@ program
|
|
|
31
31
|
.command('create')
|
|
32
32
|
.description('Create a new Minecraft instance')
|
|
33
33
|
.option('--verbose', 'Enable verbose output')
|
|
34
|
+
.option('-f, --force', 'Overwrite existing instance if it exists')
|
|
35
|
+
.option('-p, --path <path>', 'Path to create the instance in')
|
|
34
36
|
.action(createInstance);
|
|
35
37
|
|
|
36
38
|
program
|
|
37
|
-
.command('install <
|
|
38
|
-
.description('Install
|
|
39
|
+
.command('install <mods...>')
|
|
40
|
+
.description('Install one or more mods to the current Minecraft instance')
|
|
39
41
|
.option('-i, --instance <path>', 'Path to the instance directory')
|
|
40
42
|
.option('-f, --force', 'Force reinstall/update if already installed')
|
|
41
43
|
.option('--verbose', 'Enable verbose output')
|