v0.5.0: Initial Release
This commit is contained in:
		
							parent
							
								
									f95897cf30
								
							
						
					
					
						commit
						f97f217bc6
					
				
							
								
								
									
										1
									
								
								npm/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								npm/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| node_modules | ||||
							
								
								
									
										28
									
								
								npm/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								npm/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | ||||
| # serviceman | ||||
| 
 | ||||
| A cross-platform service manager | ||||
| 
 | ||||
| ```bash | ||||
| serviceman add --name "my-project" node ./serve.js --port 3000 | ||||
| serviceman stop my-project | ||||
| serviceman start my-project | ||||
| ``` | ||||
| 
 | ||||
| Works with launchd (Mac), systemd (Linux), or standalone (Windows). | ||||
| 
 | ||||
| ## Meta Package | ||||
| 
 | ||||
| This is a meta-package to fetch and install the correction version of | ||||
| [go-serviceman](https://git.rootprojects.org/root/serviceman) | ||||
| for your architecture and platform. | ||||
| 
 | ||||
| ```bash | ||||
| npm install serviceman | ||||
| ``` | ||||
| 
 | ||||
| ## How does it work? | ||||
| 
 | ||||
| 1. Resolves executable from PATH, or hashbang (ex: `#!/usr/bin/env node`) | ||||
| 2. Resolves file and directory paths to absolute paths (ex: `/Users/me/my-project/serve.js`) | ||||
| 3. Creates a template `.plist` (Mac), `.service` (Linux), or `.json` (Windows) file | ||||
| 4. Calls `launchd` (Mac), `systemd` (Linux), or `serviceman-runner` (Windows) to enable/start/stop/etc | ||||
							
								
								
									
										18
									
								
								npm/package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								npm/package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| { | ||||
| 	"name": "serviceman", | ||||
| 	"version": "0.5.0", | ||||
| 	"lockfileVersion": 1, | ||||
| 	"requires": true, | ||||
| 	"dependencies": { | ||||
| 		"@root/mkdirp": { | ||||
| 			"version": "1.0.0", | ||||
| 			"resolved": "https://registry.npmjs.org/@root/mkdirp/-/mkdirp-1.0.0.tgz", | ||||
| 			"integrity": "sha512-hxGAYUx5029VggfG+U9naAhQkoMSXtOeXtbql97m3Hi6/sQSRL/4khKZPyOF6w11glyCOU38WCNLu9nUcSjOfA==" | ||||
| 		}, | ||||
| 		"@root/request": { | ||||
| 			"version": "1.3.11", | ||||
| 			"resolved": "https://registry.npmjs.org/@root/request/-/request-1.3.11.tgz", | ||||
| 			"integrity": "sha512-3a4Eeghcjsfe6zh7EJ+ni1l8OK9Fz2wL1OjP4UCa0YdvtH39kdXB9RGWuzyNv7dZi0+Ffkc83KfH0WbPMiuJFw==" | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										30
									
								
								npm/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								npm/package.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,30 @@ | ||||
| { | ||||
| 	"name": "serviceman", | ||||
| 	"version": "0.5.0", | ||||
| 	"description": "A cross-platform service manager", | ||||
| 	"main": "index.js", | ||||
| 	"scripts": { | ||||
| 		"postinstall": "bin/install-serviceman.js", | ||||
| 		"test": "echo \"Error: no test specified\" && exit 1" | ||||
| 	}, | ||||
| 	"repository": { | ||||
| 		"type": "git", | ||||
| 		"url": "https://git.rootprojects.org/root/serviceman.git" | ||||
| 	}, | ||||
| 	"keywords": [ | ||||
| 		"launchd", | ||||
| 		"systemd", | ||||
| 		"winsvc", | ||||
| 		"launchctl", | ||||
| 		"systemctl", | ||||
| 		"HKEY_CURRENT_USER", | ||||
| 		"HKCU", | ||||
| 		"Run" | ||||
| 	], | ||||
| 	"author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)", | ||||
| 	"license": "MPL-2.0", | ||||
| 	"dependencies": { | ||||
| 		"@root/mkdirp": "^1.0.0", | ||||
| 		"@root/request": "^1.3.11" | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										197
									
								
								npm/scripts/fetch-serviceman.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								npm/scripts/fetch-serviceman.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,197 @@ | ||||
| 'use strict'; | ||||
| var os = require('os'); | ||||
| 
 | ||||
| // https://nodejs.org/api/os.html#os_os_arch
 | ||||
| // 'arm', 'arm64', 'ia32', 'mips', 'mipsel', 'ppc', 'ppc64', 's390', 's390x', 'x32', and 'x64'
 | ||||
| var arch = os.arch(); // process.arch
 | ||||
| 
 | ||||
| // https://nodejs.org/api/os.html#os_os_platform
 | ||||
| // 'aix', 'darwin', 'freebsd', 'linux', 'openbsd', 'sunos', 'win32'
 | ||||
| var platform = os.platform(); // process.platform
 | ||||
| var ext = 'windows' === platform ? '.exe' : ''; | ||||
| 
 | ||||
| // This is _probably_ right. It's good enough for us
 | ||||
| // https://github.com/nodejs/node/issues/13629
 | ||||
| if ('arm' === arch) { | ||||
| 	arch += 'v' + process.config.variables.arm_version; | ||||
| } | ||||
| 
 | ||||
| var map = { | ||||
| 	// arches
 | ||||
| 	armv6: 'armv6', | ||||
| 	armv7: 'armv7', | ||||
| 	arm64: 'armv8', | ||||
| 	ia32: '386', | ||||
| 	x32: '386', | ||||
| 	x64: 'amd64', | ||||
| 	// platforms
 | ||||
| 	darwin: 'darwin', | ||||
| 	linux: 'linux', | ||||
| 	win32: 'windows' | ||||
| }; | ||||
| 
 | ||||
| arch = map[arch]; | ||||
| platform = map[platform]; | ||||
| 
 | ||||
| if (!arch || !platform) { | ||||
| 	console.error( | ||||
| 		"'" + os.platform() + "' on '" + os.arch() + "' isn't supported yet." | ||||
| 	); | ||||
| 	console.error( | ||||
| 		'Please open an issue at https://git.rootprojects.org/root/serviceman/issues' | ||||
| 	); | ||||
| 	process.exit(1); | ||||
| } | ||||
| 
 | ||||
| var newVer = require('../package.json').version; | ||||
| var fs = require('fs'); | ||||
| var exec = require('child_process').exec; | ||||
| var request = require('@root/request'); | ||||
| var mkdirp = require('@root/mkdirp'); | ||||
| 
 | ||||
| function needsUpdate(oldVer, newVer) { | ||||
| 	// "v1.0.0-pre" is BEHIND "v1.0.0"
 | ||||
| 	newVer = newVer.replace(/^v/, '').split(/[\.\-\+]/); | ||||
| 	oldVer = oldVer.replace(/^v/, '').split(/[\.\-\+]/); | ||||
| 	//console.log(oldVer, newVer);
 | ||||
| 
 | ||||
| 	if (newVer[3] && !oldVer[3]) { | ||||
| 		// don't install beta over stable
 | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	if (oldVer[3]) { | ||||
| 		if (oldVer[2] > 0) { | ||||
| 			oldVer[2] -= 1; | ||||
| 		} else if (oldVer[1] > 0) { | ||||
| 			oldVer[2] = 999; | ||||
| 			oldVer[1] -= 1; | ||||
| 		} else if (oldVer[0] > 0) { | ||||
| 			oldVer[2] = 999; | ||||
| 			oldVer[1] = 999; | ||||
| 			oldVer[0] -= 1; | ||||
| 		} else { | ||||
| 			// v0.0.0
 | ||||
| 			return true; | ||||
| 		} | ||||
| 	} | ||||
| 	if (newVer[3]) { | ||||
| 		if (newVer[2] > 0) { | ||||
| 			newVer[2] -= 1; | ||||
| 		} else if (newVer[1] > 0) { | ||||
| 			newVer[2] = 999; | ||||
| 			newVer[1] -= 1; | ||||
| 		} else if (newVer[0] > 0) { | ||||
| 			newVer[2] = 999; | ||||
| 			newVer[1] = 999; | ||||
| 			newVer[0] -= 1; | ||||
| 		} else { | ||||
| 			// v0.0.0
 | ||||
| 			return false; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	//console.log(oldVer, newVer);
 | ||||
| 	if (oldVer[0] > newVer[0]) { | ||||
| 		return false; | ||||
| 	} else if (oldVer[0] < newVer[0]) { | ||||
| 		return true; | ||||
| 	} else if (oldVer[1] > newVer[1]) { | ||||
| 		return false; | ||||
| 	} else if (oldVer[1] < newVer[1]) { | ||||
| 		return true; | ||||
| 	} else if (oldVer[2] > newVer[2]) { | ||||
| 		return false; | ||||
| 	} else if (oldVer[2] < newVer[2]) { | ||||
| 		return true; | ||||
| 	} else if (!oldVer[3] && newVer[3]) { | ||||
| 		return false; | ||||
| 	} else if (oldVer[3] && !newVer[3]) { | ||||
| 		return true; | ||||
| 	} else { | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| // Same version
 | ||||
| console.log(false === needsUpdate('0.5.0', '0.5.0')); | ||||
| // No previous version
 | ||||
| console.log(true === needsUpdate('', '0.5.1')); | ||||
| // The new version is slightly newer
 | ||||
| console.log(true === needsUpdate('0.5.0', '0.5.1')); | ||||
| console.log(true === needsUpdate('0.4.999-pre1', '0.5.0-pre1')); | ||||
| // The new version is slightly older
 | ||||
| console.log(false === needsUpdate('0.5.0', '0.5.0-pre1')); | ||||
| console.log(false === needsUpdate('0.5.1', '0.5.0')); | ||||
| */ | ||||
| 
 | ||||
| exec('serviceman version', { windowsHide: true }, function(err, stdout) { | ||||
| 	var oldVer = (stdout || '').split(' ')[0]; | ||||
| 	console.log(oldVer, newVer); | ||||
| 	if (!needsUpdate(oldVer, newVer)) { | ||||
| 		console.info( | ||||
| 			'Current serviceman version is new enough:', | ||||
| 			oldVer, | ||||
| 			newVer | ||||
| 		); | ||||
| 		return; | ||||
| 		//} else {
 | ||||
| 		//	console.info('Current serviceman version is older:', oldVer, newVer);
 | ||||
| 	} | ||||
| 
 | ||||
| 	var url = 'https://rootprojects.org/serviceman/dist/{{ .Platform }}/{{ .Arch }}/serviceman{{ .Ext }}' | ||||
| 		.replace(/{{ .Version }}/g, newVer) | ||||
| 		.replace(/{{ .Platform }}/g, platform) | ||||
| 		.replace(/{{ .Arch }}/g, arch) | ||||
| 		.replace(/{{ .Ext }}/g, ext); | ||||
| 
 | ||||
| 	console.info('Installing from', url); | ||||
| 	return request({ uri: url, encoding: null }, function(err, resp) { | ||||
| 		if (err) { | ||||
| 			console.error(err); | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		//console.log(resp.body.byteLength);
 | ||||
| 		//console.log(typeof resp.body);
 | ||||
| 		var serviceman = 'serviceman' + ext; | ||||
| 		return fs.writeFile(serviceman, resp.body, null, function(err) { | ||||
| 			if (err) { | ||||
| 				console.error(err); | ||||
| 				return; | ||||
| 			} | ||||
| 			fs.chmodSync(serviceman, parseInt('0755', 8)); | ||||
| 
 | ||||
| 			var path = require('path'); | ||||
| 			var localdir = '/usr/local/bin'; | ||||
| 			fs.rename(serviceman, path.join(localdir, serviceman), function( | ||||
| 				err | ||||
| 			) { | ||||
| 				if (err) { | ||||
| 					//console.error(err);
 | ||||
| 				} | ||||
| 				// ignore
 | ||||
| 			}); | ||||
| 
 | ||||
| 			var homedir = require('os').homedir(); | ||||
| 			var bindir = path.join(homedir, '.local', 'bin'); | ||||
| 			return mkdirp(bindir, function(err) { | ||||
| 				if (err) { | ||||
| 					console.error(err); | ||||
| 					return; | ||||
| 				} | ||||
| 
 | ||||
| 				var localsrv = path.join(bindir, serviceman); | ||||
| 				return fs.writeFile(localsrv, resp.body, function(err) { | ||||
| 					if (err) { | ||||
| 						console.error(err); | ||||
| 						return; | ||||
| 					} | ||||
| 					fs.chmodSync(localsrv, parseInt('0755', 8)); | ||||
| 					console.info('Wrote', serviceman, 'to', bindir); | ||||
| 				}); | ||||
| 			}); | ||||
| 		}); | ||||
| 	}); | ||||
| }); | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user