@scopebond/agent 0.4.1 → 0.4.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 CHANGED
@@ -80,7 +80,9 @@ Exactly one agent serves a computer's Scopebond home; a second one exits.
80
80
  `autostart on` writes a small launcher script into the Scopebond home that finds Node and the agent each time it
81
81
  runs (the paths recorded at setup first, then the ones on the system), so a Node upgrade or a version manager never
82
82
  leaves autostart pointing at nothing. On Windows the Run entry starts it under `conhost --headless`, so no window
83
- opens at sign-in. `status` says whether autostart is on and working.
83
+ opens at sign-in. If the agent stops with an error, the launcher starts it again after 30 seconds (up to 50 times,
84
+ each noted in `agent.log`), as launchd and systemd do on macOS and Linux; a clean stop (`stop`, `autostart off`, an
85
+ update handing over) ends it. `status` says whether autostart is on and working.
84
86
 
85
87
  ## Where you see it
86
88
 
@@ -1 +1 @@
1
- {"version":3,"file":"autostart.d.ts","sourceRoot":"","sources":["../src/autostart.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,KAAK,wBAAwB,CAAC;AAO3C,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,MAAM,CAE/F;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAkBlF;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAkB/D;AAOD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAexE;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CActD;AAED,wBAAgB,cAAc,CAAC,IAAI,SAAY;;;EAK9C;AAWD;;;6DAG6D;AAC7D,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAIvH;AAED,0HAA0H;AAC1H,wBAAgB,QAAQ,CAAC,aAAa,EAAE,MAAM,EAAE,QAAQ,kBAAmB,EAAE,OAAO,SAAI,GAAG,OAAO,CAUjG;AAED,uFAAuF;AACvF,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,SAAmB,EAAE,QAAQ,kBAAmB,GAAG,MAAM,CAkBhI;AAED,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,EAAE,QAAQ,kBAAmB,GAAG,MAAM,CAiB3F;AAED,wEAAwE;AACxE,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,QAAQ,kBAAmB,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAWhI"}
1
+ {"version":3,"file":"autostart.d.ts","sourceRoot":"","sources":["../src/autostart.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,KAAK,wBAAwB,CAAC;AAO3C,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,MAAM,CAE/F;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CA8BlF;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAkB/D;AAOD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAexE;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CActD;AAED,wBAAgB,cAAc,CAAC,IAAI,SAAY;;;EAK9C;AAWD;;;6DAG6D;AAC7D,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAIvH;AAED,0HAA0H;AAC1H,wBAAgB,QAAQ,CAAC,aAAa,EAAE,MAAM,EAAE,QAAQ,kBAAmB,EAAE,OAAO,SAAI,GAAG,OAAO,CAUjG;AAED,uFAAuF;AACvF,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,SAAmB,EAAE,QAAQ,kBAAmB,GAAG,MAAM,CAkBhI;AAED,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,EAAE,QAAQ,kBAAmB,GAAG,MAAM,CAiB3F;AAED,wEAAwE;AACxE,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,QAAQ,kBAAmB,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAWhI"}
package/dist/autostart.js CHANGED
@@ -31,8 +31,20 @@ export function windowsLauncher(node, cli, logFile) {
31
31
  `set "CLI=${noQuotes(cli)}"`,
32
32
  `if not exist "%CLI%" for /f "delims=" %%i in ('npm.cmd root -g 2^>nul') do set "CLI=%%i\\@scopebond\\agent\\dist\\cli.js"`,
33
33
  `if not defined NODE exit /b 1`,
34
+ // Restart on failure, as launchd (KeepAlive) and systemd (Restart=on-failure) do: a crash restarts the agent after
35
+ // 30 seconds, up to 50 times; a clean exit (stop, autostart off, an update handing over) ends the launcher.
36
+ "set /a TRIES=0",
37
+ ":run",
34
38
  // The log sits beside this launcher; %~dp0 keeps it right whatever the folder is called.
35
39
  `"%NODE%" --disable-warning=ExperimentalWarning "%CLI%" run >> "%~dp0${win32.basename(noQuotes(logFile))}" 2>&1`,
40
+ `set "CODE=%ERRORLEVEL%"`,
41
+ "if %CODE% EQU 0 exit /b 0",
42
+ "set /a TRIES+=1",
43
+ `echo %DATE% %TIME% the agent stopped with exit code %CODE%; restarting in 30 seconds (attempt %TRIES% of 50) >> "%~dp0${win32.basename(noQuotes(logFile))}"`,
44
+ "if %TRIES% GEQ 50 exit /b 1",
45
+ // ping waits without a console to read from (timeout.exe refuses to run under a headless console).
46
+ "ping -n 31 127.0.0.1 >nul",
47
+ "goto run",
36
48
  "",
37
49
  ].join("\r\n");
38
50
  }
@@ -1 +1 @@
1
- {"version":3,"file":"autostart.js","sourceRoot":"","sources":["../src/autostart.ts"],"names":[],"mappings":"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","sourcesContent":["// Start the agent when the person signs in to the computer, per user, with no administrator\n// rights: a Run entry on Windows, a LaunchAgent on macOS, a systemd user unit on Linux.\n//\n// Each of them starts a small launcher script in the Scopebond home, not Node directly. The\n// launcher finds Node and the agent when it runs (the recorded paths first, then the system's),\n// so upgrading Node or switching versions never leaves an autostart entry pointing at nothing.\n// On Windows it runs under `conhost --headless`, so no window opens at sign-in.\n\nimport { execFileSync, spawn } from \"node:child_process\";\nimport { chmodSync, existsSync, mkdirSync, rmSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, win32 } from \"node:path\";\n\nexport const LABEL = \"com.scopebond.agent\";\nconst RUN_KEY = \"HKCU\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run\";\nconst RUN_VALUE = \"ScopebondAgent\";\n\nconst xml = (s: string) => s.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\nconst noQuotes = (s: string) => s.replace(/\"/g, \"\");\n\nexport function launcherPath(home: string, platform: NodeJS.Platform = process.platform): string {\n return join(home, platform === \"win32\" ? \"agent-launch.cmd\" : \"agent-launch.sh\");\n}\n\nexport function windowsLauncher(node: string, cli: string, logFile: string): string {\n return [\n \"@echo off\",\n // cmd.exe reads a batch file in the console code page: switch to UTF-8 first, so a profile folder\n // with non-ASCII letters in the paths below reads as written.\n \"chcp 65001 >nul\",\n \"rem Scopebond Agent launcher: finds Node and the agent each time, so a Node upgrade never stops it.\",\n \"setlocal\",\n `set \"NODE=${noQuotes(node)}\"`,\n `if not exist \"%NODE%\" set \"NODE=\"`,\n `if not defined NODE for /f \"delims=\" %%i in ('where node 2^>nul') do if not defined NODE set \"NODE=%%i\"`,\n `set \"CLI=${noQuotes(cli)}\"`,\n `if not exist \"%CLI%\" for /f \"delims=\" %%i in ('npm.cmd root -g 2^>nul') do set \"CLI=%%i\\\\@scopebond\\\\agent\\\\dist\\\\cli.js\"`,\n `if not defined NODE exit /b 1`,\n // The log sits beside this launcher; %~dp0 keeps it right whatever the folder is called.\n `\"%NODE%\" --disable-warning=ExperimentalWarning \"%CLI%\" run >> \"%~dp0${win32.basename(noQuotes(logFile))}\" 2>&1`,\n \"\",\n ].join(\"\\r\\n\");\n}\n\nexport function posixLauncher(node: string, cli: string): string {\n const q = (s: string) => `'${s.replace(/'/g, \"'\\\\''\")}'`;\n return `#!/bin/sh\n# Scopebond Agent launcher: finds Node and the agent each time, so a Node upgrade never stops it.\nNODE=${q(node)}\nif [ ! -x \"$NODE\" ]; then\n [ -s \"$HOME/.nvm/nvm.sh\" ] && . \"$HOME/.nvm/nvm.sh\" >/dev/null 2>&1\n NODE=\"$(command -v node 2>/dev/null)\"\n for candidate in /opt/homebrew/bin/node /usr/local/bin/node /usr/bin/node; do\n [ -n \"$NODE\" ] && break\n [ -x \"$candidate\" ] && NODE=\"$candidate\"\n done\nfi\nCLI=${q(cli)}\n[ -f \"$CLI\" ] || CLI=\"$(npm root -g 2>/dev/null)/@scopebond/agent/dist/cli.js\"\n[ -n \"$NODE\" ] || exit 1\nexec \"$NODE\" --disable-warning=ExperimentalWarning \"$CLI\" run\n`;\n}\n\n/** The Run value: the launcher under a headless console host, so nothing appears on screen. */\n/** `cmd /s /c \"\"<launcher>\"\"`: cmd drops only the outer quotes and runs the quoted path as it is, so a\n * profile folder with a space and a `(`, `)` or `&` (\"John (Work)\") still starts the launcher. */\nconst cmdRun = (launcher: string) => `/d /s /c \"\"${noQuotes(launcher)}\"\"`;\n\nexport function windowsRunCommand(launcher: string): string {\n return `conhost.exe --headless cmd.exe ${cmdRun(launcher)}`;\n}\n\nexport function macLaunchAgent(launcher: string, logFile: string): string {\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key><string>${LABEL}</string>\n <key>ProgramArguments</key>\n <array><string>/bin/sh</string><string>${xml(launcher)}</string></array>\n <key>RunAtLoad</key><true/>\n <key>KeepAlive</key><dict><key>SuccessfulExit</key><false/></dict>\n <key>StandardOutPath</key><string>${xml(logFile)}</string>\n <key>StandardErrorPath</key><string>${xml(logFile)}</string>\n</dict>\n</plist>\n`;\n}\n\nexport function linuxUserUnit(launcher: string): string {\n const q = (s: string) => `\"${s.replace(/([\"\\\\])/g, \"\\\\$1\")}\"`;\n return `[Unit]\nDescription=Scopebond Agent (delivers this computer's records to its Scopebond workspace)\nAfter=network-online.target\n\n[Service]\nExecStart=/bin/sh ${q(launcher)}\nRestart=on-failure\nRestartSec=30\n\n[Install]\nWantedBy=default.target\n`;\n}\n\nexport function autostartPaths(home = homedir()) {\n return {\n macPlist: join(home, \"Library\", \"LaunchAgents\", `${LABEL}.plist`),\n linuxUnit: join(home, \".config\", \"systemd\", \"user\", \"scopebond-agent.service\"),\n };\n}\n\nfunction writeLauncher(scopebondHome: string, node: string, cli: string, platform: NodeJS.Platform): string {\n mkdirSync(scopebondHome, { recursive: true });\n const launcher = launcherPath(scopebondHome, platform);\n const log = join(scopebondHome, \"agent.log\");\n writeFileSync(launcher, platform === \"win32\" ? windowsLauncher(node, cli, log) : posixLauncher(node, cli), { mode: 0o700 });\n if (platform !== \"win32\") chmodSync(launcher, 0o700);\n return launcher;\n}\n\n/** The ways to start the agent now on Windows, in order: the launcher under a headless console (no window,\n * as sign-in does), then the launcher through cmd.exe with its window hidden, for a session where the\n * headless console host does not start (seen on Windows Server). macOS and Linux start it themselves\n * when autostart is turned on (RunAtLoad, enable --now). */\nexport function startCommands(launcher: string, platform: NodeJS.Platform = process.platform): Array<[string, string[]]> {\n if (platform !== \"win32\") return [];\n // Passed verbatim (startNow sets windowsVerbatimArguments): Node's own quoting follows other rules than cmd's.\n return [[\"conhost.exe\", [\"--headless\", \"cmd.exe\", cmdRun(launcher)]], [\"cmd.exe\", [cmdRun(launcher)]]];\n}\n\n/** Start the agent now with the `attempt`-th way (0 first), detached from this terminal. Returns whether it tried one. */\nexport function startNow(scopebondHome: string, platform = process.platform, attempt = 0): boolean {\n const launcher = launcherPath(scopebondHome, platform);\n const command = startCommands(launcher, platform)[attempt];\n if (!command || !existsSync(launcher)) return false;\n try {\n const child = spawn(command[0], command[1], { detached: true, stdio: \"ignore\", windowsHide: true, windowsVerbatimArguments: true });\n child.on(\"error\", () => { /* the next way, or the next sign-in */ });\n child.unref();\n return true;\n } catch { return false; }\n}\n\n/** Turn autostart on for this user. Returns a one-line description of what changed. */\nexport function enableAutostart(scopebondHome: string, cli: string, node = process.execPath, platform = process.platform): string {\n const launcher = writeLauncher(scopebondHome, node, cli, platform);\n const paths = autostartPaths();\n if (platform === \"win32\") {\n execFileSync(\"reg\", [\"add\", RUN_KEY, \"/v\", RUN_VALUE, \"/t\", \"REG_SZ\", \"/d\", windowsRunCommand(launcher), \"/f\"], { stdio: \"ignore\" });\n return `added ${RUN_VALUE} to ${RUN_KEY} (launcher ${launcher})`;\n }\n if (platform === \"darwin\") {\n mkdirSync(dirname(paths.macPlist), { recursive: true });\n writeFileSync(paths.macPlist, macLaunchAgent(launcher, join(scopebondHome, \"agent.log\")));\n try { execFileSync(\"launchctl\", [\"load\", \"-w\", paths.macPlist], { stdio: \"ignore\" }); } catch { /* loads at next sign-in */ }\n return `wrote ${paths.macPlist}`;\n }\n mkdirSync(dirname(paths.linuxUnit), { recursive: true });\n writeFileSync(paths.linuxUnit, linuxUserUnit(launcher));\n try { execFileSync(\"systemctl\", [\"--user\", \"daemon-reload\"], { stdio: \"ignore\" }); execFileSync(\"systemctl\", [\"--user\", \"enable\", \"--now\", \"scopebond-agent.service\"], { stdio: \"ignore\" }); }\n catch { return `wrote ${paths.linuxUnit} (enable it with: systemctl --user enable --now scopebond-agent)`; }\n return `wrote and enabled ${paths.linuxUnit}`;\n}\n\nexport function disableAutostart(scopebondHome: string, platform = process.platform): string {\n const paths = autostartPaths();\n rmSync(launcherPath(scopebondHome, platform), { force: true });\n if (platform === \"win32\") {\n try { execFileSync(\"reg\", [\"delete\", RUN_KEY, \"/v\", RUN_VALUE, \"/f\"], { stdio: \"ignore\" }); } catch { return \"autostart was not on\"; }\n return `removed ${RUN_VALUE} from ${RUN_KEY}`;\n }\n if (platform === \"darwin\") {\n if (!existsSync(paths.macPlist)) return \"autostart was not on\";\n try { execFileSync(\"launchctl\", [\"unload\", \"-w\", paths.macPlist], { stdio: \"ignore\" }); } catch { /* not loaded */ }\n rmSync(paths.macPlist, { force: true });\n return `removed ${paths.macPlist}`;\n }\n if (!existsSync(paths.linuxUnit)) return \"autostart was not on\";\n try { execFileSync(\"systemctl\", [\"--user\", \"disable\", \"--now\", \"scopebond-agent.service\"], { stdio: \"ignore\" }); } catch { /* not enabled */ }\n rmSync(paths.linuxUnit, { force: true });\n return `removed ${paths.linuxUnit}`;\n}\n\n/** Whether autostart is on and its launcher can start the agent now. */\nexport function autostartHealth(scopebondHome: string, platform = process.platform): { on: boolean; ok: boolean; detail: string } {\n const paths = autostartPaths();\n let on = false;\n if (platform === \"win32\") {\n try { execFileSync(\"reg\", [\"query\", RUN_KEY, \"/v\", RUN_VALUE], { stdio: \"ignore\" }); on = true; } catch { on = false; }\n } else on = existsSync(platform === \"darwin\" ? paths.macPlist : paths.linuxUnit);\n // The fix as the person types it: PowerShell blocks the plain scopebond-agent script shim.\n const fix = `${platform === \"win32\" ? \"scopebond-agent.cmd\" : \"scopebond-agent\"} autostart on`;\n if (!on) return { on, ok: false, detail: `the agent does not start with sign-in (run: ${fix})` };\n if (!existsSync(launcherPath(scopebondHome, platform))) return { on, ok: false, detail: `the autostart launcher is missing (run: ${fix})` };\n return { on, ok: true, detail: \"starts with sign-in\" };\n}\n"]}
1
+ {"version":3,"file":"autostart.js","sourceRoot":"","sources":["../src/autostart.ts"],"names":[],"mappings":"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","sourcesContent":["// Start the agent when the person signs in to the computer, per user, with no administrator\n// rights: a Run entry on Windows, a LaunchAgent on macOS, a systemd user unit on Linux.\n//\n// Each of them starts a small launcher script in the Scopebond home, not Node directly. The\n// launcher finds Node and the agent when it runs (the recorded paths first, then the system's),\n// so upgrading Node or switching versions never leaves an autostart entry pointing at nothing.\n// On Windows it runs under `conhost --headless`, so no window opens at sign-in.\n\nimport { execFileSync, spawn } from \"node:child_process\";\nimport { chmodSync, existsSync, mkdirSync, rmSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, win32 } from \"node:path\";\n\nexport const LABEL = \"com.scopebond.agent\";\nconst RUN_KEY = \"HKCU\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run\";\nconst RUN_VALUE = \"ScopebondAgent\";\n\nconst xml = (s: string) => s.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\nconst noQuotes = (s: string) => s.replace(/\"/g, \"\");\n\nexport function launcherPath(home: string, platform: NodeJS.Platform = process.platform): string {\n return join(home, platform === \"win32\" ? \"agent-launch.cmd\" : \"agent-launch.sh\");\n}\n\nexport function windowsLauncher(node: string, cli: string, logFile: string): string {\n return [\n \"@echo off\",\n // cmd.exe reads a batch file in the console code page: switch to UTF-8 first, so a profile folder\n // with non-ASCII letters in the paths below reads as written.\n \"chcp 65001 >nul\",\n \"rem Scopebond Agent launcher: finds Node and the agent each time, so a Node upgrade never stops it.\",\n \"setlocal\",\n `set \"NODE=${noQuotes(node)}\"`,\n `if not exist \"%NODE%\" set \"NODE=\"`,\n `if not defined NODE for /f \"delims=\" %%i in ('where node 2^>nul') do if not defined NODE set \"NODE=%%i\"`,\n `set \"CLI=${noQuotes(cli)}\"`,\n `if not exist \"%CLI%\" for /f \"delims=\" %%i in ('npm.cmd root -g 2^>nul') do set \"CLI=%%i\\\\@scopebond\\\\agent\\\\dist\\\\cli.js\"`,\n `if not defined NODE exit /b 1`,\n // Restart on failure, as launchd (KeepAlive) and systemd (Restart=on-failure) do: a crash restarts the agent after\n // 30 seconds, up to 50 times; a clean exit (stop, autostart off, an update handing over) ends the launcher.\n \"set /a TRIES=0\",\n \":run\",\n // The log sits beside this launcher; %~dp0 keeps it right whatever the folder is called.\n `\"%NODE%\" --disable-warning=ExperimentalWarning \"%CLI%\" run >> \"%~dp0${win32.basename(noQuotes(logFile))}\" 2>&1`,\n `set \"CODE=%ERRORLEVEL%\"`,\n \"if %CODE% EQU 0 exit /b 0\",\n \"set /a TRIES+=1\",\n `echo %DATE% %TIME% the agent stopped with exit code %CODE%; restarting in 30 seconds (attempt %TRIES% of 50) >> \"%~dp0${win32.basename(noQuotes(logFile))}\"`,\n \"if %TRIES% GEQ 50 exit /b 1\",\n // ping waits without a console to read from (timeout.exe refuses to run under a headless console).\n \"ping -n 31 127.0.0.1 >nul\",\n \"goto run\",\n \"\",\n ].join(\"\\r\\n\");\n}\n\nexport function posixLauncher(node: string, cli: string): string {\n const q = (s: string) => `'${s.replace(/'/g, \"'\\\\''\")}'`;\n return `#!/bin/sh\n# Scopebond Agent launcher: finds Node and the agent each time, so a Node upgrade never stops it.\nNODE=${q(node)}\nif [ ! -x \"$NODE\" ]; then\n [ -s \"$HOME/.nvm/nvm.sh\" ] && . \"$HOME/.nvm/nvm.sh\" >/dev/null 2>&1\n NODE=\"$(command -v node 2>/dev/null)\"\n for candidate in /opt/homebrew/bin/node /usr/local/bin/node /usr/bin/node; do\n [ -n \"$NODE\" ] && break\n [ -x \"$candidate\" ] && NODE=\"$candidate\"\n done\nfi\nCLI=${q(cli)}\n[ -f \"$CLI\" ] || CLI=\"$(npm root -g 2>/dev/null)/@scopebond/agent/dist/cli.js\"\n[ -n \"$NODE\" ] || exit 1\nexec \"$NODE\" --disable-warning=ExperimentalWarning \"$CLI\" run\n`;\n}\n\n/** The Run value: the launcher under a headless console host, so nothing appears on screen. */\n/** `cmd /s /c \"\"<launcher>\"\"`: cmd drops only the outer quotes and runs the quoted path as it is, so a\n * profile folder with a space and a `(`, `)` or `&` (\"John (Work)\") still starts the launcher. */\nconst cmdRun = (launcher: string) => `/d /s /c \"\"${noQuotes(launcher)}\"\"`;\n\nexport function windowsRunCommand(launcher: string): string {\n return `conhost.exe --headless cmd.exe ${cmdRun(launcher)}`;\n}\n\nexport function macLaunchAgent(launcher: string, logFile: string): string {\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key><string>${LABEL}</string>\n <key>ProgramArguments</key>\n <array><string>/bin/sh</string><string>${xml(launcher)}</string></array>\n <key>RunAtLoad</key><true/>\n <key>KeepAlive</key><dict><key>SuccessfulExit</key><false/></dict>\n <key>StandardOutPath</key><string>${xml(logFile)}</string>\n <key>StandardErrorPath</key><string>${xml(logFile)}</string>\n</dict>\n</plist>\n`;\n}\n\nexport function linuxUserUnit(launcher: string): string {\n const q = (s: string) => `\"${s.replace(/([\"\\\\])/g, \"\\\\$1\")}\"`;\n return `[Unit]\nDescription=Scopebond Agent (delivers this computer's records to its Scopebond workspace)\nAfter=network-online.target\n\n[Service]\nExecStart=/bin/sh ${q(launcher)}\nRestart=on-failure\nRestartSec=30\n\n[Install]\nWantedBy=default.target\n`;\n}\n\nexport function autostartPaths(home = homedir()) {\n return {\n macPlist: join(home, \"Library\", \"LaunchAgents\", `${LABEL}.plist`),\n linuxUnit: join(home, \".config\", \"systemd\", \"user\", \"scopebond-agent.service\"),\n };\n}\n\nfunction writeLauncher(scopebondHome: string, node: string, cli: string, platform: NodeJS.Platform): string {\n mkdirSync(scopebondHome, { recursive: true });\n const launcher = launcherPath(scopebondHome, platform);\n const log = join(scopebondHome, \"agent.log\");\n writeFileSync(launcher, platform === \"win32\" ? windowsLauncher(node, cli, log) : posixLauncher(node, cli), { mode: 0o700 });\n if (platform !== \"win32\") chmodSync(launcher, 0o700);\n return launcher;\n}\n\n/** The ways to start the agent now on Windows, in order: the launcher under a headless console (no window,\n * as sign-in does), then the launcher through cmd.exe with its window hidden, for a session where the\n * headless console host does not start (seen on Windows Server). macOS and Linux start it themselves\n * when autostart is turned on (RunAtLoad, enable --now). */\nexport function startCommands(launcher: string, platform: NodeJS.Platform = process.platform): Array<[string, string[]]> {\n if (platform !== \"win32\") return [];\n // Passed verbatim (startNow sets windowsVerbatimArguments): Node's own quoting follows other rules than cmd's.\n return [[\"conhost.exe\", [\"--headless\", \"cmd.exe\", cmdRun(launcher)]], [\"cmd.exe\", [cmdRun(launcher)]]];\n}\n\n/** Start the agent now with the `attempt`-th way (0 first), detached from this terminal. Returns whether it tried one. */\nexport function startNow(scopebondHome: string, platform = process.platform, attempt = 0): boolean {\n const launcher = launcherPath(scopebondHome, platform);\n const command = startCommands(launcher, platform)[attempt];\n if (!command || !existsSync(launcher)) return false;\n try {\n const child = spawn(command[0], command[1], { detached: true, stdio: \"ignore\", windowsHide: true, windowsVerbatimArguments: true });\n child.on(\"error\", () => { /* the next way, or the next sign-in */ });\n child.unref();\n return true;\n } catch { return false; }\n}\n\n/** Turn autostart on for this user. Returns a one-line description of what changed. */\nexport function enableAutostart(scopebondHome: string, cli: string, node = process.execPath, platform = process.platform): string {\n const launcher = writeLauncher(scopebondHome, node, cli, platform);\n const paths = autostartPaths();\n if (platform === \"win32\") {\n execFileSync(\"reg\", [\"add\", RUN_KEY, \"/v\", RUN_VALUE, \"/t\", \"REG_SZ\", \"/d\", windowsRunCommand(launcher), \"/f\"], { stdio: \"ignore\" });\n return `added ${RUN_VALUE} to ${RUN_KEY} (launcher ${launcher})`;\n }\n if (platform === \"darwin\") {\n mkdirSync(dirname(paths.macPlist), { recursive: true });\n writeFileSync(paths.macPlist, macLaunchAgent(launcher, join(scopebondHome, \"agent.log\")));\n try { execFileSync(\"launchctl\", [\"load\", \"-w\", paths.macPlist], { stdio: \"ignore\" }); } catch { /* loads at next sign-in */ }\n return `wrote ${paths.macPlist}`;\n }\n mkdirSync(dirname(paths.linuxUnit), { recursive: true });\n writeFileSync(paths.linuxUnit, linuxUserUnit(launcher));\n try { execFileSync(\"systemctl\", [\"--user\", \"daemon-reload\"], { stdio: \"ignore\" }); execFileSync(\"systemctl\", [\"--user\", \"enable\", \"--now\", \"scopebond-agent.service\"], { stdio: \"ignore\" }); }\n catch { return `wrote ${paths.linuxUnit} (enable it with: systemctl --user enable --now scopebond-agent)`; }\n return `wrote and enabled ${paths.linuxUnit}`;\n}\n\nexport function disableAutostart(scopebondHome: string, platform = process.platform): string {\n const paths = autostartPaths();\n rmSync(launcherPath(scopebondHome, platform), { force: true });\n if (platform === \"win32\") {\n try { execFileSync(\"reg\", [\"delete\", RUN_KEY, \"/v\", RUN_VALUE, \"/f\"], { stdio: \"ignore\" }); } catch { return \"autostart was not on\"; }\n return `removed ${RUN_VALUE} from ${RUN_KEY}`;\n }\n if (platform === \"darwin\") {\n if (!existsSync(paths.macPlist)) return \"autostart was not on\";\n try { execFileSync(\"launchctl\", [\"unload\", \"-w\", paths.macPlist], { stdio: \"ignore\" }); } catch { /* not loaded */ }\n rmSync(paths.macPlist, { force: true });\n return `removed ${paths.macPlist}`;\n }\n if (!existsSync(paths.linuxUnit)) return \"autostart was not on\";\n try { execFileSync(\"systemctl\", [\"--user\", \"disable\", \"--now\", \"scopebond-agent.service\"], { stdio: \"ignore\" }); } catch { /* not enabled */ }\n rmSync(paths.linuxUnit, { force: true });\n return `removed ${paths.linuxUnit}`;\n}\n\n/** Whether autostart is on and its launcher can start the agent now. */\nexport function autostartHealth(scopebondHome: string, platform = process.platform): { on: boolean; ok: boolean; detail: string } {\n const paths = autostartPaths();\n let on = false;\n if (platform === \"win32\") {\n try { execFileSync(\"reg\", [\"query\", RUN_KEY, \"/v\", RUN_VALUE], { stdio: \"ignore\" }); on = true; } catch { on = false; }\n } else on = existsSync(platform === \"darwin\" ? paths.macPlist : paths.linuxUnit);\n // The fix as the person types it: PowerShell blocks the plain scopebond-agent script shim.\n const fix = `${platform === \"win32\" ? \"scopebond-agent.cmd\" : \"scopebond-agent\"} autostart on`;\n if (!on) return { on, ok: false, detail: `the agent does not start with sign-in (run: ${fix})` };\n if (!existsSync(launcherPath(scopebondHome, platform))) return { on, ok: false, detail: `the autostart launcher is missing (run: ${fix})` };\n return { on, ok: true, detail: \"starts with sign-in\" };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scopebond/agent",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "description": "Free, open-source Scopebond Agent companion: deliver queued records, maintain rules and connections, and report computer health to the separate proprietary Scopebond Cloud workspace.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Avouro LLC",
@@ -40,8 +40,8 @@
40
40
  ],
41
41
  "dependencies": {
42
42
  "@scopebond/gateway": "0.15.0",
43
- "@scopebond/hook": "0.18.0",
44
- "@scopebond/sdk": "0.1.4"
43
+ "@scopebond/sdk": "0.1.4",
44
+ "@scopebond/hook": "0.19.0"
45
45
  },
46
46
  "publishConfig": {
47
47
  "access": "public"