@naesofteak/naeso 0.0.0-stage → 1.0.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.
- package/LICENSE +21 -0
- package/README.md +46 -2
- package/package.json +48 -4
- package/src/core/cache.js +39 -0
- package/src/core/checksum.js +33 -0
- package/src/core/compatibility.js +152 -0
- package/src/core/downloader.js +234 -0
- package/src/core/environment.js +225 -0
- package/src/core/extractor.js +235 -0
- package/src/core/installer.js +691 -0
- package/src/core/package-downloader.js +284 -0
- package/src/core/package-manager.js +0 -0
- package/src/core/package-resolver.js +125 -0
- package/src/core/platform.js +41 -0
- package/src/core/registry.js +70 -0
- package/src/core/target.js +56 -0
- package/src/core/uninstaller.js +389 -0
- package/src/index.js +635 -0
- package/src/registry/packages/mongodb/package.json +100 -0
- package/src/services/launchd.js +174 -0
- package/src/services/mongodb.js +166 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
|
|
4
|
+
const {
|
|
5
|
+
resolvePackage
|
|
6
|
+
} = require("./package-resolver");
|
|
7
|
+
|
|
8
|
+
const {
|
|
9
|
+
downloadFile
|
|
10
|
+
} = require("./downloader");
|
|
11
|
+
|
|
12
|
+
const {
|
|
13
|
+
calculateSHA256
|
|
14
|
+
} = require("./checksum");
|
|
15
|
+
|
|
16
|
+
const {
|
|
17
|
+
ensurePackageCache,
|
|
18
|
+
getCachedFile
|
|
19
|
+
} = require("./cache");
|
|
20
|
+
|
|
21
|
+
async function verifyArtifact(
|
|
22
|
+
artifact,
|
|
23
|
+
archivePath,
|
|
24
|
+
packageName
|
|
25
|
+
) {
|
|
26
|
+
/*
|
|
27
|
+
* If the registry provides an official SHA-256 URL,
|
|
28
|
+
* download and verify it.
|
|
29
|
+
*/
|
|
30
|
+
if (artifact.sha256Url) {
|
|
31
|
+
const archiveName =
|
|
32
|
+
path.basename(
|
|
33
|
+
new URL(artifact.url).pathname
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const checksumName =
|
|
37
|
+
`${archiveName}.sha256`;
|
|
38
|
+
|
|
39
|
+
const checksumPath =
|
|
40
|
+
getCachedFile(
|
|
41
|
+
packageName,
|
|
42
|
+
checksumName
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
if (fs.existsSync(checksumPath)) {
|
|
46
|
+
console.log(
|
|
47
|
+
`Checksum file already exists: ${checksumPath}`
|
|
48
|
+
);
|
|
49
|
+
} else {
|
|
50
|
+
console.log(
|
|
51
|
+
"Downloading official SHA-256 checksum..."
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
await downloadFile(
|
|
55
|
+
artifact.sha256Url,
|
|
56
|
+
checksumPath
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
console.log(
|
|
60
|
+
`Downloaded: ${checksumPath}`
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const checksumText =
|
|
65
|
+
fs.readFileSync(
|
|
66
|
+
checksumPath,
|
|
67
|
+
"utf8"
|
|
68
|
+
).trim();
|
|
69
|
+
|
|
70
|
+
const expectedHash =
|
|
71
|
+
checksumText
|
|
72
|
+
.split(/\s+/)[0]
|
|
73
|
+
.toLowerCase();
|
|
74
|
+
|
|
75
|
+
if (!/^[a-f0-9]{64}$/.test(expectedHash)) {
|
|
76
|
+
throw new Error(
|
|
77
|
+
`Invalid SHA-256 checksum for ${artifact.name}.`
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
console.log(
|
|
82
|
+
`Expected SHA-256: ${expectedHash}`
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
console.log(
|
|
86
|
+
"Calculating downloaded archive SHA-256..."
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const actualHash =
|
|
90
|
+
(
|
|
91
|
+
await calculateSHA256(
|
|
92
|
+
archivePath
|
|
93
|
+
)
|
|
94
|
+
).toLowerCase();
|
|
95
|
+
|
|
96
|
+
console.log(
|
|
97
|
+
`Actual SHA-256: ${actualHash}`
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
if (actualHash !== expectedHash) {
|
|
101
|
+
fs.unlinkSync(archivePath);
|
|
102
|
+
|
|
103
|
+
throw new Error(
|
|
104
|
+
`${artifact.name} failed SHA-256 verification.`
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
console.log(
|
|
109
|
+
`${artifact.name} SHA-256 verification PASSED.`
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
verified: true,
|
|
114
|
+
checksum: expectedHash
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/*
|
|
119
|
+
* No official checksum URL is registered yet.
|
|
120
|
+
*
|
|
121
|
+
* We still calculate the local SHA-256 so that the
|
|
122
|
+
* artifact gets a deterministic fingerprint.
|
|
123
|
+
*/
|
|
124
|
+
console.log(
|
|
125
|
+
`No official SHA-256 URL registered for ${artifact.name}.`
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
const actualHash =
|
|
129
|
+
(
|
|
130
|
+
await calculateSHA256(
|
|
131
|
+
archivePath
|
|
132
|
+
)
|
|
133
|
+
).toLowerCase();
|
|
134
|
+
|
|
135
|
+
console.log(
|
|
136
|
+
`SHA-256: ${actualHash}`
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
return {
|
|
140
|
+
verified: false,
|
|
141
|
+
checksum: actualHash
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async function downloadArtifact(
|
|
146
|
+
packageName,
|
|
147
|
+
artifact
|
|
148
|
+
) {
|
|
149
|
+
const cacheDirectory =
|
|
150
|
+
ensurePackageCache(
|
|
151
|
+
packageName
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
const archiveName =
|
|
155
|
+
path.basename(
|
|
156
|
+
new URL(artifact.url).pathname
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
const archivePath =
|
|
160
|
+
getCachedFile(
|
|
161
|
+
packageName,
|
|
162
|
+
archiveName
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
console.log("");
|
|
166
|
+
console.log(
|
|
167
|
+
`Artifact: ${artifact.name}`
|
|
168
|
+
);
|
|
169
|
+
console.log(
|
|
170
|
+
`Type: ${artifact.type}`
|
|
171
|
+
);
|
|
172
|
+
console.log(
|
|
173
|
+
`Version: ${artifact.version}`
|
|
174
|
+
);
|
|
175
|
+
console.log(
|
|
176
|
+
`URL: ${artifact.url}`
|
|
177
|
+
);
|
|
178
|
+
console.log("");
|
|
179
|
+
|
|
180
|
+
if (fs.existsSync(archivePath)) {
|
|
181
|
+
console.log(
|
|
182
|
+
`Archive already exists: ${archivePath}`
|
|
183
|
+
);
|
|
184
|
+
} else {
|
|
185
|
+
console.log(
|
|
186
|
+
`Downloading ${archiveName}...`
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
await downloadFile(
|
|
190
|
+
artifact.url,
|
|
191
|
+
archivePath
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
console.log(
|
|
195
|
+
`Downloaded: ${archivePath}`
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const verification =
|
|
200
|
+
await verifyArtifact(
|
|
201
|
+
artifact,
|
|
202
|
+
archivePath,
|
|
203
|
+
packageName
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
return {
|
|
207
|
+
...artifact,
|
|
208
|
+
archive: archivePath,
|
|
209
|
+
checksum: verification.checksum,
|
|
210
|
+
verified: verification.verified
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
async function downloadPackage(
|
|
215
|
+
packageName,
|
|
216
|
+
requestedVersion = null
|
|
217
|
+
) {
|
|
218
|
+
const resolved =
|
|
219
|
+
resolvePackage(
|
|
220
|
+
packageName,
|
|
221
|
+
requestedVersion
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
const {
|
|
225
|
+
package: pkg,
|
|
226
|
+
version,
|
|
227
|
+
target,
|
|
228
|
+
artifacts
|
|
229
|
+
} = resolved;
|
|
230
|
+
|
|
231
|
+
console.log("");
|
|
232
|
+
console.log(
|
|
233
|
+
"Naeso Package Download"
|
|
234
|
+
);
|
|
235
|
+
console.log(
|
|
236
|
+
"----------------------"
|
|
237
|
+
);
|
|
238
|
+
console.log(
|
|
239
|
+
`Package: ${pkg.name}`
|
|
240
|
+
);
|
|
241
|
+
console.log(
|
|
242
|
+
`Version: ${version}`
|
|
243
|
+
);
|
|
244
|
+
console.log(
|
|
245
|
+
`Target: ${target}`
|
|
246
|
+
);
|
|
247
|
+
console.log("");
|
|
248
|
+
|
|
249
|
+
const downloaded = {};
|
|
250
|
+
|
|
251
|
+
for (
|
|
252
|
+
const [artifactName, artifact]
|
|
253
|
+
of Object.entries(artifacts)
|
|
254
|
+
) {
|
|
255
|
+
const artifactWithName = {
|
|
256
|
+
...artifact,
|
|
257
|
+
name: artifactName
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
downloaded[artifactName] =
|
|
261
|
+
await downloadArtifact(
|
|
262
|
+
packageName,
|
|
263
|
+
artifactWithName
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
console.log("");
|
|
268
|
+
console.log(
|
|
269
|
+
"All MongoDB artifacts downloaded."
|
|
270
|
+
);
|
|
271
|
+
console.log("");
|
|
272
|
+
|
|
273
|
+
return {
|
|
274
|
+
package: pkg.name,
|
|
275
|
+
version,
|
|
276
|
+
target,
|
|
277
|
+
artifacts: downloaded
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
module.exports = {
|
|
282
|
+
downloadPackage,
|
|
283
|
+
downloadArtifact
|
|
284
|
+
};
|
|
File without changes
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
const { getPackage } = require("./registry");
|
|
2
|
+
const { getTarget } = require("./target");
|
|
3
|
+
|
|
4
|
+
const {
|
|
5
|
+
getLatestVersion,
|
|
6
|
+
getVersionConfig,
|
|
7
|
+
isPackageSupported
|
|
8
|
+
} = require("./compatibility");
|
|
9
|
+
|
|
10
|
+
function resolvePackage(packageName, requestedVersion = null) {
|
|
11
|
+
const pkg = getPackage(packageName);
|
|
12
|
+
|
|
13
|
+
if (!pkg) {
|
|
14
|
+
throw new Error(
|
|
15
|
+
`Package '${packageName}' not found.`
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const target = getTarget();
|
|
20
|
+
|
|
21
|
+
const version =
|
|
22
|
+
requestedVersion ||
|
|
23
|
+
getLatestVersion(pkg);
|
|
24
|
+
|
|
25
|
+
if (!version) {
|
|
26
|
+
throw new Error(
|
|
27
|
+
`No versions available for '${packageName}'.`
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const versionConfig =
|
|
32
|
+
getVersionConfig(pkg, version);
|
|
33
|
+
|
|
34
|
+
if (!versionConfig) {
|
|
35
|
+
throw new Error(
|
|
36
|
+
`Version '${version}' not found for '${packageName}'.`
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (
|
|
41
|
+
!isPackageSupported(
|
|
42
|
+
pkg,
|
|
43
|
+
target.target,
|
|
44
|
+
version
|
|
45
|
+
)
|
|
46
|
+
) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
`${packageName} ${version} does not support ${target.target}.`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const targetConfig =
|
|
53
|
+
versionConfig.config.targets[target.target];
|
|
54
|
+
|
|
55
|
+
if (!targetConfig) {
|
|
56
|
+
throw new Error(
|
|
57
|
+
`${packageName} ${version} does not support ${target.target}.`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/*
|
|
62
|
+
* New multi-artifact package format
|
|
63
|
+
*/
|
|
64
|
+
if (targetConfig.artifacts) {
|
|
65
|
+
const artifacts = {};
|
|
66
|
+
|
|
67
|
+
for (
|
|
68
|
+
const [artifactName, artifactConfig]
|
|
69
|
+
of Object.entries(targetConfig.artifacts)
|
|
70
|
+
) {
|
|
71
|
+
if (!artifactConfig.url) {
|
|
72
|
+
throw new Error(
|
|
73
|
+
`Artifact '${artifactName}' has no download URL.`
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
artifacts[artifactName] = {
|
|
78
|
+
name: artifactName,
|
|
79
|
+
type: artifactConfig.type,
|
|
80
|
+
version: artifactConfig.version || version,
|
|
81
|
+
url: artifactConfig.url,
|
|
82
|
+
sha256Url:
|
|
83
|
+
artifactConfig.sha256Url || null
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
package: pkg,
|
|
89
|
+
version,
|
|
90
|
+
target: target.target,
|
|
91
|
+
artifacts
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/*
|
|
96
|
+
* Backward compatibility with the old
|
|
97
|
+
* single-artifact package format.
|
|
98
|
+
*/
|
|
99
|
+
if (targetConfig.url) {
|
|
100
|
+
return {
|
|
101
|
+
package: pkg,
|
|
102
|
+
version,
|
|
103
|
+
target: target.target,
|
|
104
|
+
|
|
105
|
+
artifacts: {
|
|
106
|
+
default: {
|
|
107
|
+
name: "default",
|
|
108
|
+
type: "tarball",
|
|
109
|
+
version,
|
|
110
|
+
url: targetConfig.url,
|
|
111
|
+
sha256Url:
|
|
112
|
+
targetConfig.sha256Url || null
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
throw new Error(
|
|
119
|
+
`No artifacts defined for ${packageName} ${version} on ${target.target}.`
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
module.exports = {
|
|
124
|
+
resolvePackage
|
|
125
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const os = require("os");
|
|
2
|
+
const { execSync } = require("child_process");
|
|
3
|
+
|
|
4
|
+
function getPlatform() {
|
|
5
|
+
return process.platform;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function getArchitecture() {
|
|
9
|
+
return process.arch;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function getMacOSVersion() {
|
|
13
|
+
if (process.platform !== "darwin") {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
return execSync("sw_vers -productVersion")
|
|
19
|
+
.toString()
|
|
20
|
+
.trim();
|
|
21
|
+
} catch (error) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function getPlatformInfo() {
|
|
27
|
+
return {
|
|
28
|
+
platform: getPlatform(),
|
|
29
|
+
architecture: getArchitecture(),
|
|
30
|
+
macosVersion: getMacOSVersion(),
|
|
31
|
+
hostname: os.hostname(),
|
|
32
|
+
cpuCount: os.cpus().length
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
module.exports = {
|
|
37
|
+
getPlatform,
|
|
38
|
+
getArchitecture,
|
|
39
|
+
getMacOSVersion,
|
|
40
|
+
getPlatformInfo
|
|
41
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
|
|
4
|
+
const REGISTRY_PATH = path.join(
|
|
5
|
+
__dirname,
|
|
6
|
+
"..",
|
|
7
|
+
"registry",
|
|
8
|
+
"packages"
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
function getPackagePath(packageName) {
|
|
12
|
+
return path.join(
|
|
13
|
+
REGISTRY_PATH,
|
|
14
|
+
packageName,
|
|
15
|
+
"package.json"
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function getPackage(packageName) {
|
|
20
|
+
const packagePath = getPackagePath(packageName);
|
|
21
|
+
|
|
22
|
+
if (!fs.existsSync(packagePath)) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
const data = fs.readFileSync(packagePath, "utf8");
|
|
28
|
+
return JSON.parse(data);
|
|
29
|
+
} catch (error) {
|
|
30
|
+
throw new Error(
|
|
31
|
+
`Invalid package definition: ${packageName}`
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function packageExists(packageName) {
|
|
37
|
+
return fs.existsSync(getPackagePath(packageName));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function listPackages() {
|
|
41
|
+
if (!fs.existsSync(REGISTRY_PATH)) {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return fs
|
|
46
|
+
.readdirSync(REGISTRY_PATH, { withFileTypes: true })
|
|
47
|
+
.filter((entry) => entry.isDirectory())
|
|
48
|
+
.map((entry) => entry.name);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function searchPackages(keyword) {
|
|
52
|
+
const packages = listPackages();
|
|
53
|
+
|
|
54
|
+
if (!keyword) {
|
|
55
|
+
return packages;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const search = keyword.toLowerCase();
|
|
59
|
+
|
|
60
|
+
return packages.filter((packageName) =>
|
|
61
|
+
packageName.toLowerCase().includes(search)
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
module.exports = {
|
|
66
|
+
getPackage,
|
|
67
|
+
packageExists,
|
|
68
|
+
listPackages,
|
|
69
|
+
searchPackages
|
|
70
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const {
|
|
2
|
+
getPlatformInfo
|
|
3
|
+
} = require("./platform");
|
|
4
|
+
|
|
5
|
+
function getTarget() {
|
|
6
|
+
const system = getPlatformInfo();
|
|
7
|
+
|
|
8
|
+
let platform;
|
|
9
|
+
|
|
10
|
+
switch (system.platform) {
|
|
11
|
+
case "darwin":
|
|
12
|
+
platform = "macos";
|
|
13
|
+
break;
|
|
14
|
+
|
|
15
|
+
case "linux":
|
|
16
|
+
platform = "linux";
|
|
17
|
+
break;
|
|
18
|
+
|
|
19
|
+
case "win32":
|
|
20
|
+
platform = "windows";
|
|
21
|
+
break;
|
|
22
|
+
|
|
23
|
+
default:
|
|
24
|
+
platform = system.platform;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let architecture;
|
|
28
|
+
|
|
29
|
+
switch (system.architecture) {
|
|
30
|
+
case "x64":
|
|
31
|
+
architecture = "x86_64";
|
|
32
|
+
break;
|
|
33
|
+
|
|
34
|
+
case "arm64":
|
|
35
|
+
architecture = "arm64";
|
|
36
|
+
break;
|
|
37
|
+
|
|
38
|
+
case "ia32":
|
|
39
|
+
architecture = "x86";
|
|
40
|
+
break;
|
|
41
|
+
|
|
42
|
+
default:
|
|
43
|
+
architecture = system.architecture;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
platform,
|
|
48
|
+
architecture,
|
|
49
|
+
target: `${platform}-${architecture}`,
|
|
50
|
+
version: system.macosVersion
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
module.exports = {
|
|
55
|
+
getTarget
|
|
56
|
+
};
|