commit cf7fe77eb6667d98e635eea9834324e4ffa5ec69 Author: Max Ogden Date: Sun Mar 22 19:51:19 2015 -0700 first working version diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..a2eb533 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d88cab5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +downloaded +node_modules \ No newline at end of file diff --git a/cli.js b/cli.js new file mode 100755 index 0000000..3534d3c --- /dev/null +++ b/cli.js @@ -0,0 +1,20 @@ +#!/usr/bin/env node +var args = require('minimist')(process.argv.slice(2)) +var packager = require('./') + +args.dir = args._[0] +args.name = args._[1] + +if (!args.dir || !args.name) { + console.error('Usage: atom-shell-packager ') + process.exit(1) +} + +packager(args, function done (err, appPath) { + if (err) { + console.error(err) + process.exit(1) + } + + console.error('Wrote new app to', appPath) +}) diff --git a/index.js b/index.js new file mode 100644 index 0000000..92a263e --- /dev/null +++ b/index.js @@ -0,0 +1,89 @@ +var os = require('os') +var path = require('path') +var fs = require('fs') +var child = require('child_process') + +var nugget = require('nugget') +var plist = require('plist') +var unzip = require('extract-zip') +var mkdirp = require('mkdirp') +var rimraf = require('rimraf') +var ncp = require('ncp').ncp + +var latest = '0.22.1' + +module.exports = function packager (opts, cb) { + if (!opts.version) opts.version = latest + + var names = { + mac: 'atom-shell-v' + opts.version + '-darwin-x64' + } + + var macUrl = 'https://github.com/atom/atom-shell/releases/download/v' + opts.version + '/' + names.mac + '.zip' + var localFile = path.join(__dirname, 'downloaded', names.mac + '.zip') + var tmpDir = path.join(os.tmpdir(), names.mac) + + rimraf(tmpDir, function rmrfd () { + // ignore errors + mkdirp(tmpDir, function mkdirpd () { + // ignore errors + if (opts.zip) extractZip(opts.zip) + else downloadZip() + }) + }) + + function downloadZip () { + nugget(macUrl, {target: localFile, dir: path.join(__dirname, 'downloaded'), resume: true, verbose: true}, function downloaded (err) { + if (err) return cb(err) + extractZip(localFile) + }) + } + + function extractZip (filename) { + unzip(filename, {dir: tmpDir}, function extracted (err) { + if (err) return cb(err) + buildApp() + }) + } + + function buildApp () { + var newApp = path.join(tmpDir, opts.name + '.app') + + // rename .app folder (this is exactly what Atom editor does) + fs.renameSync(path.join(tmpDir, 'Atom.app'), newApp) + + var paths = { + info1: path.join(newApp, 'Contents', 'Info.plist'), + info2: path.join(newApp, 'Contents', 'Frameworks', 'Atom Helper.app', 'Contents', 'Info.plist'), + app: path.join(newApp, 'Contents', 'Resources', 'app') + } + + // update plist files + var pl1 = plist.parse(fs.readFileSync(paths.info1).toString()) + var pl2 = plist.parse(fs.readFileSync(paths.info2).toString()) + + var bundleId = opts['app-bundle-id'] || 'com.atom-shell.' + opts.name.toLowerCase() + var bundleHelperId = opts['helper-bundle-id'] || 'com.atom-shell.' + opts.name.toLowerCase() + '.helper' + + pl1.CFBundleDisplayName = opts.name + pl1.CFBundleIdentifier = bundleId + pl1.CFBundleName = opts.name + pl2.CFBundleIdentifier = bundleHelperId + pl2.CFBundleName = opts.name + + fs.writeFileSync(paths.info1, plist.build(pl1)) + fs.writeFileSync(paths.info2, plist.build(pl2)) + + // copy users app into .app + ncp(opts.dir, paths.app, opts, function copied (err) { + if (err) return cb(err) + + // finally, move app into cwd + var finalPath = opts.out || process.cwd() + // TODO dont spawn, but I couldn't find a good module + child.exec('mv "' + newApp + '" "' + finalPath + '"', function moved (err) { + cb(err, path.join(finalPath, opts.name + '.app')) + }) + }) + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..ee25876 --- /dev/null +++ b/package.json @@ -0,0 +1,32 @@ +{ + "name": "atom-shell-app", + "version": "1.0.0", + "description": "package your atom-shell app in OS executables (.app, .exe, etc) via JS or CLI", + "main": "index.js", + "bin": { + "atom-shell-packager": "cli.js" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/maxogden/atom-shell-app.git" + }, + "author": "max ogden", + "license": "BSD", + "bugs": { + "url": "https://github.com/maxogden/atom-shell-app/issues" + }, + "homepage": "https://github.com/maxogden/atom-shell-app", + "dependencies": { + "cpr": "^0.4.0", + "extract-zip": "^1.0.3", + "minimist": "^1.1.1", + "mkdirp": "^0.5.0", + "ncp": "^2.0.0", + "nugget": "^1.4.1", + "plist": "^1.1.0", + "rimraf": "^2.3.2" + } +} diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..f50faf1 --- /dev/null +++ b/readme.md @@ -0,0 +1,35 @@ +# atom-shell-packager + +Build a distributable app from an atom-shell app source code directory. **Currently only Mac OS is implemented** but you can send PRs to implement windows/linux :) + +[![NPM](https://nodei.co/npm/atom-shell-packager.png)](https://nodei.co/npm/atom-shell-packager/) + +### installation + +``` +npm i atom-shell-packager +``` + +### usage + +``` +$ atom-shell-packager my-app-source-dir AppName +``` + +This will: + +- Download latest version of Atom Shell +- Create a Mac app in `cwd` called `AppName.app` + +You should be able to double-click `AppName.app` to launch the app. If not, check your settings and try again. + +### options + +these are optional CLI options you can pass in + +- `out` (default current working dir) - the dir to put the app into at the end +- `version` (default hardcoded in source) - atom-shell version to use +- `app-bundle-id` - bundle identifier to use in the app plist +- `helper-bundle-id` - bundle identifier to use in the app helper plist + +also, the entire `options` objects gets passed into the [`ncp`](https://npmjs.org/ncp) instance when copying your app source directory into the app container, so you can pass in any `ncp` options you want as well