(options: LaunchdPlistOptions)
| 265 | * keeps it off the foreground scheduler. |
| 266 | */ |
| 267 | export const generateLaunchdPlist = (options: LaunchdPlistOptions): string => { |
| 268 | const programArgs = options.programArguments |
| 269 | .map((arg) => ` <string>${xmlEscape(arg)}</string>`) |
| 270 | .join("\n"); |
| 271 | const bundleIdentifier = associatedBundleIdentifier(options.programArguments); |
| 272 | const associatedBundleIdentifiers = bundleIdentifier |
| 273 | ? ` <key>AssociatedBundleIdentifiers</key>\n <array>\n <string>${xmlEscape(bundleIdentifier)}</string>\n </array>\n` |
| 274 | : ""; |
| 275 | const envEntries = Object.entries(options.environment) |
| 276 | .map( |
| 277 | ([key, value]) => |
| 278 | ` <key>${xmlEscape(key)}</key>\n <string>${xmlEscape(value)}</string>`, |
| 279 | ) |
| 280 | .join("\n"); |
| 281 | return `<?xml version="1.0" encoding="UTF-8"?> |
| 282 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
| 283 | <plist version="1.0"> |
| 284 | <dict> |
| 285 | <key>Label</key> |
| 286 | <string>${xmlEscape(options.label)}</string> |
| 287 | ${associatedBundleIdentifiers} <key>ProgramArguments</key> |
| 288 | <array> |
| 289 | ${programArgs} |
| 290 | </array> |
| 291 | <key>EnvironmentVariables</key> |
| 292 | <dict> |
| 293 | ${envEntries} |
| 294 | </dict> |
| 295 | <key>RunAtLoad</key> |
| 296 | <true/> |
| 297 | <key>KeepAlive</key> |
| 298 | <dict> |
| 299 | <key>SuccessfulExit</key> |
| 300 | <false/> |
| 301 | </dict> |
| 302 | <key>ProcessType</key> |
| 303 | <string>Background</string> |
| 304 | <key>WorkingDirectory</key> |
| 305 | <string>${xmlEscape(options.workingDirectory)}</string> |
| 306 | <key>StandardOutPath</key> |
| 307 | <string>${xmlEscape(options.stdoutPath)}</string> |
| 308 | <key>StandardErrorPath</key> |
| 309 | <string>${xmlEscape(options.stderrPath)}</string> |
| 310 | </dict> |
| 311 | </plist> |
| 312 | `; |
| 313 | }; |
| 314 | |
| 315 | const parseLaunchctlPid = (printOutput: string): number | null => { |
| 316 | const match = printOutput.match(/\bpid\s*=\s*(\d+)/); |
no test coverage detected