MCPcopy Create free account
hub / github.com/ZenNotes/zennotes / installCli

Function installCli

apps/desktop/src/main/cli-install.ts:346–399  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

344/* ---------- Install --------------------------------------------------- */
345
346export async function installCli(): Promise<CliInstallStatus> {
347 if (process.platform === 'win32') {
348 throw new Error('CLI install is not yet supported on Windows.')
349 }
350 const wrapper = await locateWrapper()
351 if (!wrapper) {
352 throw new Error(
353 'The CLI wrapper is not bundled with this build. Run `npm run build` (or launch from a packaged build) and try again.'
354 )
355 }
356
357 // If something is already installed at one of our candidates, prefer
358 // overwriting it in place rather than creating a second copy on PATH.
359 const existing = await findExistingInstall(wrapper)
360 let target: InstallTarget
361 if (existing && existing.installedByThisApp) {
362 target = {
363 linkPath: existing.linkPath,
364 onPath: pathDirsOnPath().has(path.dirname(existing.linkPath)),
365 requiresSudo: !(await isWritableDir(path.dirname(existing.linkPath))),
366 pathHint: null
367 }
368 } else if (existing && !existing.installedByThisApp) {
369 throw new Error(
370 `${existing.linkPath} already exists and is not managed by ZenNotes. Remove it manually if you want ZenNotes to take over.`
371 )
372 } else {
373 target = await pickInstallTarget()
374 }
375
376 const linkDir = path.dirname(target.linkPath)
377 await fsp.mkdir(linkDir, { recursive: true }).catch(() => undefined)
378
379 if (!target.requiresSudo) {
380 await writeSymlink(wrapper.wrapperPath, target.linkPath)
381 } else {
382 try {
383 await writeSymlink(wrapper.wrapperPath, target.linkPath)
384 } catch (err) {
385 const code = (err as NodeJS.ErrnoException).code
386 if (code === 'EACCES' || code === 'EPERM' || code === 'EROFS') {
387 await elevateAndSymlink(wrapper.wrapperPath, target.linkPath)
388 } else {
389 throw err
390 }
391 }
392 }
393
394 // #126: migrate off the legacy `zen` name — drop any ZenNotes-managed `zen`
395 // symlink now that `zn` is installed.
396 await removeManagedLinks(LEGACY_CLI_NAMES, wrapper)
397
398 return await getCliInstallStatus()
399}
400
401async function writeSymlink(source: string, target: string): Promise<void> {
402 try {

Callers 1

registerIpcFunction · 0.90

Calls 9

locateWrapperFunction · 0.85
findExistingInstallFunction · 0.85
pathDirsOnPathFunction · 0.85
isWritableDirFunction · 0.85
pickInstallTargetFunction · 0.85
writeSymlinkFunction · 0.85
elevateAndSymlinkFunction · 0.85
removeManagedLinksFunction · 0.85
getCliInstallStatusFunction · 0.85

Tested by

no test coverage detected