@ohos-ports/dprint 0.57.4-beta.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 +3 -0
- package/bin.cjs +45 -0
- package/hashes.json +17 -0
- package/install.cjs +61 -0
- package/install_api.cjs +534 -0
- package/package.json +43 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2019 David Sherret
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
package/bin.cjs
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// @ts-check
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const child_process = require("child_process");
|
|
6
|
+
const os = require("os");
|
|
7
|
+
const fs = require("fs");
|
|
8
|
+
|
|
9
|
+
const exePath = path.join(__dirname, os.platform() === "win32" ? "dprint.exe" : "dprint");
|
|
10
|
+
|
|
11
|
+
if (!fs.existsSync(exePath)) {
|
|
12
|
+
try {
|
|
13
|
+
const resolvedExePath = require("./install_api.cjs").runInstall();
|
|
14
|
+
runDprintExe(resolvedExePath);
|
|
15
|
+
} catch (err) {
|
|
16
|
+
if (err !== undefined && typeof err.message === "string") {
|
|
17
|
+
console.error(err.message);
|
|
18
|
+
} else {
|
|
19
|
+
console.error(err);
|
|
20
|
+
}
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
} else {
|
|
24
|
+
runDprintExe(exePath);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** @param exePath {string} */
|
|
28
|
+
function runDprintExe(exePath) {
|
|
29
|
+
const result = child_process.spawnSync(
|
|
30
|
+
exePath,
|
|
31
|
+
process.argv.slice(2),
|
|
32
|
+
{ stdio: "inherit" },
|
|
33
|
+
);
|
|
34
|
+
if (result.error) {
|
|
35
|
+
if (!fs.existsSync(exePath)) {
|
|
36
|
+
throw new Error(
|
|
37
|
+
"Could not find exe at path '" + exePath
|
|
38
|
+
+ "'. Maybe try installing dprint again.",
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
throw result.error;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
process.exit(result.status ?? 1);
|
|
45
|
+
}
|
package/hashes.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"win32-x64": "a8ec907ca5d8209dcd21813ac7bcdaf2566e398f7b8b1357447849be95ffa3f7",
|
|
3
|
+
"win32-arm64": "8184d491b187b939e30d4f5f80c6a6f74d4c11341e01831e808dfd1028b41168",
|
|
4
|
+
"darwin-x64": "68773d368320d1f77839fcf555215a8dc12b1bbe8764e8c447f25e997161b193",
|
|
5
|
+
"darwin-arm64": "0057b28516b3f362b7ca6ca6c8e39a776a19d21532e4f3c3abfe46c2b427a541",
|
|
6
|
+
"linux-x64-glibc": "b74887f9292a5d3f9f1f027e0f4d6797630fb0be9e7e14f9672f72c0b1d7a672",
|
|
7
|
+
"linux-x64-musl": "658126efd9559d62e2cd97118a6b7a726ebd878000c7f49b8cdfa7d452ca40d8",
|
|
8
|
+
"linux-arm64-glibc": "b9560ba52e91b56cfec96d82487e41355981b9c46b172927a2adaefed8d14888",
|
|
9
|
+
"linux-arm64-musl": "bdc1c02243704b0885d124ca02ac2e34e037a0d59ca3bdfe27000c3168daf47a",
|
|
10
|
+
"linux-riscv64-glibc": "90b1e411465dcbdc5cd638601a4523940fc91a5532771539fbbab22f15623d0d",
|
|
11
|
+
"linux-loong64-glibc": "bd6fe25bd25208890657c2390b7f0fdf5fe2add780c0f55728d6651e13ee84b0",
|
|
12
|
+
"linux-loong64-musl": "54666d4b9b96d75bf623d4158a10652ecefe21616f5117003c7adc2706df040f",
|
|
13
|
+
"linux-ppc64-glibc": "59ff33c1ff835de4a0f6d4b173832d18ca9010c30f415e3903e4f60a671da43f",
|
|
14
|
+
"linux-ppc64-musl": "be8a21775a2f9810f2a3751699e820b672889c0c5cbe0012453c348aa7c8253a",
|
|
15
|
+
"android-arm64": "460cda654cda96c740f3a18deb9b1bbe1006d94d4143cd911d6692878754a780",
|
|
16
|
+
"android-x64": "9f059c8d7b38a2c3421323e0536a0f1453428647f01bcc517c04d8d9c36eb656"
|
|
17
|
+
}
|
package/install.cjs
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const os = require("os");
|
|
5
|
+
const api = require("./install_api.cjs");
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Ensures the @ohos-ports/dprint-openharmony-arm64 optional dependency is
|
|
9
|
+
* installed. On HarmonyOS, npm skips optional dependencies whose declared
|
|
10
|
+
* `libc` (glibc/musl) does not match the runtime (HarmonyOS reports no
|
|
11
|
+
* libc at all), so the platform package is installed manually with
|
|
12
|
+
* `--force` when it is missing.
|
|
13
|
+
*/
|
|
14
|
+
function ensureOpenHarmonyPlatformPackage() {
|
|
15
|
+
if (os.platform() !== "openharmony") return;
|
|
16
|
+
const packageName = "@ohos-ports/dprint-openharmony-arm64";
|
|
17
|
+
try {
|
|
18
|
+
require.resolve(packageName + "/package.json");
|
|
19
|
+
return; // already installed
|
|
20
|
+
} catch {
|
|
21
|
+
// not installed yet
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
const manifest = require("./package.json");
|
|
25
|
+
const spec = (manifest.optionalDependencies || {})[packageName];
|
|
26
|
+
if (spec == null) return;
|
|
27
|
+
require("child_process").execFileSync(
|
|
28
|
+
"npm",
|
|
29
|
+
[
|
|
30
|
+
"install",
|
|
31
|
+
packageName + "@" + spec,
|
|
32
|
+
"--force",
|
|
33
|
+
// npm's platform check rejects the package because HarmonyOS reports
|
|
34
|
+
// no libc (the package declares libc glibc/musl), so override the
|
|
35
|
+
// os/cpu/libc that npm uses for the check
|
|
36
|
+
"--os=linux",
|
|
37
|
+
"--cpu=arm64",
|
|
38
|
+
"--libc=glibc",
|
|
39
|
+
"--ignore-scripts",
|
|
40
|
+
"--no-save",
|
|
41
|
+
"--no-audit",
|
|
42
|
+
"--no-fund",
|
|
43
|
+
],
|
|
44
|
+
{ stdio: "inherit", shell: process.platform === "win32" },
|
|
45
|
+
);
|
|
46
|
+
} catch (err) {
|
|
47
|
+
// not fatal: runInstall() below falls back to downloading the binary
|
|
48
|
+
// from the registry tarball directly
|
|
49
|
+
if (process.env.DPRINT_DEBUG === "1") {
|
|
50
|
+
console.warn("[dprint] Failed to install " + packageName + ":", err);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
ensureOpenHarmonyPlatformPackage();
|
|
56
|
+
const exePath = api.runInstall();
|
|
57
|
+
try {
|
|
58
|
+
api.replaceBinEntry(exePath);
|
|
59
|
+
} catch (_err) {
|
|
60
|
+
// ignore - falls back to bin.cjs
|
|
61
|
+
}
|
package/install_api.cjs
ADDED
|
@@ -0,0 +1,534 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const os = require("os");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
/** @type {boolean | undefined} */
|
|
8
|
+
let cachedIsMusl = undefined;
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
replaceBinEntry,
|
|
12
|
+
runInstall() {
|
|
13
|
+
const dprintFileName = os.platform() === "win32" ? "dprint.exe" : "dprint";
|
|
14
|
+
const targetExecutablePath = path.join(
|
|
15
|
+
__dirname,
|
|
16
|
+
dprintFileName,
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
if (fs.existsSync(targetExecutablePath)) {
|
|
20
|
+
return targetExecutablePath;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const target = getTarget();
|
|
24
|
+
const sourceExecutablePath = resolveSourceExecutablePath(target, dprintFileName);
|
|
25
|
+
|
|
26
|
+
if (sourceExecutablePath == null) {
|
|
27
|
+
// the @dprint/<target> optional dependency isn't installed (for example
|
|
28
|
+
// the user ran `npm install --omit=optional`), so download the binary
|
|
29
|
+
// directly from the registry like esbuild does
|
|
30
|
+
downloadExecutable(target, dprintFileName, targetExecutablePath);
|
|
31
|
+
if (os.platform() !== "win32") {
|
|
32
|
+
// chmod +x
|
|
33
|
+
chmodX(targetExecutablePath);
|
|
34
|
+
}
|
|
35
|
+
return targetExecutablePath;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
if (process.env.DPRINT_SIMULATED_READONLY_FILE_SYSTEM === "1") {
|
|
40
|
+
console.warn("Simulating readonly file system for testing.");
|
|
41
|
+
throw new Error("Throwing for testing purposes.");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// in order to make things faster the next time we run and to allow the
|
|
45
|
+
// dprint vscode extension to easily pick this up, copy the executable
|
|
46
|
+
// into the dprint package folder
|
|
47
|
+
hardLinkOrCopy(sourceExecutablePath, targetExecutablePath);
|
|
48
|
+
if (os.platform() !== "win32") {
|
|
49
|
+
// chmod +x
|
|
50
|
+
chmodX(targetExecutablePath);
|
|
51
|
+
}
|
|
52
|
+
return targetExecutablePath;
|
|
53
|
+
} catch (err) {
|
|
54
|
+
// this may fail on readonly file systems... in this case, fall
|
|
55
|
+
// back to using the resolved package path
|
|
56
|
+
if (process.env.DPRINT_DEBUG === "1") {
|
|
57
|
+
console.warn(
|
|
58
|
+
"Failed to copy executable from "
|
|
59
|
+
+ sourceExecutablePath + " to " + targetExecutablePath
|
|
60
|
+
+ ". Using resolved package path instead.",
|
|
61
|
+
err,
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
return sourceExecutablePath;
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Resolves the path to the executable provided by the @dprint/<target>
|
|
71
|
+
* optional dependency, or undefined when that package isn't installed.
|
|
72
|
+
* @param target {string}
|
|
73
|
+
* @param dprintFileName {string}
|
|
74
|
+
* @returns {string | undefined}
|
|
75
|
+
*/
|
|
76
|
+
function resolveSourceExecutablePath(target, dprintFileName) {
|
|
77
|
+
// candidate packages to resolve the executable from, in priority order.
|
|
78
|
+
// The @dprint/openharmony-arm64 package does not exist on npm; the
|
|
79
|
+
// HarmonyOS openharmony-arm64 binary is published under the @ohos-ports
|
|
80
|
+
// scope instead (@ohos-ports/dprint-openharmony-arm64), so try that first.
|
|
81
|
+
const candidates = [];
|
|
82
|
+
if (target === "openharmony-arm64") {
|
|
83
|
+
candidates.push("@ohos-ports/dprint-" + target);
|
|
84
|
+
}
|
|
85
|
+
candidates.push("@dprint/" + target);
|
|
86
|
+
for (const packageName of candidates) {
|
|
87
|
+
try {
|
|
88
|
+
const sourcePackagePath = path.dirname(
|
|
89
|
+
require.resolve(packageName + "/package.json"),
|
|
90
|
+
);
|
|
91
|
+
const sourceExecutablePath = path.join(sourcePackagePath, dprintFileName);
|
|
92
|
+
if (fs.existsSync(sourceExecutablePath)) {
|
|
93
|
+
return sourceExecutablePath;
|
|
94
|
+
}
|
|
95
|
+
} catch {
|
|
96
|
+
// the optional dependency wasn't installed, try the next candidate
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Downloads the binary tarball for the target from the registry and extracts
|
|
104
|
+
* the executable to the destination path.
|
|
105
|
+
* @param target {string}
|
|
106
|
+
* @param dprintFileName {string}
|
|
107
|
+
* @param destinationPath {string}
|
|
108
|
+
*/
|
|
109
|
+
function downloadExecutable(target, dprintFileName, destinationPath) {
|
|
110
|
+
const manifest = require("./package.json");
|
|
111
|
+
const registry = (process.env.npm_config_registry || "https://registry.npmjs.org")
|
|
112
|
+
.replace(/\/+$/, "");
|
|
113
|
+
// npm tarball urls drop the scope from the file name (e.g.
|
|
114
|
+
// https://registry.npmjs.org/@dprint/win32-x64/-/win32-x64-1.0.0.tgz)
|
|
115
|
+
// candidate packages to download the binary tarball from, in priority order.
|
|
116
|
+
// @dprint/openharmony-arm64 does not exist on npm, so for that target the
|
|
117
|
+
// binary is downloaded from @ohos-ports/dprint-openharmony-arm64 instead.
|
|
118
|
+
const candidates = [];
|
|
119
|
+
if (target === "openharmony-arm64") {
|
|
120
|
+
const versionRange = (manifest.optionalDependencies || {})["@ohos-ports/dprint-" + target];
|
|
121
|
+
candidates.push({
|
|
122
|
+
packageName: "@ohos-ports/dprint-" + target,
|
|
123
|
+
// tarball urls need an exact version, so strip any range prefix (^ ~)
|
|
124
|
+
version: versionRange == null ? manifest.version : versionRange.replace(/^[~^]\s*/, ""),
|
|
125
|
+
// hashes.json only contains hashes of official @dprint binaries, so
|
|
126
|
+
// skip the sha256 check for @ohos-ports published binaries
|
|
127
|
+
skipHashVerification: true,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
candidates.push({
|
|
131
|
+
packageName: "@dprint/" + target,
|
|
132
|
+
version: manifest.version,
|
|
133
|
+
skipHashVerification: false,
|
|
134
|
+
});
|
|
135
|
+
let lastError;
|
|
136
|
+
for (const candidate of candidates) {
|
|
137
|
+
const tarballUrl = registry + "/" + candidate.packageName + "/-/"
|
|
138
|
+
+ candidate.packageName.split("/")[1] + "-" + candidate.version + ".tgz";
|
|
139
|
+
console.error("[dprint] Optional dependency " + candidate.packageName
|
|
140
|
+
+ " was not installed. Downloading from " + tarballUrl);
|
|
141
|
+
try {
|
|
142
|
+
const tarballBuffer = downloadBufferSync(tarballUrl);
|
|
143
|
+
// files inside an npm tarball live under the "package/" directory
|
|
144
|
+
const executableBuffer = extractFileFromTarGzip(tarballBuffer, "package/" + dprintFileName);
|
|
145
|
+
if (!candidate.skipHashVerification) {
|
|
146
|
+
verifyExecutableHash(target, executableBuffer);
|
|
147
|
+
}
|
|
148
|
+
atomicWriteFile(destinationPath, executableBuffer);
|
|
149
|
+
return;
|
|
150
|
+
} catch (err) {
|
|
151
|
+
lastError = err;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
throw lastError;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Verifies the downloaded executable against the hash recorded at build time
|
|
159
|
+
* so that we only ever run the exact binary that was published.
|
|
160
|
+
* @param target {string}
|
|
161
|
+
* @param buffer {Buffer}
|
|
162
|
+
*/
|
|
163
|
+
function verifyExecutableHash(target, buffer) {
|
|
164
|
+
let hashes;
|
|
165
|
+
try {
|
|
166
|
+
hashes = require("./hashes.json");
|
|
167
|
+
} catch (err) {
|
|
168
|
+
throw new Error("Could not load hashes.json to verify the downloaded binary: " + (err && err.message || err));
|
|
169
|
+
}
|
|
170
|
+
const expected = hashes[target];
|
|
171
|
+
if (typeof expected !== "string") {
|
|
172
|
+
throw new Error("No known hash for @dprint/" + target + " to verify the download against.");
|
|
173
|
+
}
|
|
174
|
+
const actual = require("crypto").createHash("sha256").update(buffer).digest("hex");
|
|
175
|
+
if (actual !== expected) {
|
|
176
|
+
throw new Error(
|
|
177
|
+
"Integrity check failed for the downloaded @dprint/" + target + " binary.\n"
|
|
178
|
+
+ " Expected sha256: " + expected + "\n"
|
|
179
|
+
+ " Actual sha256: " + actual,
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Downloads a url to a buffer synchronously. Prefer curl since it transparently
|
|
186
|
+
* supports proxies (http_proxy/https_proxy/no_proxy and npm's proxy config),
|
|
187
|
+
* redirects and TLS, then fall back to node for environments without curl.
|
|
188
|
+
* @param url {string}
|
|
189
|
+
* @returns {Buffer}
|
|
190
|
+
*/
|
|
191
|
+
function downloadBufferSync(url) {
|
|
192
|
+
const fromCurl = downloadBufferWithCurl(url);
|
|
193
|
+
return fromCurl != null ? fromCurl : downloadBufferWithNode(url);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* @param url {string}
|
|
198
|
+
* @returns {Buffer | undefined} undefined when curl isn't available
|
|
199
|
+
*/
|
|
200
|
+
function downloadBufferWithCurl(url) {
|
|
201
|
+
// -f: fail on http errors, -s: silent, -S: still show errors, -L: follow redirects
|
|
202
|
+
const args = ["-fsSL"];
|
|
203
|
+
const proxy = process.env.npm_config_https_proxy
|
|
204
|
+
|| process.env.npm_config_proxy
|
|
205
|
+
|| process.env.HTTPS_PROXY
|
|
206
|
+
|| process.env.https_proxy;
|
|
207
|
+
if (proxy) {
|
|
208
|
+
args.push("--proxy", proxy);
|
|
209
|
+
}
|
|
210
|
+
const noProxy = process.env.npm_config_noproxy || process.env.NO_PROXY || process.env.no_proxy;
|
|
211
|
+
if (noProxy) {
|
|
212
|
+
args.push("--noproxy", noProxy);
|
|
213
|
+
}
|
|
214
|
+
args.push("-o", "-", url);
|
|
215
|
+
try {
|
|
216
|
+
return require("child_process").execFileSync("curl", args, { maxBuffer: 512 * 1024 * 1024 });
|
|
217
|
+
} catch (err) {
|
|
218
|
+
if (err && err.code === "ENOENT") {
|
|
219
|
+
// curl isn't installed, fall back to node
|
|
220
|
+
return undefined;
|
|
221
|
+
}
|
|
222
|
+
throw err;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Node has no synchronous https client, so spawn a child node process that
|
|
228
|
+
* streams the response to stdout. Does not support proxies.
|
|
229
|
+
* @param url {string}
|
|
230
|
+
* @returns {Buffer}
|
|
231
|
+
*/
|
|
232
|
+
function downloadBufferWithNode(url) {
|
|
233
|
+
const script = "const https=require('https');"
|
|
234
|
+
+ "function f(u){https.get(u,r=>{"
|
|
235
|
+
+ "const s=r.statusCode;"
|
|
236
|
+
+ "if((s===301||s===302||s===303||s===307||s===308)&&r.headers.location){f(new URL(r.headers.location,u).toString());return;}"
|
|
237
|
+
+ "if(s!==200){console.error('[dprint] Unexpected status code '+s+' downloading '+u);process.exit(1);}"
|
|
238
|
+
+ "r.pipe(process.stdout);"
|
|
239
|
+
+ "}).on('error',e=>{console.error(String(e&&e.message||e));process.exit(1);});}"
|
|
240
|
+
+ "f(process.argv[1]);";
|
|
241
|
+
return require("child_process").execFileSync(
|
|
242
|
+
process.execPath,
|
|
243
|
+
["-e", script, url],
|
|
244
|
+
{ maxBuffer: 512 * 1024 * 1024 },
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Extracts a single file from a gzipped tarball buffer.
|
|
250
|
+
* @param buffer {Buffer}
|
|
251
|
+
* @param subpath {string}
|
|
252
|
+
* @returns {Buffer}
|
|
253
|
+
*/
|
|
254
|
+
function extractFileFromTarGzip(buffer, subpath) {
|
|
255
|
+
const zlib = require("zlib");
|
|
256
|
+
let tar;
|
|
257
|
+
try {
|
|
258
|
+
tar = zlib.gunzipSync(buffer);
|
|
259
|
+
} catch (err) {
|
|
260
|
+
throw new Error("Invalid gzip data in downloaded tarball: " + (err && err.message || err));
|
|
261
|
+
}
|
|
262
|
+
let offset = 0;
|
|
263
|
+
while (offset < tar.length) {
|
|
264
|
+
const name = readTarString(tar, offset, 100);
|
|
265
|
+
const size = parseInt(readTarString(tar, offset + 124, 12).trim(), 8);
|
|
266
|
+
offset += 512;
|
|
267
|
+
if (!isNaN(size)) {
|
|
268
|
+
if (name === subpath) {
|
|
269
|
+
return tar.subarray(offset, offset + size);
|
|
270
|
+
}
|
|
271
|
+
// entries are padded to 512 byte boundaries
|
|
272
|
+
offset += (size + 511) & ~511;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
throw new Error("Could not find " + JSON.stringify(subpath) + " in downloaded tarball");
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* @param buffer {Buffer}
|
|
280
|
+
* @param offset {number}
|
|
281
|
+
* @param length {number}
|
|
282
|
+
*/
|
|
283
|
+
function readTarString(buffer, offset, length) {
|
|
284
|
+
return buffer.toString("utf8", offset, offset + length).replace(/\0.*$/, "");
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* @param destinationPath {string}
|
|
289
|
+
* @param buffer {Buffer}
|
|
290
|
+
*/
|
|
291
|
+
function atomicWriteFile(destinationPath, buffer) {
|
|
292
|
+
const crypto = require("crypto");
|
|
293
|
+
const rand = crypto.randomBytes(4).toString("hex");
|
|
294
|
+
const tempFilePath = destinationPath + "." + rand;
|
|
295
|
+
fs.writeFileSync(tempFilePath, buffer);
|
|
296
|
+
try {
|
|
297
|
+
fs.renameSync(tempFilePath, destinationPath);
|
|
298
|
+
} catch (err) {
|
|
299
|
+
// will maybe throw when another process had already done this
|
|
300
|
+
// so just ignore and delete the created temporary file
|
|
301
|
+
try {
|
|
302
|
+
fs.unlinkSync(tempFilePath);
|
|
303
|
+
} catch (_err2) {
|
|
304
|
+
// ignore
|
|
305
|
+
}
|
|
306
|
+
throw err;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/** @filePath {string} */
|
|
311
|
+
function chmodX(filePath) {
|
|
312
|
+
const fd = fs.openSync(filePath, "r");
|
|
313
|
+
try {
|
|
314
|
+
const perms = fs.fstatSync(fd).mode;
|
|
315
|
+
fs.fchmodSync(fd, perms | 0o111);
|
|
316
|
+
} finally {
|
|
317
|
+
fs.closeSync(fd);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function getTarget() {
|
|
322
|
+
const platform = os.platform();
|
|
323
|
+
if (platform === "linux") {
|
|
324
|
+
return platform + "-" + getArch() + "-" + getLinuxFamily();
|
|
325
|
+
} else {
|
|
326
|
+
return platform + "-" + getArch();
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function getArch() {
|
|
331
|
+
const arch = os.arch();
|
|
332
|
+
if (arch !== "arm64" && arch !== "x64" && arch !== "riscv64" && arch !== "loong64" && arch !== "ppc64") {
|
|
333
|
+
throw new Error("Unsupported architecture " + os.arch() + ". Only x64, arm64, riscv64, loong64 and ppc64 binaries are available.");
|
|
334
|
+
}
|
|
335
|
+
return arch;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function getLinuxFamily() {
|
|
339
|
+
return getIsMusl() ? "musl" : "glibc";
|
|
340
|
+
|
|
341
|
+
function getIsMusl() {
|
|
342
|
+
// code adapted from https://github.com/napi-rs/package-template/blob/main/index.js
|
|
343
|
+
// which is in turn based on https://github.com/lovell/detect-libc (Apache 2.0 license)
|
|
344
|
+
if (cachedIsMusl == null) {
|
|
345
|
+
cachedIsMusl = innerGet();
|
|
346
|
+
}
|
|
347
|
+
return cachedIsMusl;
|
|
348
|
+
|
|
349
|
+
function innerGet() {
|
|
350
|
+
try {
|
|
351
|
+
if (os.platform() !== "linux") {
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
354
|
+
let musl = isMuslFromFilesystem();
|
|
355
|
+
if (musl == null) {
|
|
356
|
+
musl = isMuslFromReport();
|
|
357
|
+
}
|
|
358
|
+
if (musl == null) {
|
|
359
|
+
musl = isMuslFromChildProcess();
|
|
360
|
+
}
|
|
361
|
+
return musl;
|
|
362
|
+
} catch (err) {
|
|
363
|
+
// just in case
|
|
364
|
+
console.warn("Error checking if musl.", err);
|
|
365
|
+
return false;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function isMuslFromFilesystem() {
|
|
370
|
+
try {
|
|
371
|
+
return fs.readFileSync("/usr/bin/ldd", "utf-8").includes("musl");
|
|
372
|
+
} catch {
|
|
373
|
+
return null;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
function isMuslFromReport() {
|
|
378
|
+
if (typeof process.report?.getReport !== "function") {
|
|
379
|
+
return null;
|
|
380
|
+
}
|
|
381
|
+
// excludeNetwork avoids a slow reverse DNS lookup while generating the
|
|
382
|
+
// report, but it's a global flag so restore it once we're done
|
|
383
|
+
const originalExcludeNetwork = process.report.excludeNetwork;
|
|
384
|
+
let rawReport;
|
|
385
|
+
try {
|
|
386
|
+
process.report.excludeNetwork = true;
|
|
387
|
+
rawReport = process.report.getReport();
|
|
388
|
+
} finally {
|
|
389
|
+
process.report.excludeNetwork = originalExcludeNetwork;
|
|
390
|
+
}
|
|
391
|
+
const report = typeof rawReport === "string" ? JSON.parse(rawReport) : rawReport;
|
|
392
|
+
if (!report) {
|
|
393
|
+
return null;
|
|
394
|
+
}
|
|
395
|
+
if (report.header && report.header.glibcVersionRuntime) {
|
|
396
|
+
return false;
|
|
397
|
+
}
|
|
398
|
+
if (Array.isArray(report.sharedObjects)) {
|
|
399
|
+
return report.sharedObjects.some(isFileMusl);
|
|
400
|
+
}
|
|
401
|
+
return false;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
function isMuslFromChildProcess() {
|
|
405
|
+
try {
|
|
406
|
+
return require("child_process").execSync("ldd --version", { encoding: "utf8" }).includes("musl");
|
|
407
|
+
} catch {
|
|
408
|
+
return false;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
function isFileMusl(f) {
|
|
413
|
+
return f.includes("libc.musl-") || f.includes("ld-musl-");
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Replaces the bin entry in node_modules/.bin to point directly at the
|
|
420
|
+
* native binary, avoiding Node.js startup overhead on each invocation.
|
|
421
|
+
* @param exePath {string}
|
|
422
|
+
*/
|
|
423
|
+
function replaceBinEntry(exePath) {
|
|
424
|
+
const binDir = findBinDir();
|
|
425
|
+
if (binDir === undefined) return;
|
|
426
|
+
|
|
427
|
+
const relative = path.relative(binDir, exePath);
|
|
428
|
+
if (os.platform() === "win32") {
|
|
429
|
+
// rewrite .cmd and .ps1 wrappers to invoke the native binary directly
|
|
430
|
+
fs.writeFileSync(
|
|
431
|
+
path.join(binDir, "dprint.cmd"),
|
|
432
|
+
"@\"%~dp0" + relative + "\" %*\r\n",
|
|
433
|
+
);
|
|
434
|
+
fs.writeFileSync(
|
|
435
|
+
path.join(binDir, "dprint.ps1"),
|
|
436
|
+
"& \"$PSScriptRoot/" + relative.replace(/\\/g, "/")
|
|
437
|
+
+ "\" $args\r\nexit $LASTEXITCODE\r\n",
|
|
438
|
+
);
|
|
439
|
+
} else {
|
|
440
|
+
// replace symlink to point directly at the native binary
|
|
441
|
+
const binDprint = path.join(binDir, "dprint");
|
|
442
|
+
fs.unlinkSync(binDprint);
|
|
443
|
+
fs.symlinkSync(relative, binDprint);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
function findBinDir() {
|
|
448
|
+
// For global installs, npm sets npm_config_global=true and npm_config_prefix
|
|
449
|
+
// to the install prefix. The bin dir is {prefix}/bin on Linux/Mac or
|
|
450
|
+
// {prefix} on Windows (e.g. %APPDATA%\npm).
|
|
451
|
+
if (process.env.npm_config_global === "true") {
|
|
452
|
+
const prefix = process.env.npm_config_prefix;
|
|
453
|
+
if (prefix) {
|
|
454
|
+
const binDir = os.platform() === "win32"
|
|
455
|
+
? prefix
|
|
456
|
+
: path.join(prefix, "bin");
|
|
457
|
+
if (isBinDirForThisPackage(binDir)) {
|
|
458
|
+
return binDir;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// For local installs, walk up looking for node_modules/.bin
|
|
464
|
+
let dir = __dirname;
|
|
465
|
+
for (let i = 0; i < 64; i++) {
|
|
466
|
+
const parent = path.dirname(dir);
|
|
467
|
+
if (parent === dir) {
|
|
468
|
+
break;
|
|
469
|
+
}
|
|
470
|
+
if (path.basename(parent) === "node_modules") {
|
|
471
|
+
const binDir = path.join(parent, ".bin");
|
|
472
|
+
if (isBinDirForThisPackage(binDir)) {
|
|
473
|
+
return binDir;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
dir = parent;
|
|
477
|
+
}
|
|
478
|
+
return undefined;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
function isBinDirForThisPackage(binDir) {
|
|
482
|
+
try {
|
|
483
|
+
if (os.platform() === "win32") {
|
|
484
|
+
// verify the .cmd wrapper references our bin.cjs
|
|
485
|
+
const content = fs.readFileSync(
|
|
486
|
+
path.join(binDir, "dprint.cmd"),
|
|
487
|
+
"utf8",
|
|
488
|
+
);
|
|
489
|
+
return content.includes("bin.cjs");
|
|
490
|
+
} else {
|
|
491
|
+
// verify the symlink points into our package directory
|
|
492
|
+
const linkTarget = fs.readlinkSync(path.join(binDir, "dprint"));
|
|
493
|
+
const resolved = path.resolve(binDir, linkTarget);
|
|
494
|
+
return resolved.endsWith("bin.cjs");
|
|
495
|
+
}
|
|
496
|
+
} catch (_err) {
|
|
497
|
+
return false;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* @param sourcePath {string}
|
|
503
|
+
* @param destinationPath {string}
|
|
504
|
+
*/
|
|
505
|
+
function hardLinkOrCopy(sourcePath, destinationPath) {
|
|
506
|
+
try {
|
|
507
|
+
fs.linkSync(sourcePath, destinationPath);
|
|
508
|
+
} catch {
|
|
509
|
+
atomicCopyFile(sourcePath, destinationPath);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* @param sourcePath {string}
|
|
515
|
+
* @param destinationPath {string}
|
|
516
|
+
*/
|
|
517
|
+
function atomicCopyFile(sourcePath, destinationPath) {
|
|
518
|
+
const crypto = require("crypto");
|
|
519
|
+
const rand = crypto.randomBytes(4).toString("hex");
|
|
520
|
+
const tempFilePath = destinationPath + "." + rand;
|
|
521
|
+
fs.copyFileSync(sourcePath, tempFilePath);
|
|
522
|
+
try {
|
|
523
|
+
fs.renameSync(tempFilePath, destinationPath);
|
|
524
|
+
} catch (err) {
|
|
525
|
+
// will maybe throw when another process had already done this
|
|
526
|
+
// so just ignore and delete the created temporary file
|
|
527
|
+
try {
|
|
528
|
+
fs.unlinkSync(tempFilePath);
|
|
529
|
+
} catch (_err2) {
|
|
530
|
+
// ignore
|
|
531
|
+
}
|
|
532
|
+
throw err;
|
|
533
|
+
}
|
|
534
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ohos-ports/dprint",
|
|
3
|
+
"version": "0.57.4-beta.0",
|
|
4
|
+
"description": "Pluggable and configurable code formatting platform written in Rust.",
|
|
5
|
+
"bin": "bin.cjs",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/ohos-ports/ohos-ports.git",
|
|
9
|
+
"directory": "ports/dprint/0.57.4"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"code",
|
|
13
|
+
"formatter"
|
|
14
|
+
],
|
|
15
|
+
"author": "David Sherret",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://github.com/ohos-ports/ohos-ports/issues"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://github.com/ohos-ports/ohos-ports#readme",
|
|
21
|
+
"preferUnplugged": true,
|
|
22
|
+
"scripts": {
|
|
23
|
+
"postinstall": "node ./install.cjs"
|
|
24
|
+
},
|
|
25
|
+
"optionalDependencies": {
|
|
26
|
+
"@dprint/win32-x64": "0.57.4",
|
|
27
|
+
"@dprint/win32-arm64": "0.57.4",
|
|
28
|
+
"@dprint/darwin-x64": "0.57.4",
|
|
29
|
+
"@dprint/darwin-arm64": "0.57.4",
|
|
30
|
+
"@dprint/linux-x64-glibc": "0.57.4",
|
|
31
|
+
"@dprint/linux-x64-musl": "0.57.4",
|
|
32
|
+
"@dprint/linux-arm64-glibc": "0.57.4",
|
|
33
|
+
"@dprint/linux-arm64-musl": "0.57.4",
|
|
34
|
+
"@dprint/linux-riscv64-glibc": "0.57.4",
|
|
35
|
+
"@dprint/linux-loong64-glibc": "0.57.4",
|
|
36
|
+
"@dprint/linux-loong64-musl": "0.57.4",
|
|
37
|
+
"@dprint/linux-ppc64-glibc": "0.57.4",
|
|
38
|
+
"@dprint/linux-ppc64-musl": "0.57.4",
|
|
39
|
+
"@dprint/android-arm64": "0.57.4",
|
|
40
|
+
"@dprint/android-x64": "0.57.4",
|
|
41
|
+
"@ohos-ports/dprint-openharmony-arm64": "^0.57.4-beta.1"
|
|
42
|
+
}
|
|
43
|
+
}
|