@hanzo/dev 3.0.1 → 3.0.2
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 +358 -0
- package/bin/dev.js +90 -97
- package/package.json +15 -27
- package/postinstall.js +229 -305
- package/scripts/preinstall.js +69 -0
- package/scripts/windows-cleanup.ps1 +31 -0
package/bin/dev.js
CHANGED
|
@@ -6,6 +6,7 @@ import { fileURLToPath } from "url";
|
|
|
6
6
|
import { platform as nodePlatform, arch as nodeArch } from "os";
|
|
7
7
|
import { execSync } from "child_process";
|
|
8
8
|
import { get as httpsGet } from "https";
|
|
9
|
+
import { runPostinstall } from "../postinstall.js";
|
|
9
10
|
|
|
10
11
|
// __dirname equivalent in ESM
|
|
11
12
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -13,23 +14,15 @@ const __dirname = path.dirname(__filename);
|
|
|
13
14
|
|
|
14
15
|
const { platform, arch } = process;
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
// When users run via `npx @hanzo/dev`, we must always execute our
|
|
18
|
-
// packaged native binary by absolute path to avoid PATH collisions.
|
|
19
|
-
|
|
20
|
-
const isWSL = () => {
|
|
17
|
+
function isWSL() {
|
|
21
18
|
if (platform !== "linux") return false;
|
|
22
19
|
try {
|
|
23
|
-
const
|
|
24
|
-
const rel = os.release().toLowerCase();
|
|
25
|
-
if (rel.includes("microsoft")) return true;
|
|
26
|
-
const fs = require("fs");
|
|
27
|
-
const txt = fs.readFileSync("/proc/version", "utf8").toLowerCase();
|
|
20
|
+
const txt = readFileSync("/proc/version", "utf8").toLowerCase();
|
|
28
21
|
return txt.includes("microsoft");
|
|
29
22
|
} catch {
|
|
30
23
|
return false;
|
|
31
24
|
}
|
|
32
|
-
}
|
|
25
|
+
}
|
|
33
26
|
|
|
34
27
|
let targetTriple = null;
|
|
35
28
|
switch (platform) {
|
|
@@ -77,12 +70,11 @@ if (!targetTriple) {
|
|
|
77
70
|
throw new Error(`Unsupported platform: ${platform} (${arch})`);
|
|
78
71
|
}
|
|
79
72
|
|
|
80
|
-
//
|
|
73
|
+
// Binary names for Hanzo dev
|
|
81
74
|
let binaryPath = path.join(__dirname, "..", "bin", `dev-${targetTriple}`);
|
|
82
|
-
let legacyBinaryPath = path.join(__dirname, "..", "bin", `
|
|
75
|
+
let legacyBinaryPath = path.join(__dirname, "..", "bin", `code-${targetTriple}`);
|
|
83
76
|
|
|
84
|
-
|
|
85
|
-
import { existsSync, chmodSync, statSync, openSync, readSync, closeSync, mkdirSync, copyFileSync, readFileSync, unlinkSync } from "fs";
|
|
77
|
+
import { existsSync, chmodSync, statSync, openSync, readSync, closeSync, mkdirSync, copyFileSync, readFileSync, unlinkSync, createWriteStream } from "fs";
|
|
86
78
|
|
|
87
79
|
const validateBinary = (p) => {
|
|
88
80
|
try {
|
|
@@ -130,23 +122,22 @@ const getCacheDir = (version) => {
|
|
|
130
122
|
};
|
|
131
123
|
|
|
132
124
|
const getCachedBinaryPath = (version) => {
|
|
133
|
-
const isWin = nodePlatform() === "win32";
|
|
134
|
-
const ext = isWin ? ".exe" : "";
|
|
135
125
|
const cacheDir = getCacheDir(version);
|
|
136
|
-
return path.join(cacheDir, `dev-${targetTriple}
|
|
126
|
+
return path.join(cacheDir, `dev-${targetTriple}`);
|
|
137
127
|
};
|
|
138
128
|
|
|
129
|
+
let lastBootstrapError = null;
|
|
130
|
+
|
|
139
131
|
const httpsDownload = (url, dest) => new Promise((resolve, reject) => {
|
|
140
132
|
const req = httpsGet(url, (res) => {
|
|
141
133
|
const status = res.statusCode || 0;
|
|
142
134
|
if (status >= 300 && status < 400 && res.headers.location) {
|
|
143
|
-
// follow one redirect recursively
|
|
144
135
|
return resolve(httpsDownload(res.headers.location, dest));
|
|
145
136
|
}
|
|
146
137
|
if (status !== 200) {
|
|
147
138
|
return reject(new Error(`HTTP ${status}`));
|
|
148
139
|
}
|
|
149
|
-
const out =
|
|
140
|
+
const out = createWriteStream(dest);
|
|
150
141
|
res.pipe(out);
|
|
151
142
|
out.on("finish", () => out.close(resolve));
|
|
152
143
|
out.on("error", (e) => {
|
|
@@ -165,29 +156,30 @@ const httpsDownload = (url, dest) => new Promise((resolve, reject) => {
|
|
|
165
156
|
|
|
166
157
|
const tryBootstrapBinary = async () => {
|
|
167
158
|
try {
|
|
168
|
-
// 1) Read our published version
|
|
169
159
|
const pkg = JSON.parse(readFileSync(path.join(__dirname, "..", "package.json"), "utf8"));
|
|
170
160
|
const version = pkg.version;
|
|
171
161
|
|
|
172
162
|
const binDir = path.join(__dirname, "..", "bin");
|
|
173
163
|
if (!existsSync(binDir)) mkdirSync(binDir, { recursive: true });
|
|
174
164
|
|
|
175
|
-
//
|
|
165
|
+
// Fast path: user cache
|
|
176
166
|
const cachePath = getCachedBinaryPath(version);
|
|
177
167
|
if (existsSync(cachePath)) {
|
|
178
168
|
const v = validateBinary(cachePath);
|
|
179
169
|
if (v.ok) {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
170
|
+
if (platform !== "win32") {
|
|
171
|
+
copyFileSync(cachePath, binaryPath);
|
|
172
|
+
try { chmodSync(binaryPath, 0o755); } catch {}
|
|
173
|
+
}
|
|
174
|
+
return true;
|
|
183
175
|
}
|
|
184
176
|
}
|
|
185
177
|
|
|
186
|
-
//
|
|
178
|
+
// Try platform package (if present)
|
|
187
179
|
try {
|
|
188
180
|
const req = (await import("module")).createRequire(import.meta.url);
|
|
189
181
|
const name = (() => {
|
|
190
|
-
if (platform === "win32") return "@
|
|
182
|
+
if (platform === "win32") return "@hanzo/dev-win32-x64";
|
|
191
183
|
const plt = nodePlatform();
|
|
192
184
|
const cpu = nodeArch();
|
|
193
185
|
if (plt === "darwin" && cpu === "arm64") return "@hanzo/dev-darwin-arm64";
|
|
@@ -200,31 +192,41 @@ const tryBootstrapBinary = async () => {
|
|
|
200
192
|
try {
|
|
201
193
|
const pkgJson = req.resolve(`${name}/package.json`);
|
|
202
194
|
const pkgDir = path.dirname(pkgJson);
|
|
203
|
-
const src = path.join(pkgDir, "bin", `dev-${targetTriple}
|
|
195
|
+
const src = path.join(pkgDir, "bin", `dev-${targetTriple}`);
|
|
204
196
|
if (existsSync(src)) {
|
|
205
|
-
copyFileSync(src,
|
|
206
|
-
if (platform !== "win32")
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
197
|
+
copyFileSync(src, cachePath);
|
|
198
|
+
if (platform !== "win32") {
|
|
199
|
+
copyFileSync(cachePath, binaryPath);
|
|
200
|
+
try { chmodSync(binaryPath, 0o755); } catch {}
|
|
201
|
+
}
|
|
202
|
+
return true;
|
|
210
203
|
}
|
|
211
204
|
} catch { /* ignore and fall back */ }
|
|
212
205
|
}
|
|
213
206
|
} catch { /* ignore */ }
|
|
214
207
|
|
|
215
|
-
//
|
|
208
|
+
// Download from GitHub release
|
|
216
209
|
const isWin = platform === "win32";
|
|
210
|
+
// Use 'code-*' binary names since that's what the release produces
|
|
211
|
+
const binaryName = `code-${targetTriple}`;
|
|
217
212
|
const archiveName = isWin
|
|
218
|
-
?
|
|
219
|
-
: (() => { try { execSync("zstd --version", { stdio: "ignore", shell: true }); return
|
|
213
|
+
? `${binaryName}.zip`
|
|
214
|
+
: (() => { try { execSync("zstd --version", { stdio: "ignore", shell: true }); return `${binaryName}.zst`; } catch { return `${binaryName}.tar.gz`; } })();
|
|
220
215
|
const url = `https://github.com/hanzoai/dev/releases/download/v${version}/${archiveName}`;
|
|
221
216
|
const tmp = path.join(binDir, `.${archiveName}.part`);
|
|
222
217
|
return httpsDownload(url, tmp)
|
|
223
218
|
.then(() => {
|
|
224
219
|
if (isWin) {
|
|
225
220
|
try {
|
|
226
|
-
const
|
|
227
|
-
|
|
221
|
+
const sysRoot = process.env.SystemRoot || process.env.windir || 'C:\\Windows';
|
|
222
|
+
const psFull = path.join(sysRoot, 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe');
|
|
223
|
+
const unzipDest = getCacheDir(version);
|
|
224
|
+
const psCmd = `Expand-Archive -Path '${tmp}' -DestinationPath '${unzipDest}' -Force`;
|
|
225
|
+
let ok = false;
|
|
226
|
+
try { execSync(`"${psFull}" -NoProfile -NonInteractive -Command "${psCmd}"`, { stdio: 'ignore' }); ok = true; } catch {}
|
|
227
|
+
if (!ok) { try { execSync(`powershell -NoProfile -NonInteractive -Command "${psCmd}"`, { stdio: 'ignore' }); ok = true; } catch {} }
|
|
228
|
+
if (!ok) { try { execSync(`pwsh -NoProfile -NonInteractive -Command "${psCmd}"`, { stdio: 'ignore' }); ok = true; } catch {} }
|
|
229
|
+
if (!ok) { execSync(`tar -xf "${tmp}" -C "${unzipDest}"`, { stdio: 'ignore', shell: true }); }
|
|
228
230
|
} catch (e) {
|
|
229
231
|
throw new Error(`failed to unzip: ${e.message}`);
|
|
230
232
|
} finally { try { unlinkSync(tmp); } catch {} }
|
|
@@ -239,48 +241,75 @@ const tryBootstrapBinary = async () => {
|
|
|
239
241
|
try { unlinkSync(tmp); } catch {}
|
|
240
242
|
}
|
|
241
243
|
}
|
|
242
|
-
|
|
244
|
+
if (platform !== "win32") {
|
|
245
|
+
try { copyFileSync(binaryPath, cachePath); } catch {}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const v = validateBinary(platform === "win32" ? cachePath : binaryPath);
|
|
243
249
|
if (!v.ok) throw new Error(`invalid binary (${v.reason})`);
|
|
244
|
-
if (platform !== "win32") chmodSync(binaryPath, 0o755);
|
|
245
|
-
try { copyFileSync(binaryPath, cachePath); } catch {}
|
|
250
|
+
if (platform !== "win32") try { chmodSync(binaryPath, 0o755); } catch {}
|
|
246
251
|
return true;
|
|
247
252
|
})
|
|
248
|
-
.catch((
|
|
253
|
+
.catch((e) => { lastBootstrapError = e; return false; });
|
|
249
254
|
} catch {
|
|
250
255
|
return false;
|
|
251
256
|
}
|
|
252
257
|
};
|
|
253
258
|
|
|
254
|
-
// If missing, attempt to bootstrap into place
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
259
|
+
// If missing, attempt to bootstrap into place
|
|
260
|
+
let binaryReady = existsSync(binaryPath) || existsSync(legacyBinaryPath);
|
|
261
|
+
if (!binaryReady) {
|
|
262
|
+
let runtimePostinstallError = null;
|
|
263
|
+
try {
|
|
264
|
+
await runPostinstall({ invokedByRuntime: true, skipGlobalAlias: true });
|
|
265
|
+
} catch (err) {
|
|
266
|
+
runtimePostinstallError = err;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
binaryReady = existsSync(binaryPath) || existsSync(legacyBinaryPath);
|
|
270
|
+
if (!binaryReady) {
|
|
271
|
+
const ok = await tryBootstrapBinary();
|
|
272
|
+
if (!ok) {
|
|
273
|
+
if (runtimePostinstallError && !lastBootstrapError) {
|
|
274
|
+
lastBootstrapError = runtimePostinstallError;
|
|
275
|
+
}
|
|
276
|
+
if (existsSync(legacyBinaryPath) && !existsSync(binaryPath)) {
|
|
277
|
+
binaryPath = legacyBinaryPath;
|
|
278
|
+
}
|
|
261
279
|
}
|
|
262
280
|
}
|
|
263
281
|
}
|
|
264
282
|
|
|
265
|
-
//
|
|
266
|
-
|
|
267
|
-
|
|
283
|
+
// Prefer cached binary when available
|
|
284
|
+
try {
|
|
285
|
+
const pkg = JSON.parse(readFileSync(path.join(__dirname, "..", "package.json"), "utf8"));
|
|
286
|
+
const version = pkg.version;
|
|
287
|
+
const cached = getCachedBinaryPath(version);
|
|
288
|
+
const v = existsSync(cached) ? validateBinary(cached) : { ok: false };
|
|
289
|
+
if (v.ok) {
|
|
290
|
+
binaryPath = cached;
|
|
291
|
+
} else if (!existsSync(binaryPath) && existsSync(legacyBinaryPath)) {
|
|
292
|
+
binaryPath = legacyBinaryPath;
|
|
293
|
+
}
|
|
294
|
+
} catch {
|
|
295
|
+
// ignore
|
|
268
296
|
}
|
|
269
297
|
|
|
270
|
-
// Check if binary exists and try to fix permissions if needed
|
|
271
|
-
// fs imports are above; keep for readability if tree-shaken by bundlers
|
|
272
298
|
import { spawnSync } from "child_process";
|
|
273
299
|
if (existsSync(binaryPath)) {
|
|
274
300
|
try {
|
|
275
|
-
// Ensure binary is executable on Unix-like systems
|
|
276
301
|
if (platform !== "win32") {
|
|
277
302
|
chmodSync(binaryPath, 0o755);
|
|
278
303
|
}
|
|
279
304
|
} catch (e) {
|
|
280
|
-
// Ignore permission errors
|
|
305
|
+
// Ignore permission errors
|
|
281
306
|
}
|
|
282
307
|
} else {
|
|
283
308
|
console.error(`Binary not found: ${binaryPath}`);
|
|
309
|
+
if (lastBootstrapError) {
|
|
310
|
+
const msg = (lastBootstrapError && (lastBootstrapError.message || String(lastBootstrapError))) || 'unknown bootstrap error';
|
|
311
|
+
console.error(`Bootstrap error: ${msg}`);
|
|
312
|
+
}
|
|
284
313
|
console.error(`Please try reinstalling the package:`);
|
|
285
314
|
console.error(` npm uninstall -g @hanzo/dev`);
|
|
286
315
|
console.error(` npm install -g @hanzo/dev`);
|
|
@@ -292,9 +321,6 @@ if (existsSync(binaryPath)) {
|
|
|
292
321
|
process.exit(1);
|
|
293
322
|
}
|
|
294
323
|
|
|
295
|
-
// Lightweight header validation to provide clearer errors before spawn
|
|
296
|
-
// Reuse the validateBinary helper defined above in the bootstrap section.
|
|
297
|
-
|
|
298
324
|
const validation = validateBinary(binaryPath);
|
|
299
325
|
if (!validation.ok) {
|
|
300
326
|
console.error(`The native binary at ${binaryPath} appears invalid: ${validation.reason}`);
|
|
@@ -313,47 +339,25 @@ if (!validation.ok) {
|
|
|
313
339
|
process.exit(1);
|
|
314
340
|
}
|
|
315
341
|
|
|
316
|
-
// If running under npx/npm, emit a concise notice
|
|
342
|
+
// If running under npx/npm, emit a concise notice
|
|
317
343
|
try {
|
|
318
344
|
const ua = process.env.npm_config_user_agent || "";
|
|
319
345
|
const isNpx = ua.includes("npx");
|
|
320
346
|
if (isNpx && process.stderr && process.stderr.isTTY) {
|
|
321
|
-
|
|
322
|
-
let otherCode = "";
|
|
323
|
-
try {
|
|
324
|
-
const cmd = process.platform === "win32" ? "where code" : "command -v code || which code || true";
|
|
325
|
-
const out = spawnSync(process.platform === "win32" ? "cmd" : "bash", [
|
|
326
|
-
process.platform === "win32" ? "/c" : "-lc",
|
|
327
|
-
cmd,
|
|
328
|
-
], { encoding: "utf8" });
|
|
329
|
-
const line = (out.stdout || "").split(/\r?\n/).map((s) => s.trim()).filter(Boolean)[0];
|
|
330
|
-
if (line && !line.includes("@hanzo/dev")) {
|
|
331
|
-
otherCode = line;
|
|
332
|
-
}
|
|
333
|
-
} catch {}
|
|
334
|
-
if (otherCode) {
|
|
335
|
-
console.error(`@hanzo/dev: running bundled binary -> ${binaryPath}`);
|
|
336
|
-
console.error(`Note: a different 'dev' exists at ${otherCode}; not delegating.`);
|
|
337
|
-
} else {
|
|
338
|
-
console.error(`@hanzo/dev: running bundled binary -> ${binaryPath}`);
|
|
339
|
-
}
|
|
347
|
+
console.error(`@hanzo/dev: running bundled binary -> ${binaryPath}`);
|
|
340
348
|
}
|
|
341
349
|
} catch {}
|
|
342
350
|
|
|
343
|
-
// Use an asynchronous spawn instead of spawnSync so that Node is able to
|
|
344
|
-
// respond to signals (e.g. Ctrl-C / SIGINT) while the native binary is
|
|
345
|
-
// executing. This allows us to forward those signals to the child process
|
|
346
|
-
// and guarantees that when either the child terminates or the parent
|
|
347
|
-
// receives a fatal signal, both processes exit in a predictable manner.
|
|
348
351
|
const { spawn } = await import("child_process");
|
|
349
352
|
|
|
353
|
+
process.env.DEV_BINARY_PATH = binaryPath;
|
|
354
|
+
|
|
350
355
|
const child = spawn(binaryPath, process.argv.slice(2), {
|
|
351
356
|
stdio: "inherit",
|
|
352
|
-
env: { ...process.env,
|
|
357
|
+
env: { ...process.env, DEV_MANAGED_BY_NPM: "1", DEV_BINARY_PATH: binaryPath },
|
|
353
358
|
});
|
|
354
359
|
|
|
355
360
|
child.on("error", (err) => {
|
|
356
|
-
// Typically triggered when the binary is missing or not executable.
|
|
357
361
|
const code = err && err.code;
|
|
358
362
|
if (code === 'EACCES') {
|
|
359
363
|
console.error(`Permission denied: ${binaryPath}`);
|
|
@@ -377,10 +381,6 @@ child.on("error", (err) => {
|
|
|
377
381
|
process.exit(1);
|
|
378
382
|
});
|
|
379
383
|
|
|
380
|
-
// Forward common termination signals to the child so that it shuts down
|
|
381
|
-
// gracefully. In the handler we temporarily disable the default behavior of
|
|
382
|
-
// exiting immediately; once the child has been signaled we simply wait for
|
|
383
|
-
// its exit event which will in turn terminate the parent (see below).
|
|
384
384
|
const forwardSignal = (signal) => {
|
|
385
385
|
if (child.killed) {
|
|
386
386
|
return;
|
|
@@ -396,11 +396,6 @@ const forwardSignal = (signal) => {
|
|
|
396
396
|
process.on(sig, () => forwardSignal(sig));
|
|
397
397
|
});
|
|
398
398
|
|
|
399
|
-
// When the child exits, mirror its termination reason in the parent so that
|
|
400
|
-
// shell scripts and other tooling observe the correct exit status.
|
|
401
|
-
// Wrap the lifetime of the child process in a Promise so that we can await
|
|
402
|
-
// its termination in a structured way. The Promise resolves with an object
|
|
403
|
-
// describing how the child exited: either via exit code or due to a signal.
|
|
404
399
|
const childResult = await new Promise((resolve) => {
|
|
405
400
|
child.on("exit", (code, signal) => {
|
|
406
401
|
if (signal) {
|
|
@@ -412,8 +407,6 @@ const childResult = await new Promise((resolve) => {
|
|
|
412
407
|
});
|
|
413
408
|
|
|
414
409
|
if (childResult.type === "signal") {
|
|
415
|
-
// Re-emit the same signal so that the parent terminates with the expected
|
|
416
|
-
// semantics (this also sets the correct exit code of 128 + n).
|
|
417
410
|
process.kill(process.pid, childResult.signal);
|
|
418
411
|
} else {
|
|
419
412
|
process.exit(childResult.exitCode);
|
package/package.json
CHANGED
|
@@ -1,44 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hanzo/dev",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.2",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "Hanzo AI coding assistant - intelligent CLI for developers",
|
|
6
6
|
"bin": {
|
|
7
|
-
"dev": "bin/dev.js"
|
|
7
|
+
"dev": "bin/dev.js",
|
|
8
|
+
"hanzo": "bin/dev.js"
|
|
8
9
|
},
|
|
9
10
|
"type": "module",
|
|
10
11
|
"engines": {
|
|
11
|
-
"node": ">=
|
|
12
|
+
"node": ">=16"
|
|
12
13
|
},
|
|
13
14
|
"files": [
|
|
14
15
|
"bin/dev.js",
|
|
15
16
|
"postinstall.js",
|
|
17
|
+
"scripts/preinstall.js",
|
|
18
|
+
"scripts/windows-cleanup.ps1",
|
|
16
19
|
"dist"
|
|
17
20
|
],
|
|
18
21
|
"scripts": {
|
|
19
|
-
"
|
|
22
|
+
"preinstall": "node scripts/preinstall.js",
|
|
23
|
+
"postinstall": "node postinstall.js",
|
|
24
|
+
"prepublishOnly": "node -e \"const fs=require('fs'),path=require('path'); const repoGit=path.join(__dirname,'..','.git'); const inCi=process.env.GITHUB_ACTIONS==='true'||process.env.CI==='true'; if(fs.existsSync(repoGit) && !inCi){ console.error('Refusing to publish from dev-cli. Publishing happens via release.yml.'); process.exit(1);} else { console.log(inCi ? 'CI publish detected.' : 'Publishing staged package...'); }\""
|
|
20
25
|
},
|
|
21
26
|
"repository": {
|
|
22
27
|
"type": "git",
|
|
23
28
|
"url": "git+https://github.com/hanzoai/dev.git"
|
|
24
29
|
},
|
|
25
|
-
"keywords": [
|
|
26
|
-
"ai",
|
|
27
|
-
"cli",
|
|
28
|
-
"dev",
|
|
29
|
-
"developer-tools",
|
|
30
|
-
"coding-assistant",
|
|
31
|
-
"hanzo",
|
|
32
|
-
"llm",
|
|
33
|
-
"chatgpt",
|
|
34
|
-
"claude",
|
|
35
|
-
"code-generation"
|
|
36
|
-
],
|
|
37
|
-
"author": "Hanzo AI",
|
|
38
|
-
"homepage": "https://github.com/hanzoai/dev#readme",
|
|
39
|
-
"bugs": {
|
|
40
|
-
"url": "https://github.com/hanzoai/dev/issues"
|
|
41
|
-
},
|
|
42
30
|
"publishConfig": {
|
|
43
31
|
"access": "public"
|
|
44
32
|
},
|
|
@@ -47,10 +35,10 @@
|
|
|
47
35
|
"prettier": "^3.3.3"
|
|
48
36
|
},
|
|
49
37
|
"optionalDependencies": {
|
|
50
|
-
"@hanzo/dev-darwin-arm64": "3.0.
|
|
51
|
-
"@hanzo/dev-darwin-x64": "3.0.
|
|
52
|
-
"@hanzo/dev-linux-x64": "3.0.
|
|
53
|
-
"@hanzo/dev-linux-arm64": "3.0.
|
|
54
|
-
"@hanzo/dev-win32-x64": "3.0.
|
|
38
|
+
"@hanzo/dev-darwin-arm64": "3.0.2",
|
|
39
|
+
"@hanzo/dev-darwin-x64": "3.0.2",
|
|
40
|
+
"@hanzo/dev-linux-x64-musl": "3.0.2",
|
|
41
|
+
"@hanzo/dev-linux-arm64-musl": "3.0.2",
|
|
42
|
+
"@hanzo/dev-win32-x64": "3.0.2"
|
|
55
43
|
}
|
|
56
44
|
}
|