@zaxlck/modder-installer 0.0.0-stage → 0.1.4
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/backend/data/mods.json +114 -0
- package/backend/package-lock.json +987 -0
- package/backend/package.json +23 -0
- package/backend/server.js +476 -0
- package/bin/modder-cli.js +489 -0
- package/bin/modder-format.js +767 -0
- package/bin/modder-launcher.cmd +2 -0
- package/bin/modder.js +72 -0
- package/modder.js +91 -0
- package/package.json +35 -6
- package/scripts/install.ps1 +189 -0
- package/README.md +0 -3
package/bin/modder.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const { spawn } = require("child_process");
|
|
4
|
+
|
|
5
|
+
const root = path.join(process.env.LOCALAPPDATA, "Modder");
|
|
6
|
+
const backend = path.join(root, "backend");
|
|
7
|
+
const server = path.join(backend, "server.js");
|
|
8
|
+
const cli = path.join(root, "bin", "modder-cli.js");
|
|
9
|
+
const logDir = path.join(root, "logs");
|
|
10
|
+
const logFile = path.join(logDir, "server.log");
|
|
11
|
+
const api = "http://localhost:3000/api/mods";
|
|
12
|
+
|
|
13
|
+
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
|
|
14
|
+
|
|
15
|
+
async function serverReady() {
|
|
16
|
+
try {
|
|
17
|
+
const response = await fetch(api);
|
|
18
|
+
return response.ok;
|
|
19
|
+
} catch {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function main() {
|
|
25
|
+
if (!fs.existsSync(server) || !fs.existsSync(cli)) {
|
|
26
|
+
throw new Error("Modder is not fully installed. Run modder-install.");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!await serverReady()) {
|
|
30
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
31
|
+
|
|
32
|
+
const log = fs.openSync(logFile, "a");
|
|
33
|
+
|
|
34
|
+
const child = spawn(process.execPath, [server], {
|
|
35
|
+
cwd: backend,
|
|
36
|
+
detached: true,
|
|
37
|
+
stdio: ["ignore", log, log],
|
|
38
|
+
windowsHide: true
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
child.unref();
|
|
42
|
+
fs.closeSync(log);
|
|
43
|
+
|
|
44
|
+
let ready = false;
|
|
45
|
+
|
|
46
|
+
for (let i = 0; i < 40; i++) {
|
|
47
|
+
await delay(500);
|
|
48
|
+
|
|
49
|
+
if (await serverReady()) {
|
|
50
|
+
ready = true;
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!ready) {
|
|
56
|
+
const details = fs.existsSync(logFile)
|
|
57
|
+
? fs.readFileSync(logFile, "utf8").slice(-2500)
|
|
58
|
+
: "No server log available.";
|
|
59
|
+
|
|
60
|
+
throw new Error(
|
|
61
|
+
"Could not start the backend. Server log:\n" + details
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
require(cli);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
main().catch(error => {
|
|
70
|
+
console.error("\nModder:", error.message);
|
|
71
|
+
process.exitCode = 1;
|
|
72
|
+
});
|
package/modder.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
const readline = require("readline/promises");
|
|
4
|
+
const { stdin, stdout } = require("process");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
const { spawnSync } = require("child_process");
|
|
7
|
+
|
|
8
|
+
const VERSION = "0.1.0";
|
|
9
|
+
|
|
10
|
+
const rl = readline.createInterface({
|
|
11
|
+
input: stdin,
|
|
12
|
+
output: stdout
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
function runInstaller(mode) {
|
|
16
|
+
if (process.platform !== "win32") {
|
|
17
|
+
throw new Error("The Modder installer currently supports Windows only.");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const scriptPath = path.join(
|
|
21
|
+
__dirname,
|
|
22
|
+
"scripts",
|
|
23
|
+
"install.ps1"
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
const result = spawnSync(
|
|
27
|
+
"powershell.exe",
|
|
28
|
+
[
|
|
29
|
+
"-NoProfile",
|
|
30
|
+
"-ExecutionPolicy",
|
|
31
|
+
"Bypass",
|
|
32
|
+
"-File",
|
|
33
|
+
scriptPath,
|
|
34
|
+
"-Mode",
|
|
35
|
+
mode
|
|
36
|
+
],
|
|
37
|
+
{ stdio: "inherit" }
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
if (result.error) {
|
|
41
|
+
throw result.error;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (result.status !== 0) {
|
|
45
|
+
throw new Error("The installation did not complete successfully.");
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function main() {
|
|
50
|
+
console.log("");
|
|
51
|
+
console.log("================================");
|
|
52
|
+
console.log(" JUNGLE MODDER");
|
|
53
|
+
console.log(" MODDER INSTALLER");
|
|
54
|
+
console.log("================================");
|
|
55
|
+
console.log("");
|
|
56
|
+
console.log("Welcome to the Modder Installer!");
|
|
57
|
+
console.log("");
|
|
58
|
+
console.log("1. Full Modder application");
|
|
59
|
+
console.log("2. PowerShell support only");
|
|
60
|
+
console.log("3. Exit");
|
|
61
|
+
console.log("");
|
|
62
|
+
|
|
63
|
+
const choice = (await rl.question("Choose an option (1-3): ")).trim();
|
|
64
|
+
|
|
65
|
+
switch (choice) {
|
|
66
|
+
case "1":
|
|
67
|
+
runInstaller("Full");
|
|
68
|
+
break;
|
|
69
|
+
|
|
70
|
+
case "2":
|
|
71
|
+
runInstaller("PowerShell");
|
|
72
|
+
break;
|
|
73
|
+
|
|
74
|
+
case "3":
|
|
75
|
+
console.log("Installation cancelled.");
|
|
76
|
+
break;
|
|
77
|
+
|
|
78
|
+
default:
|
|
79
|
+
console.log("Invalid option.");
|
|
80
|
+
process.exitCode = 1;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
main()
|
|
85
|
+
.catch(error => {
|
|
86
|
+
console.error("\nInstaller error:", error.message);
|
|
87
|
+
process.exitCode = 1;
|
|
88
|
+
})
|
|
89
|
+
.finally(() => {
|
|
90
|
+
rl.close();
|
|
91
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,35 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@zaxlck/modder-installer",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@zaxlck/modder-installer",
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"description": "Installer for the Modder Geometry Dash mod platform",
|
|
5
|
+
"main": "modder.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"modder-install": "modder.js",
|
|
8
|
+
"modder": "bin/modder-launcher.cmd"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"modder.js",
|
|
12
|
+
"bin/",
|
|
13
|
+
"scripts/",
|
|
14
|
+
"backend/"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"test": "node --check modder.js && node --check bin/modder.js"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"geometry-dash",
|
|
21
|
+
"modder",
|
|
22
|
+
"installer"
|
|
23
|
+
],
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "https://github.com/zackdebono11-ux/Modder.git"
|
|
28
|
+
},
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"registry": "https://registry.npmjs.org/"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"fflate": "^0.8.3"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
|
|
2
|
+
param(
|
|
3
|
+
[ValidateSet("Full", "PowerShell")]
|
|
4
|
+
[string]$Mode = "PowerShell"
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
$ErrorActionPreference = "Stop"
|
|
8
|
+
|
|
9
|
+
$InstallRoot = Join-Path $env:LOCALAPPDATA "Modder"
|
|
10
|
+
$PackageRoot = Split-Path -Parent $PSScriptRoot
|
|
11
|
+
|
|
12
|
+
$ReleaseUrl = "https://github.com/zackdebono11-ux/Modder-Early-Access/releases/download/0.1.0/Modder-Full.zip"
|
|
13
|
+
$ExpectedHash = "1EFAE0C6344EA546D09698F62A299E508BA4B7FF702EA706D016FC390E2E5D88"
|
|
14
|
+
|
|
15
|
+
Write-Host ""
|
|
16
|
+
Write-Host "================================" -ForegroundColor Green
|
|
17
|
+
Write-Host " JUNGLE MODDER" -ForegroundColor Green
|
|
18
|
+
Write-Host " INSTALLER" -ForegroundColor Green
|
|
19
|
+
Write-Host "================================" -ForegroundColor Green
|
|
20
|
+
Write-Host ""
|
|
21
|
+
|
|
22
|
+
if (-not (Get-Command node -ErrorAction SilentlyContinue)) {
|
|
23
|
+
throw "Node.js is required. Install Node.js and run this installer again."
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
New-Item -ItemType Directory -Force -Path $InstallRoot | Out-Null
|
|
27
|
+
|
|
28
|
+
if ($Mode -eq "Full") {
|
|
29
|
+
Write-Host "Downloading Modder Full v0.1.0..." -ForegroundColor Cyan
|
|
30
|
+
|
|
31
|
+
$WorkRoot = Join-Path $env:TEMP ("Modder-Install-" + [guid]::NewGuid())
|
|
32
|
+
$ZipPath = Join-Path $WorkRoot "Modder-Full.zip"
|
|
33
|
+
$ExtractRoot = Join-Path $WorkRoot "Extracted"
|
|
34
|
+
$PreserveRoot = Join-Path $WorkRoot "Preserved"
|
|
35
|
+
|
|
36
|
+
New-Item -ItemType Directory -Force -Path $WorkRoot | Out-Null
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
# Download the official GitHub release.
|
|
40
|
+
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
|
41
|
+
|
|
42
|
+
Invoke-WebRequest `
|
|
43
|
+
-Uri $ReleaseUrl `
|
|
44
|
+
-OutFile $ZipPath `
|
|
45
|
+
-UseBasicParsing
|
|
46
|
+
|
|
47
|
+
# Verify the download before extracting it.
|
|
48
|
+
$ActualHash = (Get-FileHash $ZipPath -Algorithm SHA256).Hash
|
|
49
|
+
|
|
50
|
+
if ($ActualHash -ne $ExpectedHash) {
|
|
51
|
+
throw "The downloaded archive failed SHA256 verification. Installation cancelled."
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
Write-Host "Download verified!" -ForegroundColor Green
|
|
55
|
+
|
|
56
|
+
# Preserve existing user data before updating files.
|
|
57
|
+
$ExistingMods = Join-Path $InstallRoot "backend\data\mods.json"
|
|
58
|
+
$ExistingUploads = Join-Path $InstallRoot "backend\uploads"
|
|
59
|
+
|
|
60
|
+
if (Test-Path $ExistingMods) {
|
|
61
|
+
New-Item -ItemType Directory -Force -Path "$PreserveRoot\data" | Out-Null
|
|
62
|
+
Copy-Item $ExistingMods "$PreserveRoot\data\mods.json" -Force
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (Test-Path $ExistingUploads) {
|
|
66
|
+
New-Item -ItemType Directory -Force -Path $PreserveRoot | Out-Null
|
|
67
|
+
Copy-Item $ExistingUploads "$PreserveRoot\uploads" -Recurse -Force
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# Extract the release.
|
|
71
|
+
Write-Host "Extracting Modder Full..." -ForegroundColor Cyan
|
|
72
|
+
|
|
73
|
+
Expand-Archive -Path $ZipPath -DestinationPath $ExtractRoot -Force
|
|
74
|
+
|
|
75
|
+
# Install the release files.
|
|
76
|
+
Write-Host "Installing Modder files..." -ForegroundColor Cyan
|
|
77
|
+
|
|
78
|
+
Copy-Item "$ExtractRoot\*" $InstallRoot -Recurse -Force
|
|
79
|
+
|
|
80
|
+
# Restore existing user data.
|
|
81
|
+
if (Test-Path "$PreserveRoot\data\mods.json") {
|
|
82
|
+
Copy-Item "$PreserveRoot\data\mods.json" `
|
|
83
|
+
"$InstallRoot\backend\data\mods.json" -Force
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (Test-Path "$PreserveRoot\uploads") {
|
|
87
|
+
New-Item -ItemType Directory -Force `
|
|
88
|
+
-Path "$InstallRoot\backend\uploads" | Out-Null
|
|
89
|
+
|
|
90
|
+
Copy-Item "$PreserveRoot\uploads\*" `
|
|
91
|
+
"$InstallRoot\backend\uploads" -Recurse -Force
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
# Set up the existing working CLI launcher.
|
|
95
|
+
New-Item -ItemType Directory -Force `
|
|
96
|
+
-Path "$InstallRoot\bin" | Out-Null
|
|
97
|
+
|
|
98
|
+
# Install the current CLI and .modder format module.
|
|
99
|
+
Copy-Item "$PackageRoot\bin\modder-cli.js" `
|
|
100
|
+
"$InstallRoot\bin\modder-cli.js" -Force
|
|
101
|
+
|
|
102
|
+
Copy-Item "$PackageRoot\bin\modder-format.js" `
|
|
103
|
+
"$InstallRoot\bin\modder-format.js" -Force
|
|
104
|
+
|
|
105
|
+
# Ensure Full mode has the ZIP dependency too.
|
|
106
|
+
Copy-Item "$PackageRoot\backend\package.json" `
|
|
107
|
+
"$InstallRoot\backend\package.json" -Force
|
|
108
|
+
|
|
109
|
+
Copy-Item "$PackageRoot\backend\package-lock.json" `
|
|
110
|
+
"$InstallRoot\backend\package-lock.json" -Force
|
|
111
|
+
|
|
112
|
+
Copy-Item "$PackageRoot\bin\modder.js" `
|
|
113
|
+
"$InstallRoot\bin\modder.js" -Force
|
|
114
|
+
|
|
115
|
+
Write-Host "Modder Full files installed!" -ForegroundColor Green
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
if (Test-Path $WorkRoot) {
|
|
119
|
+
Remove-Item $WorkRoot -Recurse -Force
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
Write-Host "Installing Modder PowerShell support..." -ForegroundColor Cyan
|
|
125
|
+
|
|
126
|
+
New-Item -ItemType Directory -Force -Path "$InstallRoot\bin" | Out-Null
|
|
127
|
+
New-Item -ItemType Directory -Force -Path "$InstallRoot\backend\data" | Out-Null
|
|
128
|
+
New-Item -ItemType Directory -Force -Path "$InstallRoot\backend\uploads\mods" | Out-Null
|
|
129
|
+
New-Item -ItemType Directory -Force -Path "$InstallRoot\backend\uploads\screenshots" | Out-Null
|
|
130
|
+
|
|
131
|
+
Copy-Item "$PackageRoot\bin\modder.js" "$InstallRoot\bin\modder.js" -Force
|
|
132
|
+
Copy-Item "$PackageRoot\bin\modder-cli.js" "$InstallRoot\bin\modder-cli.js" -Force
|
|
133
|
+
Copy-Item "$PackageRoot\bin\modder-format.js" "$InstallRoot\bin\modder-format.js" -Force
|
|
134
|
+
|
|
135
|
+
Copy-Item "$PackageRoot\backend\server.js" "$InstallRoot\backend\server.js" -Force
|
|
136
|
+
Copy-Item "$PackageRoot\backend\package.json" "$InstallRoot\backend\package.json" -Force
|
|
137
|
+
Copy-Item "$PackageRoot\backend\package-lock.json" "$InstallRoot\backend\package-lock.json" -Force
|
|
138
|
+
|
|
139
|
+
if (-not (Test-Path "$InstallRoot\backend\data\mods.json")) {
|
|
140
|
+
Copy-Item "$PackageRoot\backend\data\mods.json" "$InstallRoot\backend\data\mods.json"
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
# Install backend dependencies.
|
|
145
|
+
Write-Host "Installing backend dependencies..." -ForegroundColor Cyan
|
|
146
|
+
|
|
147
|
+
Push-Location "$InstallRoot\backend"
|
|
148
|
+
try {
|
|
149
|
+
npm.cmd ci --omit=dev
|
|
150
|
+
|
|
151
|
+
if ($LASTEXITCODE -ne 0) {
|
|
152
|
+
throw "Backend dependency installation failed."
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
finally {
|
|
156
|
+
Pop-Location
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
# Add the CLI folder to the user's PATH.
|
|
160
|
+
$BinPath = "$InstallRoot\bin"
|
|
161
|
+
$UserPath = [Environment]::GetEnvironmentVariable("Path", "User")
|
|
162
|
+
|
|
163
|
+
$PathEntries = @()
|
|
164
|
+
if ($UserPath) {
|
|
165
|
+
$PathEntries = $UserPath -split ";" | Where-Object { $_ }
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if ($PathEntries -notcontains $BinPath) {
|
|
169
|
+
$NewPath = if ($UserPath) {
|
|
170
|
+
"$UserPath;$BinPath"
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
$BinPath
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
[Environment]::SetEnvironmentVariable("Path", $NewPath, "User")
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if ($env:Path -notlike "*$BinPath*") {
|
|
180
|
+
$env:Path += ";$BinPath"
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
Write-Host ""
|
|
184
|
+
Write-Host "Modder installation completed successfully!" -ForegroundColor Green
|
|
185
|
+
Write-Host ""
|
|
186
|
+
Write-Host "Installation folder: $InstallRoot"
|
|
187
|
+
Write-Host "CLI command: modder"
|
|
188
|
+
Write-Host "Restart PowerShell if necessary."
|
|
189
|
+
Write-Host ""
|
package/README.md
DELETED