@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 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
@@ -0,0 +1,3 @@
1
+ # dprint
2
+
3
+ npm CLI distribution for [dprint](https://dprint.dev)—a pluggable and configurable code formatting platform.
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
+ }
@@ -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
+ }