@muggleai/mcp 1.0.0 → 1.0.1
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/README.md +160 -160
- package/bin/muggle-mcp.js +2 -2
- package/dist/{chunk-6DQWAMGJ.js → chunk-IGLYJZH6.js} +154 -47
- package/dist/chunk-IGLYJZH6.js.map +1 -0
- package/dist/cli/cleanup.d.ts +55 -0
- package/dist/cli/cleanup.d.ts.map +1 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/upgrade.d.ts +26 -0
- package/dist/cli/upgrade.d.ts.map +1 -0
- package/dist/cli.js +611 -18
- package/dist/cli.js.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/local-qa/services/execution-service.d.ts.map +1 -1
- package/dist/shared/checksum.d.ts +59 -0
- package/dist/shared/checksum.d.ts.map +1 -0
- package/dist/shared/config.d.ts +21 -2
- package/dist/shared/config.d.ts.map +1 -1
- package/dist/shared/types.d.ts +24 -0
- package/dist/shared/types.d.ts.map +1 -1
- package/package.json +81 -75
- package/scripts/postinstall.mjs +247 -153
- package/dist/chunk-6DQWAMGJ.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,75 +1,81 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@muggleai/mcp",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Unified MCP server for Muggle AI - Cloud QA and Local Testing tools",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "dist/index.js",
|
|
7
|
-
"types": "dist/index.d.ts",
|
|
8
|
-
"bin": {
|
|
9
|
-
"muggle-mcp": "bin/muggle-mcp.js"
|
|
10
|
-
},
|
|
11
|
-
"files": [
|
|
12
|
-
"dist",
|
|
13
|
-
"bin/muggle-mcp.js",
|
|
14
|
-
"scripts/postinstall.mjs"
|
|
15
|
-
],
|
|
16
|
-
"scripts": {
|
|
17
|
-
"clean": "rimraf dist",
|
|
18
|
-
"build": "tsup && tsc --emitDeclarationOnly --declaration --outDir dist",
|
|
19
|
-
"build:release": "npm run build",
|
|
20
|
-
"postinstall": "node scripts/postinstall.mjs",
|
|
21
|
-
"start": "node dist/index.js",
|
|
22
|
-
"dev": "tsx watch src/index.ts",
|
|
23
|
-
"lint": "eslint . --fix",
|
|
24
|
-
"lint:check": "eslint .",
|
|
25
|
-
"test": "vitest run",
|
|
26
|
-
"test:watch": "vitest"
|
|
27
|
-
},
|
|
28
|
-
"muggleConfig": {
|
|
29
|
-
"electronAppVersion": "1.0.
|
|
30
|
-
"downloadBaseUrl": "https://github.com/multiplex-ai/muggle-ai-mcp/releases/download"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
"eslint
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"typescript": "^
|
|
54
|
-
"
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
"
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
"
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
"
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
|
|
74
|
-
"
|
|
75
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@muggleai/mcp",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Unified MCP server for Muggle AI - Cloud QA and Local Testing tools",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"muggle-mcp": "bin/muggle-mcp.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"bin/muggle-mcp.js",
|
|
14
|
+
"scripts/postinstall.mjs"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"clean": "rimraf dist",
|
|
18
|
+
"build": "tsup && tsc --emitDeclarationOnly --declaration --outDir dist",
|
|
19
|
+
"build:release": "npm run build",
|
|
20
|
+
"postinstall": "node scripts/postinstall.mjs",
|
|
21
|
+
"start": "node dist/index.js",
|
|
22
|
+
"dev": "tsx watch src/index.ts",
|
|
23
|
+
"lint": "eslint . --fix",
|
|
24
|
+
"lint:check": "eslint .",
|
|
25
|
+
"test": "vitest run",
|
|
26
|
+
"test:watch": "vitest"
|
|
27
|
+
},
|
|
28
|
+
"muggleConfig": {
|
|
29
|
+
"electronAppVersion": "1.0.1",
|
|
30
|
+
"downloadBaseUrl": "https://github.com/multiplex-ai/muggle-ai-mcp/releases/download",
|
|
31
|
+
"checksums": {
|
|
32
|
+
"darwin-arm64": "",
|
|
33
|
+
"darwin-x64": "",
|
|
34
|
+
"win32-x64": "",
|
|
35
|
+
"linux-x64": ""
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
40
|
+
"axios": "^1.7.9",
|
|
41
|
+
"commander": "^12.0.0",
|
|
42
|
+
"open": "^10.0.0",
|
|
43
|
+
"ulid": "^2.3.0",
|
|
44
|
+
"uuid": "^10.0.0",
|
|
45
|
+
"winston": "^3.17.0",
|
|
46
|
+
"zod": "^3.24.1"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@eslint/js": "^9.21.0",
|
|
50
|
+
"@types/node": "^22.0.0",
|
|
51
|
+
"@types/uuid": "^10.0.0",
|
|
52
|
+
"@typescript-eslint/eslint-plugin": "^8.34.0",
|
|
53
|
+
"@typescript-eslint/parser": "^8.34.0",
|
|
54
|
+
"eslint": "^9.28.0",
|
|
55
|
+
"eslint-plugin-unused-imports": "^4.2.0",
|
|
56
|
+
"rimraf": "^6.0.1",
|
|
57
|
+
"tsup": "^8.5.1",
|
|
58
|
+
"tsx": "^4.19.2",
|
|
59
|
+
"typescript": "^5.7.3",
|
|
60
|
+
"vitest": "^4.0.18"
|
|
61
|
+
},
|
|
62
|
+
"engines": {
|
|
63
|
+
"node": ">=22.0.0"
|
|
64
|
+
},
|
|
65
|
+
"keywords": [
|
|
66
|
+
"mcp",
|
|
67
|
+
"model-context-protocol",
|
|
68
|
+
"muggle-ai",
|
|
69
|
+
"qa",
|
|
70
|
+
"testing",
|
|
71
|
+
"automation",
|
|
72
|
+
"localhost"
|
|
73
|
+
],
|
|
74
|
+
"author": "Muggle AI",
|
|
75
|
+
"license": "MIT",
|
|
76
|
+
"repository": {
|
|
77
|
+
"type": "git",
|
|
78
|
+
"url": "git+https://github.com/multiplex-ai/muggle-ai-mcp.git"
|
|
79
|
+
},
|
|
80
|
+
"homepage": "https://www.muggle-ai.com/muggleTestV0/docs/mcp/mcp-overview"
|
|
81
|
+
}
|
package/scripts/postinstall.mjs
CHANGED
|
@@ -1,153 +1,247 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Postinstall script for @muggleai/mcp.
|
|
4
|
-
* Downloads the Electron app binary for local testing.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
*
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
*
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
*
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
return arch === "arm64"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
case "
|
|
47
|
-
return "
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
*
|
|
57
|
-
*/
|
|
58
|
-
async function
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
//
|
|
153
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Postinstall script for @muggleai/mcp.
|
|
4
|
+
* Downloads the Electron app binary for local testing.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { createHash } from "crypto";
|
|
8
|
+
import { exec } from "child_process";
|
|
9
|
+
import { createReadStream, createWriteStream, existsSync, mkdirSync, rmSync } from "fs";
|
|
10
|
+
import { homedir, platform } from "os";
|
|
11
|
+
import { join } from "path";
|
|
12
|
+
import { pipeline } from "stream/promises";
|
|
13
|
+
import { createRequire } from "module";
|
|
14
|
+
|
|
15
|
+
const require = createRequire(import.meta.url);
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Get the Muggle AI data directory.
|
|
19
|
+
* @returns {string} Path to ~/.muggle-ai
|
|
20
|
+
*/
|
|
21
|
+
function getDataDir() {
|
|
22
|
+
return join(homedir(), ".muggle-ai");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Get the Electron app directory.
|
|
27
|
+
* @returns {string} Path to ~/.muggle-ai/electron-app
|
|
28
|
+
*/
|
|
29
|
+
function getElectronAppDir() {
|
|
30
|
+
return join(getDataDir(), "electron-app");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Get platform key for checksum lookup.
|
|
35
|
+
* @returns {string} Platform key (e.g., "darwin-arm64", "win32-x64")
|
|
36
|
+
*/
|
|
37
|
+
function getPlatformKey() {
|
|
38
|
+
const os = platform();
|
|
39
|
+
const arch = process.arch;
|
|
40
|
+
|
|
41
|
+
switch (os) {
|
|
42
|
+
case "darwin":
|
|
43
|
+
return arch === "arm64" ? "darwin-arm64" : "darwin-x64";
|
|
44
|
+
case "win32":
|
|
45
|
+
return "win32-x64";
|
|
46
|
+
case "linux":
|
|
47
|
+
return "linux-x64";
|
|
48
|
+
default:
|
|
49
|
+
throw new Error(`Unsupported platform: ${os}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Calculate SHA256 checksum of a file.
|
|
55
|
+
* @param {string} filePath - Path to the file
|
|
56
|
+
* @returns {Promise<string>} SHA256 checksum as hex string
|
|
57
|
+
*/
|
|
58
|
+
async function calculateFileChecksum(filePath) {
|
|
59
|
+
return new Promise((resolve, reject) => {
|
|
60
|
+
const hash = createHash("sha256");
|
|
61
|
+
const stream = createReadStream(filePath);
|
|
62
|
+
|
|
63
|
+
stream.on("data", (data) => {
|
|
64
|
+
hash.update(data);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
stream.on("end", () => {
|
|
68
|
+
resolve(hash.digest("hex"));
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
stream.on("error", (error) => {
|
|
72
|
+
reject(error);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Verify file checksum against expected value.
|
|
79
|
+
* @param {string} filePath - Path to the file
|
|
80
|
+
* @param {string} expectedChecksum - Expected SHA256 checksum
|
|
81
|
+
* @returns {Promise<{valid: boolean, actual: string}>} Verification result
|
|
82
|
+
*/
|
|
83
|
+
async function verifyFileChecksum(filePath, expectedChecksum) {
|
|
84
|
+
if (!expectedChecksum || expectedChecksum.trim() === "") {
|
|
85
|
+
return { valid: true, actual: "", skipped: true };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const actualChecksum = await calculateFileChecksum(filePath);
|
|
89
|
+
const normalizedExpected = expectedChecksum.toLowerCase().trim();
|
|
90
|
+
const normalizedActual = actualChecksum.toLowerCase();
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
valid: normalizedExpected === normalizedActual,
|
|
94
|
+
expected: normalizedExpected,
|
|
95
|
+
actual: normalizedActual,
|
|
96
|
+
skipped: false,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Get platform-specific binary name.
|
|
102
|
+
* @returns {string} Binary filename
|
|
103
|
+
*/
|
|
104
|
+
function getBinaryName() {
|
|
105
|
+
const os = platform();
|
|
106
|
+
const arch = process.arch;
|
|
107
|
+
|
|
108
|
+
switch (os) {
|
|
109
|
+
case "darwin":
|
|
110
|
+
// Support both Apple Silicon (arm64) and Intel (x64) Macs
|
|
111
|
+
return arch === "arm64"
|
|
112
|
+
? "MuggleAI-darwin-arm64.zip"
|
|
113
|
+
: "MuggleAI-darwin-x64.zip";
|
|
114
|
+
case "win32":
|
|
115
|
+
return "MuggleAI-win32-x64.zip";
|
|
116
|
+
case "linux":
|
|
117
|
+
return "MuggleAI-linux-x64.zip";
|
|
118
|
+
default:
|
|
119
|
+
throw new Error(`Unsupported platform: ${os}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Download and extract the Electron app.
|
|
125
|
+
*/
|
|
126
|
+
async function downloadElectronApp() {
|
|
127
|
+
try {
|
|
128
|
+
// Read config from package.json
|
|
129
|
+
const packageJson = require("../package.json");
|
|
130
|
+
const config = packageJson.muggleConfig || {};
|
|
131
|
+
const version = config.electronAppVersion || "1.0.0";
|
|
132
|
+
const baseUrl = config.downloadBaseUrl || "https://github.com/multiplex-ai/muggle-ai-mcp/releases/download";
|
|
133
|
+
|
|
134
|
+
const binaryName = getBinaryName();
|
|
135
|
+
const downloadUrl = `${baseUrl}/electron-app-v${version}/${binaryName}`;
|
|
136
|
+
|
|
137
|
+
const appDir = getElectronAppDir();
|
|
138
|
+
const versionDir = join(appDir, version);
|
|
139
|
+
|
|
140
|
+
// Check if already downloaded
|
|
141
|
+
if (existsSync(versionDir)) {
|
|
142
|
+
console.log(`Electron app v${version} already installed at ${versionDir}`);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
console.log(`Downloading Muggle Test Electron app v${version}...`);
|
|
147
|
+
console.log(`URL: ${downloadUrl}`);
|
|
148
|
+
|
|
149
|
+
// Create directories
|
|
150
|
+
mkdirSync(versionDir, { recursive: true });
|
|
151
|
+
|
|
152
|
+
// Download using fetch
|
|
153
|
+
const response = await fetch(downloadUrl);
|
|
154
|
+
if (!response.ok) {
|
|
155
|
+
throw new Error(`Download failed: ${response.status} ${response.statusText}`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const tempFile = join(versionDir, binaryName);
|
|
159
|
+
const fileStream = createWriteStream(tempFile);
|
|
160
|
+
await pipeline(response.body, fileStream);
|
|
161
|
+
|
|
162
|
+
console.log("Download complete, verifying checksum...");
|
|
163
|
+
|
|
164
|
+
// Get expected checksum from config
|
|
165
|
+
const checksums = config.checksums || {};
|
|
166
|
+
const platformKey = getPlatformKey();
|
|
167
|
+
const expectedChecksum = checksums[platformKey] || "";
|
|
168
|
+
|
|
169
|
+
// Verify checksum
|
|
170
|
+
const checksumResult = await verifyFileChecksum(tempFile, expectedChecksum);
|
|
171
|
+
|
|
172
|
+
if (!checksumResult.valid && !checksumResult.skipped) {
|
|
173
|
+
rmSync(versionDir, { recursive: true, force: true });
|
|
174
|
+
throw new Error(
|
|
175
|
+
`Checksum verification failed!\n` +
|
|
176
|
+
`Expected: ${checksumResult.expected}\n` +
|
|
177
|
+
`Actual: ${checksumResult.actual}\n` +
|
|
178
|
+
`The downloaded file may be corrupted or tampered with.`
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (checksumResult.skipped) {
|
|
183
|
+
console.log("Warning: No checksum configured, skipping verification.");
|
|
184
|
+
} else {
|
|
185
|
+
console.log("Checksum verified successfully.");
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
console.log("Extracting...");
|
|
189
|
+
|
|
190
|
+
// Extract based on file type
|
|
191
|
+
if (binaryName.endsWith(".zip")) {
|
|
192
|
+
await extractZip(tempFile, versionDir);
|
|
193
|
+
} else if (binaryName.endsWith(".tar.gz")) {
|
|
194
|
+
await extractTarGz(tempFile, versionDir);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Clean up temp file
|
|
198
|
+
rmSync(tempFile, { force: true });
|
|
199
|
+
|
|
200
|
+
console.log(`Electron app installed to ${versionDir}`);
|
|
201
|
+
} catch (error) {
|
|
202
|
+
console.warn("Warning: Failed to download Electron app.");
|
|
203
|
+
console.warn("You can manually download it later using: muggle-mcp setup");
|
|
204
|
+
console.warn(`Error: ${error.message}`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Extract a zip file.
|
|
210
|
+
* @param {string} zipPath - Path to zip file
|
|
211
|
+
* @param {string} destDir - Destination directory
|
|
212
|
+
*/
|
|
213
|
+
async function extractZip(zipPath, destDir) {
|
|
214
|
+
return new Promise((resolve, reject) => {
|
|
215
|
+
const cmd = platform() === "win32"
|
|
216
|
+
? `powershell -command "Expand-Archive -Path '${zipPath}' -DestinationPath '${destDir}' -Force"`
|
|
217
|
+
: `unzip -o "${zipPath}" -d "${destDir}"`;
|
|
218
|
+
|
|
219
|
+
exec(cmd, (error) => {
|
|
220
|
+
if (error) {
|
|
221
|
+
reject(error);
|
|
222
|
+
} else {
|
|
223
|
+
resolve();
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Extract a tar.gz file.
|
|
231
|
+
* @param {string} tarPath - Path to tar.gz file
|
|
232
|
+
* @param {string} destDir - Destination directory
|
|
233
|
+
*/
|
|
234
|
+
async function extractTarGz(tarPath, destDir) {
|
|
235
|
+
return new Promise((resolve, reject) => {
|
|
236
|
+
exec(`tar -xzf "${tarPath}" -C "${destDir}"`, (error) => {
|
|
237
|
+
if (error) {
|
|
238
|
+
reject(error);
|
|
239
|
+
} else {
|
|
240
|
+
resolve();
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Run postinstall
|
|
247
|
+
downloadElectronApp().catch(console.error);
|