Compare commits

...

168 Commits

Author SHA1 Message Date
Jared Allard 5dc698be9d minor comsetic logging fix. vbump to v0.4.1 2015-08-09 08:42:18 -07:00
Jared Allard 1bf334399b fix second run issues with --flag enabled. better error handling 2015-08-09 08:32:18 -07:00
Jared Allard a30db5fc5d package: finally got around to adding contrib 2015-06-29 10:41:16 -07:00
Jared Allard 77cfcf0da4 retarget 2.3.1 for nexe 2015-06-26 18:36:26 -07:00
Jared Allard d8541a82ac readme: note on output. 2015-06-26 18:30:35 -07:00
Jared Allard 489bd0f0fe exe: fixes #122, implement base nexe package field 2015-06-26 18:27:26 -07:00
Jared Allard a3f30bf783 nexe: vbump / remove devdepends 2015-06-26 15:30:02 -07:00
Jared Allard 61ff0b1052 changelog: maintainer fix 2015-06-19 21:49:15 -07:00
Jared Allard e02d39a6bf manifest: async 0.9.0 => 1.2.1 2015-06-19 21:46:00 -07:00
Jared Allard ca414f03db readme: author update 2015-06-19 21:43:23 -07:00
Jared Allard 4200724316 readme: clairify that all platforms require python 2015-05-31 11:53:07 -07:00
Jared Allard 686f67fac2 readme: clairify building requirements. 2015-05-31 11:50:54 -07:00
RainbowDashDC 494618cca1 nexe: vbump and dependencies. 2015-05-01 13:29:42 -07:00
Jared Allard 86fe200bfd Merge pull request #114 from shivamadhavan/master
Updated version of dependency builtins to 1.0.1 ( inclusion of console to the built in module list )
2015-04-16 21:11:54 -07:00
Shiva Kumar Madhavan c272f52994 Updated version of dependency builtins to 1.0.1 ( inclusion of console to the built in module list ) 2015-04-16 17:17:08 +08:00
Craig Jefferds 93ed48a537 Merge pull request #111 from lahdekorpi/patch-1
Fixed typo in README.md
2015-03-30 08:51:44 -07:00
Toni Lähdekorpi 740e3f441d Fixed typo in README.md 2015-03-30 18:51:18 +03:00
Jared Allard 8204feadaa Add 'readline' not include rule.
For some reason nexe attempts to include readline, this solves it. readline is a bultin of node as of 10
2015-03-20 22:08:31 -07:00
Jared Allard cdf53e133b Update README.md
Fixing a spelling mistake. Ugh.
2015-03-20 10:55:09 -07:00
Jared Allard 65c07d4e4a Update README to show new feature 2015-03-20 09:26:30 -07:00
Jared Allard 4c3443655e Merge pull request #108 from crcn/iojs
Implement io.js support! And a few fixes
2015-03-20 09:20:39 -07:00
RainbowDashDC 6d20d4da22 Fixes #107, implements --framework/-F. Fetchs iojs latest. 2015-03-19 23:50:48 -07:00
RainbowDashDC b72b14b6c3 Initial iojs support. 2015-03-16 10:36:39 -07:00
Jared Allard 9134bcf351 Add waffle.io board label 2015-03-08 20:49:52 -07:00
Christopher Karper 1c0d8d0fc0 Freshened up all dependencies 2015-02-22 21:32:59 -05:00
Christopher Karper a7c3fda721 Updated deps 2015-02-22 15:05:47 -05:00
Christopher Karper 7d75480a6f Renamed relative to absolute 2015-02-21 19:42:04 -05:00
Christopher Karper 67361b27e1 Update README.md
Added myself as a maintainer.
2015-02-21 19:35:17 -05:00
Christopher Karper 3b6f9ff4b7 This was bothering me... 2015-02-21 19:02:16 -05:00
RainbowDashDC 6fcfb10e38 Update changelog for 0.3.6 and 0.3.7 2015-02-21 01:32:20 -05:00
RainbowDashDC 06cab4f43b Publish new version to hopefully fix #103 2015-02-21 01:16:34 -05:00
Craig Jefferds 2cacd8340b Update README.md 2015-02-18 14:18:47 -08:00
Craig Jefferds 0e90ac9f16 Update README.md 2015-02-18 14:18:29 -08:00
Jared Allard efd3f78c9d Merge pull request #102 from gitter-badger/gitter-badge
Add a Gitter chat badge to README.md
2015-02-18 13:40:14 -08:00
The Gitter Badger 54967d1ab0 Added Gitter badge 2015-02-18 19:35:28 +00:00
RainbowDashDC bb489a3cb7 Fixes #98 by giving win32 a 100 length progress bar. 2015-02-15 19:38:35 -08:00
Jared Allard 6097c20204 Merge pull request #101 from CKarper/master
Lighter weight way to accomplish the exclusion of the sys module
2015-02-15 15:00:05 -08:00
Christopher Karper 39665a8d5c Lighter weight way to accomplish the exclusion of the sys module 2015-02-15 17:51:05 -05:00
Jared Allard f49ece0c86 Merge pull request #100 from CKarper/master
Stub to ignore require('sys')
2015-02-15 12:57:05 -08:00
Christopher Karper 5aca22d28e This handles embedding 'bin' scripts with shebang interpreter directives at the start 2015-02-15 15:02:58 -05:00
Christopher Karper e79b0fb23e Stub to ignore require('sys') 2015-02-15 14:52:40 -05:00
RainbowDashDC cac698609c V bump to solve critical error. 2015-02-15 11:10:34 -08:00
RainbowDashDC b040337a94 Fixes #99, resolves #97 by warning on missing file. New examples. New log functions 2015-02-15 11:05:24 -08:00
Jared Allard 06d7730802 Merge pull request #96 from CKarper/patch-1
Support .json extensions in require() resolution
2015-02-15 07:39:13 -08:00
Christopher Karper ad4da1d193 Support .json extensions in require() resolution
Embarrassingly simple fix.  Added .json to the list of extensions to search when a require with no extension is found.  

This resolves #57
2015-02-15 00:33:28 -05:00
RainbowDashDC 5927b45e70 Add changelog.md, add resourceFiles to example, MIT-LICENSE.txt => LICENSE.txt 2015-02-14 19:53:30 -08:00
RainbowDashDC e4155c8fed Version bump 0.3.5, update depends 2015-02-14 09:44:49 -08:00
RainbowDashDC e91f5b52af Add example, fix outdated examples 2015-02-14 01:57:54 -08:00
RainbowDashDC 3b1d5a9fe1 Modify readme, implement cross-plat --python <loc> closes #94 2015-02-14 01:50:32 -08:00
Jared Allard 3ac298fe4f Merge pull request #95 from LorenzGardner/master
Make process.argv consistent in the child fork case
2015-02-09 17:46:51 -08:00
Lorenz Gardner 229f0516c6 Merge branch 'master' of https://github.com/LorenzGardner/nexe 2015-02-09 16:06:29 -06:00
Lorenz Gardner 29d5f6aaeb Make process.argv consistent in the child fork cas
(argv.[0] must = the executable)
2015-02-09 16:05:09 -06:00
LorenzGardner 174599df30 Merge pull request #2 from crcn/master
Pull in changes to master
2015-02-09 15:56:29 -06:00
Jared Allard 3ca6bbbda2 Merge pull request #93 from LorenzGardner/embedFiles
Embed files
2015-01-31 18:56:18 -08:00
Lorenz Gardner 97dbd37068 Add support for embedded files. 2015-01-06 19:05:01 -06:00
Lorenz Gardner b615e125c0 Make the example code demonstrate forked process and dynamic require 2015-01-05 17:58:57 -06:00
LorenzGardner c34f6719b5 Merge pull request #1 from crcn/master
update
2014-12-30 12:07:37 -06:00
Craig Jefferds 2342fe6fdd Merge pull request #92 from LorenzGardner/child.fork
Add child_process.fork support.
2014-12-23 19:59:18 -03:00
LorenzGardner 333cc697c3 update read me mentioning usage of child_process.fork 2014-12-23 12:16:49 -06:00
Lorenz Gardner ece4b2d62a Add child_process.fork support. 2014-12-23 12:01:33 -06:00
Craig Jefferds ba62973dca Merge pull request #88 from LorenzGardner/master
Add support for JSON files, and __dirname
2014-12-19 16:05:25 -08:00
LorenzGardner 9b5892e6ad clarify workaround for native module support 2014-12-19 14:23:40 -06:00
Lorenz Gardner f7ad9a8e83 It actually makes way more sense for __driname to be exectuable dir rather
than the cwd.
2014-12-18 18:02:48 -06:00
LorenzGardner 7c1331bed8 Update README.md
update the readme to explain how to workaround the limitations (not supporting dynamic require statements and lack of native module support the pseudo support of __dirname)
2014-12-18 17:46:55 -06:00
Lorenz Gardner e55dacf8c8 Merge branch 'JSON-Support'
Conflicts:
	lib/bundle.js
2014-12-18 17:02:29 -06:00
Lorenz Gardner ec79ff85d4 add __dirname support 2014-12-17 18:52:04 -06:00
Lorenz Gardner 99a8cbe9b3 Add JSON support for require statments. 2014-12-17 13:09:00 -06:00
LorenzIndus f458298ffb update version of builtins in deps
Get the fix they did to include the "constants" builtin module.
2014-12-17 08:48:01 -06:00
Craig Jefferds c3fa94a2e5 Merge pull request #83 from rknell/patch-1
Update README.md
2014-11-04 14:41:23 -08:00
rknell 961f72b1d9 Update README.md
Adding missing comma to example
2014-11-05 07:57:53 +10:00
Craig Jefferds d91d91fc2b Merge pull request #82 from RainbowDashDC/master
Prevent Windows Paths from causing issues.
2014-10-27 18:21:34 -07:00
Jared Allard 273bfa3e4d Prevent Windows Paths from causing issues. 2014-10-27 15:14:55 -07:00
Craig Condon 31b01469c7 v bump 2014-10-10 09:23:51 -07:00
Craig Condon b94d0c3719 Merge branch 'master' of github.com:crcn/nexe 2014-10-10 09:23:31 -07:00
Craig Condon 275a7b025b fix issue loading native modules 2014-10-10 09:23:20 -07:00
Craig Jefferds 71d7b97736 Update README.md 2014-09-19 12:09:10 -07:00
Craig Jefferds faf0a85b36 Merge pull request #78 from tm1000/patch-1
Update README.md
2014-09-16 11:31:11 -07:00
Craig Jefferds 56578c09b1 Merge pull request #79 from tm1000/patch-2
Remove all non-ascii code from external sources
2014-09-16 11:31:01 -07:00
Andrew Nagy 6ad1ec436c Remove all non-ascii code from external sources
Remove all non-ascii code from external sources
2014-09-16 10:32:45 -07:00
Andrew Nagy 62461dbc41 Update README.md
Fix the documentation :-)
2014-09-12 16:14:04 -07:00
Craig Jefferds 7f34aa8854 Merge pull request #74 from caffeinewriter/replace-yargs
Replace optimist with yargs
2014-08-29 19:13:00 -07:00
Brandon Anzaldi 76072f6df9 Replace optimist with yargs in nexe bin 2014-08-29 18:44:52 -07:00
Brandon Anzaldi 83daa5553b Replace Optimist with Yargs in Package.json 2014-08-29 18:43:06 -07:00
Craig Condon ff09ef6755 cleanup 2014-08-10 23:46:38 -07:00
Craig Condon 85c8831248 include all node.js builtins 2014-08-10 23:32:01 -07:00
Craig Condon 3d2ae606ef v bump 2014-07-30 12:22:50 -07:00
Craig Condon d4f27aea7f filter http 2014-07-30 12:22:37 -07:00
Craig Condon 87abd1a295 remove commented out code 2014-07-30 11:38:16 -07:00
Craig Condon 9fd462da2f v bump 2014-07-30 11:37:20 -07:00
Craig Condon 60849404a2 remove sardines - move into nexe. Use bundle.js 2014-07-30 11:37:05 -07:00
Craig Condon 00fa37fff0 start on using browserify 2014-07-30 11:12:20 -07:00
Craig Condon 270350fda6 fix #48 - ability to just run ----> bundle /Users/craig/Developer/Public/nexe/lib/index.js
unable to include script /Users/craig/Developer/Public/nexe/lib/exe.js from /Users/craig/Developer/Public/nexe/lib/index.js, Error: Cannot find module 'nexe'
    at Function.module.exports [as sync] (/Users/craig/Developer/Public/nexe/node_modules/sardines/node_modules/amdify/node_modules/resolve/lib/sync.js:32:11)
    at resolvePath (/Users/craig/Developer/Public/nexe/node_modules/sardines/node_modules/amdify/lib/pathInfo.js:135:20)
    at self.getPathInfo (/Users/craig/Developer/Public/nexe/node_modules/sardines/node_modules/amdify/lib/pathInfo.js:88:24)
    at /Users/craig/Developer/Public/nexe/node_modules/sardines/node_modules/amdify/lib/analyzeDeps.js:324:13
    at /Users/craig/Developer/Public/nexe/node_modules/async/lib/async.js:111:13
    at Array.forEach (native)
    at _each (/Users/craig/Developer/Public/nexe/node_modules/async/lib/async.js:32:24)
    at Object.async.each (/Users/craig/Developer/Public/nexe/node_modules/async/lib/async.js:110:9)
    at scanRequired (/Users/craig/Developer/Public/nexe/node_modules/sardines/node_modules/amdify/lib/analyzeDeps.js:321:9)
    at Function.on.success.deps.forEach.dep.source (/Users/craig/Developer/Public/nexe/node_modules/sardines/node_modules/amdify/lib/analyzeDeps.js:245:5) in cwd. Resolves package.json main script
2014-05-28 10:47:52 -07:00
Craig Condon dd2aa5a831 Merge pull request #55 from fritx/patch-1
Update README.md
2014-05-28 10:28:08 -07:00
Fritz Lin afc7140b6b Update README.md
Better style with Code Usage in README.md
2014-05-28 22:02:28 +08:00
Craig Condon 1d47091304 v bump 2014-05-13 11:42:44 -07:00
Craig Condon 36bbdd4aa9 Merge pull request #52 from jhbruhn/master
Windows support
2014-05-12 14:40:28 -07:00
Jan-Henrik e73804a4dd Added Windows support to Readme 2014-05-12 20:33:04 +02:00
Jan-Henrik bd1152357e Added Windows Support using vcbuild.bat 2014-05-12 20:29:02 +02:00
Craig Condon c53f229848 added progress to package.json 2014-03-06 11:28:00 -08:00
Craig Condon 3cb81249d8 Merge pull request #46 from northshorenetworks/master
Updated README.md
2014-02-28 19:43:16 -08:00
Adam Snodgrass 518fbc7280 Updated README.md 2014-02-28 21:40:59 -06:00
Craig Condon dd5607886a Merge pull request #45 from northshorenetworks/master
Remove duplicate _log definition in monkeypatch.js
2014-02-28 19:39:44 -08:00
Adam Snodgrass 666774b5b5 Remove duplicate _log definition 2014-02-28 21:35:56 -06:00
Adam Snodgrass 3f75ae462e Merge pull request #2 from crcn/master
Pull in crcn/nexe master changes
2014-02-28 21:33:12 -06:00
Craig Condon dacb31fd67 Merge pull request #44 from northshorenetworks/master
Add option to pass through CLI flags but ignore node and v8 flags
2014-02-28 19:31:00 -08:00
Adam Snodgrass d4e62c668e Add option to disable node and v8 flags and pass through app flags 2014-02-28 21:16:38 -06:00
Craig Condon b267d9ba41 fix typo 2014-02-28 19:01:16 -08:00
Adam Snodgrass 75932723ac Added progress to package.json dependencies; Defined _log in monkeypatch.js 2014-02-28 18:54:38 -06:00
Adam Snodgrass 28442e6714 Merge pull request #1 from crcn/master
Pull in crcn/nexe master changes
2014-02-28 18:14:51 -06:00
Craig Condon 9bb3b76a65 remove old file 2014-02-28 10:46:43 -08:00
Craig Condon 6702ce326a resolve merge conflict 2014-02-28 10:40:07 -08:00
Craig Condon 27075a778d move utils to their own file 2014-02-28 10:39:13 -08:00
Craig Condon 368195be77 Update README.md 2014-02-28 10:33:18 -08:00
Craig Condon b11ce7540c Update README.md 2014-02-28 10:23:52 -08:00
Craig Condon 069c910b7b Update README.md 2014-02-28 10:23:40 -08:00
Craig Condon 934c7bb3d5 Update README.md 2014-02-28 10:23:04 -08:00
Craig Condon 8c8a1eddd7 Update README.md 2014-02-28 10:21:27 -08:00
Craig Condon 3eea6784dd Update README.md 2014-02-28 10:21:17 -08:00
Craig Condon cef44e9b77 Update README.md 2014-02-28 10:20:53 -08:00
Craig Condon b6f555c223 Merge pull request #42 from northshorenetworks/master
Add platform detection for openbsd & freebsd compatibility
2014-02-28 10:17:06 -08:00
Adam Snodgrass 87cacafd3e Add platform detection for openbsd & freebsd compatibility 2014-02-27 23:08:33 -08:00
Craig Condon 9caa365a3e Merge branch 'master' of github.com:crcn/nexe 2014-02-27 16:49:56 -08:00
Craig Condon e7e80f5a2c refactor 2014-02-27 16:49:35 -08:00
Craig Condon 4284c399dd Merge pull request #36 from tallesl/issue35
Solves #35
2013-12-12 22:18:07 -08:00
Talles L 89eeeda575 Solves #35 2013-12-13 03:25:03 -02:00
Craig Condon 3b1b82dc40 cleanup 2013-10-14 10:40:46 -07:00
Craig Condon a9a97fefe1 download latest version 2013-10-14 10:29:35 -07:00
Craig Condon 12a7069a32 v bump 2013-10-14 10:26:47 -07:00
Craig Condon 533ed8c500 Merge branch 'master' of github.com:crcn/nexe 2013-10-14 10:25:57 -07:00
Craig Condon 875d6d0ff7 update node version 2013-10-14 10:25:46 -07:00
Craig Condon ea2cfdf5ee Merge pull request #32 from samyakbhuta/master
Installing 'nexe' globally.
2013-10-14 10:22:52 -07:00
Samyak Bhuta 60ebde86cc Added preference for global install. 2013-10-14 18:47:33 +05:30
Samyak Bhuta d927887355 'nexe', can be installed globally. 2013-10-14 16:28:08 +05:30
Craig Condon 04280a3016 Merge pull request #29 from alexwhitman/node-argv
Unshift 'node' onto process.argv
2013-08-18 10:36:51 -07:00
Alex Whitman 3c084b9573 Unshift 'node' onto process.argv
The node executable is the first value in argv. This was missing after
compiling.
2013-08-18 18:16:23 +01:00
Craig Condon 708851cc40 Merge pull request #28 from alexwhitman/fixup
Linting, spawning and temp directory
2013-08-17 08:37:59 -07:00
Alex Whitman 2214dccd4a Add temp option to README 2013-08-17 12:40:00 +01:00
Alex Whitman ca9fced819 Add -t|--temp option to specify location for node.js sources 2013-08-17 12:04:38 +01:00
Alex Whitman 684b285217 Rewrite configure/make spawning 2013-08-17 11:36:03 +01:00
Alex Whitman 1dc6243b75 Fix up linting warnings
- Mix of tabs and spaces
- Trailing whitepsace
- Missing semi-colons
2013-08-17 10:31:55 +01:00
Craig Condon f1a8a7269f fix #26 - should resolve to absolute path unless / is the first character 2013-07-26 13:40:54 -07:00
Craig Condon 4e8830365e added mit license 2013-06-04 14:32:26 -07:00
Craig Condon 34e6f79096 update readme 2013-04-29 12:41:14 -07:00
Craig Condon e58e22a329 updated example 2013-04-09 13:52:47 -07:00
Craig Condon 4866e04c13 replace browserify with sardines 2013-04-09 13:37:45 -07:00
Craig Condon bedcdfe26f v bump 2013-02-27 11:27:10 -08:00
Craig Condon 5fe8618236 added ability to use -h or --help for help menu 2013-02-27 11:26:44 -08:00
Craig Condon 127377a92b properly parse relative path 2013-02-01 11:39:52 -08:00
Craig Condon d6a083778a cleanup 2013-02-01 11:39:32 -08:00
Craig Condon a52eae6665 Merge branch 'master' of github.com:crcn/nexe 2013-02-01 11:37:03 -08:00
Craig Condon 75ecf22ba9 properly parse relative path 2013-02-01 11:36:47 -08:00
Craig Condon 7f444e93de Update README.md 2013-02-01 11:30:47 -08:00
Craig Condon 818da103a8 added dependency 2013-01-31 12:19:14 -08:00
Craig Condon b565aaafc0 Update README.md 2012-12-02 12:08:10 -06:00
Craig Condon 67282e2506 remove node modules 2012-11-30 20:17:44 -06:00
Craig Condon 3c432a0d3a cleanup 2012-11-30 20:16:17 -06:00
Craig Condon a831244c3d finally works 2012-11-30 20:12:56 -06:00
Craig Condon ad5532eaad finally works 2012-11-30 20:11:55 -06:00
Craig Condon 8b03984ca8 fix package repo 2012-02-17 14:54:58 -06:00
Craig Condon 953d57240f update pkg 2011-11-30 12:55:16 -06:00
Craig Condon dfb751ca12 updated readme 2011-11-26 17:34:11 -06:00
Craig Condon 0813ef0f67 typo 2011-11-26 17:30:50 -06:00
Craig Condon 1e12cad040 can build node.js file from cwd now 2011-11-26 17:30:13 -06:00
Craig Condon 015b60ee24 can build node.js file from cwd now 2011-11-26 17:24:25 -06:00
Craig Condon 66d3454129 updated readme 2011-11-26 17:03:30 -06:00
Craig Condon b385069ebb updated readme 2011-11-26 17:03:08 -06:00
Craig Condon 51879ed636 updated readme 2011-11-26 17:01:47 -06:00
Craig Condon c018684658 ability to build executables 2011-11-26 17:00:12 -06:00
52 changed files with 1513 additions and 1869 deletions
+3 -1
View File
@@ -1,2 +1,4 @@
[commands] [commands]
proj = subl --project project.sublime-project proj = subl .
.DS_Store
+9
View File
@@ -0,0 +1,9 @@
node_modules
.DS_Store
*.nex
src
nexe.exe
nexe
npm-debug.log
examples/**/src
examples/**/out.nex
View File
+59
View File
@@ -0,0 +1,59 @@
# Nexe ChangeLog
## 2015-02-20, Version v0.3.7, @jaredallard
### Noteable Changes
* Fixed #103.
* Made not-available require not a fatal error.
* Stub and system to ignore certain requires.
* Added 'sys' to ignore list.
* We have a gitter!
* Gave win32 a 100 length progress bar.
### Commits
* [**2cacd83**] Update README.md (@crcn)
* [**0e90ac9**] Update README.md (@crcn)
* [**54967d1**] Added Gitter badge (@jaredallard)
* [**bb489a3**] Fixes #98 by giving win32 a 100 length progress bar. (@jaredallard)
* [**39665a8**] Lighter weight way to accomplish the exclusion of the sys module (@CKarper)
* [**5aca22d**] This handles embedding 'bin' scripts with shebang interpreter... (@CKarper)
* [**e79b0fb**] Stub to ignore require('sys') (@CKarper)
## 2015-02-15, Version v0.3.6, @jaredallard
### Noteable Changes
* Now support .json in require.
* Fixed a major --python flag bug.
### Commits
* [**cac6986**] V bump to solve critical error. (@jaredallard)
* [**b040337**] Fixes #99, resolves #97 by warning on missing file. New examples... (@jaredallard)
* [**ad4da1d**] Support .json extensions in require() resolution (@CKarper)
## 2015-02-14, Version v0.3.5, @jaredallard
### Noteable Changes
* Added new flag: `--python </path/to/python>`
* Added resourceFiles option which allows embedding files and getting them via embed.js
* Updated a bunch of the dependencies.
* `process.argv` is now consistent in a child fork case.
* Added `child_process.fork` support.
* Added new collaborators:
* Jared Allard (@jaredallard)
### Commits
* [**e4155c8**] Version bump 0.3.5, update depends (@jaredallard)
* [**e91f5b5**] Add example, fix outdated examples (@jaredallard)
* [**3b1d5a9**] Modify README, implement cross-plat `--python <loc>` closes #94 (@jaredallard)
* [**29d5f6a**] Make `process.argv` consistent in the child fork case (@LorenzGardner)
* [**97dbd37**] Add support for embedded files. (@LorenzGardner)
* [**b615e12**] Make the example code demonstrate forked process and dynamic require (@LorenzGardner)
* [**333cc69**] update read me mentioning usage of `child_process.fork` (@LorenzGardner)
* [**ece4b2d**] Add `child_process.fork` support. (@LorenzGardner)
+20
View File
@@ -0,0 +1,20 @@
Copyright (c) 2013 Craig Condon
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+145 -26
View File
@@ -1,58 +1,177 @@
Compile javascript **with** node.js. This allows you to move your executable around *without* needing to install the node.js runtime. ### Nexe
## Requirements [![Join the chat at https://gitter.im/crcn/nexe](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/crcn/nexe?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Dependency Status](https://david-dm.org/crcn/nexe.svg)](https://david-dm.org/crcn/nexe)
[![Stories in Ready](https://badge.waffle.io/crcn/nexe.svg?label=ready&title=Ready)](http://waffle.io/crcn/nexe)
- Linux / Mac Nexe is a command-line utility that compiles your Node.js application into a single executable file.
![screen shot 2014-02-28 at 10 32 54 am](https://f.cloud.github.com/assets/757408/2296993/c276f7b6-a0a6-11e3-86d3-e6c5feba2a85.png)
### Motivation
- Ability to run multiple applications with *different* node.js runtimes.
- Distributable binaries without needing node / npm.
- Starts faster.
- Lockdown specific application versions, and easily rollback.
- Faster deployments.
## Building Requirements
- Linux / Mac / BSD / Windows
- Python 2.6 or 2.7 (use --python if not in PATH)
- Windows: Visual Studio 2010+
## Caveats
### Doesn't support native modules
- Use the techniques below for working around dynamic require statements to exclude the module from the bundling, and deploy along side the executable in a node_module folder so your app can find it. Note: On windows you may need to have your app be named node.exe if .node file depends on node.
### Doesn't support dynamic require statements
Such As:
```javascript
var x = require(someVar);
```
In this case nexe won't bundle the file
```javascript
var x;
if (someCheck) {
x = require("./ver1.js");
} else {
x = require("./var2.js");
}
```
In this case nexe will bundle both files.
Workarounds:
1) for dynamic requires that you want bundled add the following into your project
```javascript
var dummyToForceIncludeForBundle = false;
if (dummyToForceIncludeForBundle) {
require("./loadedDynamicallyLater.js");
// ...
}
```
this will trick the bundler into including them.
2) for dynamic files getting included that you don't want to be
```javascript
var moduleName = "./ver2.js";
if (someCheck) {
moduleName = "./ver1.js";
}
var x = require(moduleName);
```
Note: neither file will be bundled.
Using these two techniques you can change your application code so modules are not bundles, and generate a includes.js file as part of your build process so that the right files get bundled for your build configuration.
### &#95;&#95;dirname
Once the module is bundled it is part of the executable. &#95;&#95;dirname is therefore the executable dir (process.execPath). Thus if you put resources on a relative path from the the executable your app will be able to access them.
If you had a data file at `/dev/myNodeApp/stateManager/handler/data/some.csv`
and a file at `/dev/myNodeApp/stateManager/handler/loader.js`
```javascript
module.exports = fw.readFileSync(path.join(__dirname, "./data/some.csv"));
```
You would need to deploy some.csv in a sub dir `data/` along side your executable
There are potential use cases for &#95;&#95;dirname where the executable path is not the correct substitution, and could result in a silent error (possibly even in a dependency that you are unaware of).
Note: &#95;&#95;filename will be 'undefined'
### child_process.fork
child_process.spawn works is unmodified, but child_process.fork will make an attempt to launch a new instance of your executable and run the bundled module.
## Installation ## Installation
Via NPM: Via NPM:
```bash ```bash
npm install nexe npm install nexe [-g]
``` ```
Or git: Or git:
```bash ```bash
git clone git clone https://github.com/crcn/nexe.git
``` ```
### Motivation
- Developing client-side utilities without requiring to install a bunch of dependencies first (node.js, npm).
- Ability to run multiple node.js applications with *different* node.js runtimes.
### CLI Usage ### CLI Usage
````text ```text
Commands: Usage: nexe -i [sources] -o [binary] [options]
-i the input javascript files
-o the output executable
--runtime the runtime version of node.js to compile with
Examples: Options:
-i input.js -o my-binary --runtime=0.6.2 compile javascript file with node -i, --input The entry javascript files [default: cwd]
-o, --output The output binary [default: out.nex]
-r, --runtime The node.js runtime to use [default: "latest"]
-t, --temp The path to store node.js sources [default: ./tmp/nexe]
-f, --flags Don't parse node and v8 flags, pass through app flags [default: false]
-v, --version Display version number
-p, --python Set path of python to use. [default: "python"]
-F, --framework Set the framework to use. [default: "nodejs"]
```` ```
### Code usage ### Code Usage
````javascript ```javascript
var nexe = require('nexe'); var nexe = require('nexe');
nexe.compile('input.js', 'output.bin', function() { nexe.compile({
input: 'input.js',
output: 'path/to/bin',
nodeVersion: '0.12.5',
nodeTempDir: 'src',
python: 'path/to/python',
resourceFiles: [ 'path/to/a/file' ],
flags: true,
framework: "nodejs"
}, function(err) {
console.log(err);
});
}); ```
```` ### package.json inclusion
As of 0.4.0 you can now embed nexe options into package.json. Note that this Format
is still in works, so it is likely to change.
```
"nexe": {
"input": "./bin/nexe",
"output": "nexe^$",
"temp": "src",
"runtime": {
"framework": "iojs",
"version": "2.3.1",
"ignoreFlags": true
}
}
```
Notes:
* output: can use ^$ for platform specific file extension
## Maintainers
* __Jared Allard__ ([@jaredallard](https://github.com/jaredallard)) &lt;[jaredallard@outlook.com](mailto:jaredallard@outlook.com)&gt; (Active)
* __Christopher Karper__ ([@ckarper](https://github.com/CKarper)) &lt;[Christopher.Karper@gmail.com](mailto:Christopher.Karper@gmail.com)&gt; (Active)
* __Craig Jefferds__ ([@crcn](https://github.com/crcn)) &lt;[craig.j.condon@gmail.com](mailto:craig.j.condon@gmail.com)&gt; (Not Active)
Regular → Executable
+94
View File
@@ -1,2 +1,96 @@
#!/usr/bin/env node #!/usr/bin/env node
var path = require('path'),
fs = require('fs'),
nexe = require('../lib'),
_log = require("../lib/log"),
cli = require('yargs').
usage('Usage: $0 -i [sources] -o [binary]').
options('i', {
demand: true,
alias: 'input',
desc: 'The entry javascript files',
default: process.cwd()
}).
options('o', {
demand: true,
alias: 'output',
desc: 'The output binary',
default: "out.nex"
}).
options('r', {
alias: 'runtime',
default: 'latest',
description: 'The node.js runtime to use'
}).
options('t', {
alias: 'temp',
default: './tmp/nexe',
description: 'The path to store node.js sources'
}).
options('f', {
alias: 'flags',
description: 'Don\'t parse node and v8 flags, pass through app flags',
default: false
}).
options('v', {
alias: 'version',
description: 'Display version number'
}).
options('p', {
alias: 'python',
description: 'Set path of python to use.',
default: 'python'
}).
options('F', {
alias: 'framework',
description: 'Set the framework to use',
default: 'nodejs'
});
var argv = cli.argv;
if(argv.h || argv.help) {
cli.showHelp();
process.exit();
} else if (argv.v || argv.version) {
var pkginfo = require('../package.json');
console.log(pkginfo.version);
process.exit();
}
/**
* TODO: Support network shares?
**/
function toAbsolute(pt) {
if(pt.substr(0, 1) == "/") return pt;
if(pt.substr(1, 3) == ":/") return pt; // for windows "c:/"
return path.join(process.cwd(), pt);
}
if(fs.lstatSync(argv.i).isDirectory()) {
opts = nexe.package(path.join(argv.i, "package.json"), argv);
nexe.compile(opts, function(error) {
if(error) {
console.log(error.message);
}
});
} else {
/**
* Call the core
**/
nexe.compile({
input : require.resolve(toAbsolute(argv.i)),
output : toAbsolute(argv.o),
flags : argv.f,
nodeVersion : argv.r,
python : argv.python,
nodeTempDir : toAbsolute(argv.t),
framework : argv.F
},
function(error) {
if(error) {
console.log(error.message);
}
}
);
}
+1
View File
@@ -0,0 +1 @@
console.log("hello browser!");
+19
View File
@@ -0,0 +1,19 @@
var nexe = require('../..');
nexe.compile(
{
input: "./index.js",
output: "./out.nex",
nodeVersion: "3.0.0",
framework: "iojs",
nodeTempDir: "src",
python: "python",
flags: true,
resourceFiles: ["./message.txt"]
},
function (err) {
if (err) {
console.log(err);
}
}
);
+1
View File
@@ -0,0 +1 @@
Hello World!!!
+23
View File
@@ -0,0 +1,23 @@
var http = require("http"),
fs = require("fs"),
path = require("path"),
nexeres = require("nexeres"),
childProc = require("child_process"),
port = 1337;
//Fork a new process to execute the broser.js
childProc.fork(path.join(__dirname, "browser.js"));
if (false) {
require("./browser.js"); //force the bundler to include the .js file
}
//start a web server on specified port (or default if not given)
console.log("started HTTP server on port %d", port = Number(process.argv.concat().pop()) || port);
http.createServer(function(req, res) {
//return the embeded file in response to any request
res.write(nexeres.get("message.txt"));
res.end();
}).listen(port);
+1
View File
@@ -0,0 +1 @@
hello world!
+4
View File
@@ -0,0 +1,4 @@
{
"main": "./index.js",
"browser": "./index.js"
}
+1
View File
@@ -0,0 +1 @@
console.log("hello browser!");
+18
View File
@@ -0,0 +1,18 @@
var nexe = require('../..');
nexe.compile(
{
input: "./index.js",
output: "./out.nex",
nodeVersion: "3.0.0",
nodeTempDir: "./src",
framework: "iojs",
python: 'python',
flags: true
},
function (err) {
if (err) {
console.log(err);
}
}
);
+23
View File
@@ -0,0 +1,23 @@
var http = require("http"),
fs = require("fs"),
path = require("path"),
nexeres = require("nexeres"),
childProc = require("child_process"),
port = 1337;
//Fork a new process to execute the broser.js
childProc.fork(path.join(__dirname, "browser.js"));
if (false) {
require("./browser.js"); //force the bundler to include the .js file
}
//start a web server on specified port (or default if not given)
console.log("started HTTP server on port %d", port = Number(process.argv.concat().pop()) || port);
http.createServer(function(req, res) {
//return the embeded file in response to any request
res.write("Hello, world!");
res.end();
}).listen(port);
+1
View File
@@ -0,0 +1 @@
hello world!
+4
View File
@@ -0,0 +1,4 @@
{
"main": "./index.js",
"browser": "./index.js"
}
+185
View File
@@ -0,0 +1,185 @@
/**
* Copyright (c) 2013 Craig Condon
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**/
var mdeps = require("module-deps"),
through = require("through"),
async = require("async"),
builtins = require("builtins");
var _log = require("./log");
function bundle (input, complete) {
async.waterfall([
/**
* first we resolve all of the deps
*/
function resolveDeps (next) {
var deps = [];
var md = mdeps({
xtransform: function (tr, file) {
var buffer = [];
console.log(tr);
return through(write, end);
var self = this;
function write (chunk) {
buffer.push(chunk.toString());
// console.log(chunk.toString(""))
console.log(tr);
}
function end() {
var content = buffer.join("");
// console.log(content);
/*
// TODO add uglify flag
var source = uglify.parse(content, {
strict: false
});
source.figure_out_scope();
source.compute_char_frequency();
source.mangle_names();
// TODO - production
content = source.print_to_string({
ascii_only: true,
quote_keys: true
});*/
this.queue(content);
this.queue(null);
}
},
filter: function (id) {
if ([ 'nexeres', 'sys', 'readline' ].indexOf(id) > -1) { return false; }
return !~builtins.indexOf(id);
},
extensions: [ '.js', '.json' ],
ignoreMissing: true
});
/** event for missing packages, fixes conditional requires **/
md.on('missing', function(id, parent) {
_log("warn", "couldn't find require '" + id + "', errors may occur.");
});
md.pipe(through(function (chunk) {
deps.push(chunk);
}, function () {
next(null, deps);
}));
md.end({ file: input })
},
function bundleScript (deps, next) {
var buffer = [loader.toString()];
var dbuffer = [];
for (var i = deps.length; i--;) {
var dep = deps[i];
var req = "function (require, module, exports, __dirname) { \n"
if (dep.id.toLowerCase().indexOf(".json", dep.id.length - 5) !== -1) {
//this is the result of require("someFile.json"), so we need to export it from the function
req += "module.exports = "
}
if ((/^\#\!/).test(dep.source)) {
dep.source = '//' + dep.source;
}
req += dep.source + "}";
dbuffer.push(JSON.stringify(dep.id) + ": ["+req+", "+!!dep.entry+", "+JSON.stringify(dep.deps)+"]")
}
buffer = ["(" + loader.toString() + ").call(null, {"+dbuffer.join(",")+"}," + JSON.stringify(deps[deps.length-1].id) + ")"].toString();
next(null, buffer);
}
], complete)
}
var loader = function (deps, key) {
var pathModule = global.require("path");
var darr = [];
var dir = global.require("path").dirname(process.execPath);
var argv3 = process.argv[3];
if (argv3) {
argv3 = pathModule.relative(pathModule.dirname(process.execPath), argv3);
argv3 = pathModule.resolve(pathModule.dirname(key), argv3);
}
if (process.argv[2] == "--child_process" && deps[argv3]) {
//we've been forked and should run the module specified by argv3[3] instead of the start up module
key = argv3;
process.argv.splice(2, 2); //restore the argv to [0] = executable, [1] = nexejs
}
else if (process.argv[2] == "--child_process") {
//fork called, but for a module not bundled.
argv3 = process.argv[3];
process.argv.splice(1, 2); //restore the argv to [0] = executable, [1] = script
global.require(argv3);
return;
}
darr.push(deps[key]); //start up module.
function initModule (dep) {
if (dep.module) return dep.module.exports;
dep.module = { exports: {} };
dep[0](function (path) {
var rdep = deps[dep[2][path]];
var exports = rdep ? rdep.module ? rdep.module.exports : initModule(rdep) : global.require(path);
return exports;
}, dep.module, dep.module.exports, dir);
return dep.module.exports;
}
//run the startup module
darr.forEach(initModule);
return darr.filter(function (dep) {
return dep[1];
}).map(function (dep) {
return dep.module || {};
}).pop();
}
module.exports = bundle;
+64
View File
@@ -0,0 +1,64 @@
/**
* Copyright (c) 2013 Craig Condon
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**/
var path = require("path"),
fs = require("fs");
/**
* TODO: Optimize this code. (more like document it so I understand it better.)
**/
function embed(resourceFiles, resourceRoot, complete) {
function encode(filePath) {
return fs.readFileSync(filePath).toString('base64');
}
resourceFiles = resourceFiles || [];
resourceRoot = resourceRoot || "";
if (!Array.isArray(resourceFiles)) {
throw new Error("Bad Argument: resourceFiles is not an array");
}
var buffer = "var embeddedFiles = {\n";
for (var i = 0; i < resourceFiles.length; ++i) {
buffer += JSON.stringify(path.relative(resourceRoot, resourceFiles[i])) + ': "';
buffer += encode(resourceFiles[i]) + '",\n';
}
buffer += "\n};\n\nmodule.exports.keys = function () { return Object.keys(embeddedFiles); }\n\nmodule.exports.get = ";
buffer += accessor.toString();
complete(null, buffer);
}
var accessor = function (key) {
if (embeddedFiles.hasOwnProperty(key)) {
return new Buffer(embeddedFiles[key], 'base64');
}
else {
//file was not embedded, throw err.
throw new Error('Embedded file not found');
}
}
module.exports = embed;
+674
View File
@@ -0,0 +1,674 @@
/**
* Copyright (c) 2013 Craig Condon
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**/
var async = require("async"),
outcome = require("outcome"),
mkdirp = require("mkdirp"),
request = require("request"),
path = require("path"),
fs = require("fs"),
ncp = require("ncp").ncp,
ProgressBar = require("progress"),
child_process = require("child_process"),
glob = require("glob"),
bundle = require("./bundle"),
embed = require("./embed"),
os = require("os"),
targz = require('tar.gz'),
_log = require("./log"),
_monkeypatch = require("./monkeypatch"),
spawn = child_process.spawn;
var isWin = /^win/.test(process.platform);
var isPy;
var framework;
var version;
var option_list = [
"python",
"input",
"output",
"nodeTempDir",
"flags",
"framework",
"nodeVersion"
]
/**
* Compiliation process.
*/
exports.compile = function (options, complete) {
var nodeCompiler, nexeEntryPath;
async.waterfall([
/**
*check relevant options
*/
function checkOpts (next) {
/* failsafe */
if(options === undefined) {
_log("error", "no options given to .compile()");
process.exit()
}
option_list.forEach(function(v) {
if(options[v] === undefined) {
_log("error", "option "+v+" was empty")
process.exit();
}
});
/**
* Have we been given a custom flag for python executable?
**/
if(options.python!=='python' && options.python!==""
&& options.python!==undefined) {
if(isWin) {
isPy=options.python.replace(/\//gm, "\\"); // use windows file paths, batch is sensitive.
} else {
isPy=options.python;
}
_log("set python as "+isPy);
} else {
isPy="python";
}
// remove dots
options.framework = options.framework.replace(/\./g, "");
// set outter-scope framework variable.
framework = options.framework;
_log("framework => "+framework);
version = options.nodeVersion; // better framework vc
// check iojs version
if (framework === "iojs" && version === "latest" ) {
_log("fetching iojs versions");
mkdirp(options.nodeTempDir); // make temp dir, probably repetive.
// create write stream so we have control over events
var output = fs.createWriteStream(path.join(options.nodeTempDir,
"iojs-versions.json"));
request.get("https://iojs.org/dist/index.json")
.pipe(output);
output.on('close', function() {
_log("done");
var f = fs.readFileSync(path.join(options.nodeTempDir,
"iojs-versions.json"));
f = JSON.parse(f);
version = f[0].version.replace("v", "");
_log("iojs latest => "+version);
// continue down along the async road
next();
})
} else {
next();
}
},
/**
* first download node
*/
function downloadNode (next) {
_downloadNode(version, options.nodeTempDir, next);
},
/**
* bundle the application into one script
*/
function combineProject (nc, next) {
nodeCompiler = nc;
_log("bundle %s", options.input);
bundle(options.input, next);
},
/**
* write the bundle to the lib directory of the target node version
*/
function writeBundle (source, next) {
bundlePath = path.join(nodeCompiler.dir, "lib", "nexe.js");
_log("bundle -> %s", bundlePath);
//Remove all non-ascii code from sources
source = source.replace(/[^\x00-\x7F]/g, "");
// same path as all the other JS files
fs.writeFile(bundlePath, source, next);
},
function embedResources(next) {
_log("embedResources %s", options.resourceFiles);
embed(options.resourceFiles, options.resourceRoot, next);
},
function writeResources (resources, next) {
resourcePath = path.join(nodeCompiler.dir, "lib", "nexeres.js");
_log("resource -> %s", resourcePath);
fs.writeFile(resourcePath, resources, next);
},
/**
* monkeypatch some files so that the nexe.js file is loaded when the app runs
*/
function monkeyPatchNodeConfig (next) {
_monkeyPatchNodeConfig(nodeCompiler, next);
},
/**
* monkeypatch node.cc to prevent v8 and node from processing CLI flags
*/
function monkeyPatchNodeCc (next) {
if (options.flags) {
_monkeyPatchMainCc(nodeCompiler, next);
} else {
next();
}
},
/**
* monkeypatch child_process.js so nexejs knows when it is a forked process
*/
function monkeyPatchChildProc(next) {
_monkeyPatchChildProcess(nodeCompiler, next);
},
/**
* compile the node application
*/
function makeExe (next) {
if(isWin) {
_log("vcbuild [make stage]");
} else {
_log("make");
}
nodeCompiler.make(next);
},
/**
* we create the output directory if needed
*/
function makeOutputDirectory (next) {
mkdirp(path.dirname(options.output), function(){ next(); });
},
/**
* Copy the compilied binary to the output specified.
*/
function copyBinaryToOutput (next) {
_log("cp %s %s", nodeCompiler.releasePath, options.output);
ncp(nodeCompiler.releasePath, options.output, function (err) {
if (err) {
_log("error", "Couldn't copy binary.");
throw err; // dump raw error object
}
_log('copied');
next();
});
}
], complete);
}
/**
* Download a version of node
*
* @param {string} version, version of node to download
* @param {string} directory, where to store the downloaded src
* @param {function} complete, callback
*/
function _downloadNode (version, directory, complete) {
var nodeFileDir = path.resolve(path.join(directory, framework, version)), // fixes #107, was process.cwd(), + rest.
nodeFilePath = path.resolve(path.join(nodeFileDir, framework + "-" + version + ".tar.gz"));
// might already be downloaded, and unzipped
if (_getNodeCompiler(nodeFileDir, complete)) {
return;
}
async.waterfall([
/**
* first make the directory where the zip file will live
*/
function makeDirectory (next) {
mkdirp.sync(path.dirname(nodeFilePath));
next();
},
/**
* download node into the target directory
*/
function downloadNode (next) {
if (fs.existsSync(nodeFilePath)) return next();
var type = global.type;
var url, prefix = "https://"+framework+".org/dist";
// pick which url depending on the version
if(framework==="nodejs") framework = "node"; // cmon node why can't you stay the same
if (version === "latest") {
url = prefix + "/" + framework + "-" + version + ".tar.gz";
} else {
url = prefix + "/v" + version + "/"+framework+"-v" + version + ".tar.gz";
}
_log("downloading %s", url);
var output = fs.createWriteStream(nodeFilePath, { "flags": "w+" });
// need to set user-agent to bypass some corporate firewalls
var requestOptions = {
url: url,
headers: {
"User-Agent": "Node.js"
}
}
_logProgress(request(requestOptions)).pipe(output);
output.on("close", function () { next(); });
},
/**
* unzip in the same directory
*/
function unzipNodeTarball (next) {
if(isWin) {
_log("Extracting the .tar.gz.");
new targz().extract(nodeFilePath, nodeFileDir, next);
} else {
var cmd = ["tar", "-xf", nodeFilePath, "-C", nodeFileDir];
_log(cmd.join(" "));
var tar = spawn(cmd.shift(), cmd);
tar.stdout.pipe(process.stdout);
tar.stderr.pipe(process.stderr);
tar.on("close", function () { next(); })
}
},
/**
* return the compiler object for the node version
*/
function (next, type) {
_getNodeCompiler(nodeFileDir, next, type)
},
], complete);
}
/**
* Get the compilier we will use for whatever platform we may be on and configure
* it.
*/
function _getNodeCompiler (nodeFileDir, complete, type) {
var dir = _getFirstDirectory(nodeFileDir);
// standard
var executable = "node.exe";
var binary = "node";
// iojs specifics.
if(framework === "iojs") {
executable = "iojs.exe";
binary = "iojs";
}
if (dir) {
if(isWin) {
complete(null, {
dir: dir,
version: path.basename(nodeFileDir),
releasePath: path.join(dir, "Release", executable),
make: function(next) {
// create a new env with minimal impact on old one
var newEnv = process.env
if(isPy!=="python") {
// add the dir of the suposed python exe to path
newEnv.path = process.env.PATH+";"+path.dirname(isPy)
}
// spawn a vcbuild process with our custom enviroment.
var vcbuild = spawn("vcbuild.bat", ["nosign", "release"], {
cwd: dir,
env: newEnv
});
vcbuild.stdout.pipe(process.stdout);
vcbuild.stderr.pipe(process.stderr);
vcbuild.on("close", function() {
next();
});
}
});
} else {
complete(null, {
dir: dir,
version: path.basename(nodeFileDir),
releasePath: path.join(dir, "out", "Release", binary),
make: function (next) {
var cfg = "./configure", configure;
if(isPy !== "python") {
configure = spawn(isPy, [cfg], { cwd: dir });
} else {
configure = spawn(cfg, [], { cwd: dir });
}
// local function, move to top eventually
function _loop(dir) {
/* eventually try every python file */
var pdir = fs.readdirSync(dir);
pdir.forEach(function(v, i) {
var stat = fs.statSync(dir+"/"+v);
if(stat.isFile()) {
// only process Makefiles and .mk targets.
if(v !== "Makefile" && path.extname(v) !== ".mk") {
return;
}
_log("patching "+v);
/* patch the file */
var py = fs.readFileSync(dir+"/"+v, {encoding: 'utf8'});
py = py.replace(/([a-z]|\/)*python(\w|)/gm, isPy); // this is definently needed
fs.writeFileSync(dir+"/"+v, py, {encoding: 'utf8'}); // write to file
delete pv;
} else if(stat.isDirectory()) {
// must be dir?
// skip tests because we don't need them here
if(v !== "test") {
_loop(dir+"/"+v)
}
}
});
}
configure.stdout.pipe(process.stdout);
configure.stderr.pipe(process.stderr);
configure.on("close", function () {
if(isPy !== "python") {
/**
* Originally I thought this only applied to io.js,
* however I soon found out this affects node.js,
* so it is now mainstream.
*/
_log("preparing python");
// loop over depends
_loop(dir);
}
var platformMake = "make";
if (os.platform().match(/bsd$/) != null) {
platformMake = "gmake";
}
var make = spawn(platformMake, [], { cwd: dir });
make.stdout.pipe(process.stdout);
make.stderr.pipe(process.stderr);
make.on("close", function () {
next();
});
})
}
});
}
return true;
}
return false;
}
/**
*/
function _monkeyPatchNodeConfig (compiler, complete) {
async.waterfall([
/**
* monkeypatch the gyp file to include the nexe.js and nexeres.js files
*/
function (next) {
_monkeyPatchGyp(compiler, next)
},
/**
* monkeypatch main entry point
*/
function (next) {
_monkeyPatchMainJs(compiler, next)
}
], complete);
}
/**
* patch the gyp file to allow our custom includes
*/
function _monkeyPatchGyp (compiler, complete) {
var gypPath = path.join(compiler.dir, "node.gyp");
_monkeypatch(
gypPath,
function (content) {
return ~content.indexOf("nexe.js");
},
function (content, next) {
next(null, content.replace("'lib/fs.js',", "'lib/fs.js', 'lib/nexe.js', 'lib/nexeres.js', "))
},
complete
)
}
/**
*/
function _monkeyPatchMainJs (compiler, complete) {
var mainPath = path.join(compiler.dir, "src", "node.js");
_monkeypatch(
mainPath,
function (content) {
return ~content.indexOf("nexe");
},
function (content, next) {
next(null, content.replace(/\(function\(process\) \{/,'(function(process) {\n process._eval = \'require("nexe");\';\n process.argv.splice(1, 0, "nexe.js");\n'))
},
complete
);
}
/**
*/
function _monkeyPatchChildProcess(compiler, complete) {
var childProcPath = path.join(compiler.dir, "lib", "child_process.js");
_monkeypatch(
childProcPath,
function (content) {
return ~content.indexOf("--child_process");
},
function (content, next) {
next(null, content.replace(/return spawn\(/, 'args.unshift("--child_process");\n return spawn('));
},
complete
);
}
/**
* Patch node.cc to not check the internal arguments.
*/
function _monkeyPatchMainCc(compiler, complete) {
var mainPath = path.join(compiler.dir, "src", "node.cc");
_monkeypatch(
mainPath,
function (content) {
return ~content.indexOf('// // TODO use parse opts');
},
function (content, next) {
var lines = content.split('\n');
var endLine = lines.indexOf(' option_end_index = i;'); // pre node 0.11.6 compat
if(endLine !== -1) { // check if it succedded or not.
lines[endLine] = ' option_end_index = 1;';
_log("patched node.cc")
}
/**
* This is the new method of passing the args. Tested on node.js 0.12.5
* and iojs 2.3.1
**/
if(endLine === -1) { // only if the pre-0.12.5 failed.
var startLine = lines.indexOf(' while (index < nargs && argv[index][0] == \'-\') {'); // beginning of the function
endLine = lines.indexOf(' // Copy remaining arguments.');
endLine = endLine-1; // space, then it's at the }
// remove the offending lines
if(startLine !== -1) {
for (var i = startLine; i < endLine; i++) {
lines[i] = undefined; // set the value to undefined so it's skipped by the join
}
_log('patched node.cc');
}
}
lines = lines.join('\n');
next(null, lines);
},
complete
);
}
/**
*/
function _getFirstDirectory (dir) {
var files = glob.sync(dir + "/*");
for (var i = files.length; i--;) {
var file = files[i];
if (fs.statSync(file).isDirectory()) return file;
}
return false;
}
/**
*/
function _logProgress (req) {
req.on("response", function (resp) {
var len = parseInt(resp.headers["content-length"], 10),
bar = new ProgressBar("[:bar]", {
complete: "=",
incomplete: " ",
total: len,
width: ((isWin) ? 100 : process.stdout.columns - 2) // windows doesn't output colums correctly
});
req.on("data", function (chunk) {
bar.tick(chunk.length);
});
});
return req;
}
/**
* Attempt to parse the package.json for nexe information.
*
* @param {string} path - path to package.json
* @param {object} options - fallback options
*
* @todo implement options overriding package defaults.
*
* @return {object} nexe.compile options object
**/
exports.package = function(path, options) {
var _package; // scope
// check if the file exists
if(fs.existsSync(path)===false) {
_log("warn", "no package.json found.");
} else {
_package = require(path);
}
// replace ^$ w/ os specific extension on output
if(isWin) {
_package.nexe.output = _package.nexe.output.replace(/\^\$/, '.exe') // exe
} else {
_package.nexe.output = _package.nexe.output.replace(/\^\$/, '') // none
}
// construct the object
var obj = {
input: (_package.nexe.input || options.i),
output: (_package.nexe.output || options.o),
flags: (_package.nexe.runtime.ignoreFlags || options.f),
resourceFiles: (_package.nexe.resourceFiles),
nodeVersion: (_package.nexe.runtime.version || options.r),
python: (_package.nexe.python || options.p),
nodeTempDir: (_package.nexe.temp || options.t),
framework: (_package.nexe.runtime.framework || options.f)
}
Object.keys(_package.nexe).forEach(function(v,i) {
if(v!=="runtime") {
_log("log", v+" => '"+_package.nexe[v]+"'");
}
});
Object.keys(_package.nexe.runtime).forEach(function(v,i) {
_log("log", "runtime."+v+" => '"+_package.nexe.runtime[v]+"'");
});
return obj;
}
+1 -3
View File
@@ -1,3 +1 @@
exports.compile = function(ops, callback) { module.exports = require("./exe");
}
+56
View File
@@ -0,0 +1,56 @@
/**
* Copyright (c) 2013 Craig Condon
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**/
/**
* standard output, takes 3 different types.
* log, error, and warn
*
* @param {any} arguments - Text to output.
* @return undefined
**/
function _log () {
var colors = require('colors');
var args = Array.prototype.slice.call(arguments, 0),
level = args.shift();
if (!~["log", "error", "warn"].indexOf(level)) {
args.unshift(level);
level = "log";
}
if(level == "log") {
args[0] = "----> " + args[0];
} else if(level == "error") {
args[0] = "....> " + colors.red("ERROR: ") + args[0]
} else if(level == "warn") {
args[0] = "....> " + colors.yellow("WARNING: ") + args[0]
}
console[level].apply(console, args);
}
// export the log function, for require()
module.exports = _log;
+63
View File
@@ -0,0 +1,63 @@
/**
* Copyright (c) 2013 Craig Condon
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**/
var async = require("async"),
fs = require("fs"),
_log = require("./log");
/**
* Monkey patch a file.
*
* @param {string} filePath - path to file.
* @param {function} monkeyPatched - function to process contents
* @param {function} processor - TODO: detail what this is
* @param {function} complete - callback
*
* @return undefined
*/
function _monkeypatch (filePath, monkeyPatched, processor, complete) {
async.waterfall([
function read (next) {
fs.readFile(filePath, "utf8", next);
},
// TODO - need to parse gyp file - this is a bit hacker
function monkeypatch (content, next) {
if (monkeyPatched(content)) return complete();
_log("monkey patch %s", filePath);
processor(content, next);
},
function write (content, next) {
fs.writeFile(filePath, content, "utf8", next);
}
], complete);
}
// export the function for require()
module.exports = _monkeypatch;
-2
View File
@@ -1,2 +0,0 @@
node_modules/
node_modules/*
-4
View File
@@ -1,4 +0,0 @@
lib-cov/*
*.swp
*.swo
node_modules
-21
View File
@@ -1,21 +0,0 @@
Copyright 2010 James Halliday (mail@substack.net)
This project is free software released under the MIT/X11 license:
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-474
View File
@@ -1,474 +0,0 @@
optimist
========
Optimist is a node.js library for option parsing for people who hate option
parsing. More specifically, this module is for people who like all the --bells
and -whistlz of program usage but think optstrings are a waste of time.
With optimist, option parsing doesn't have to suck (as much).
examples
========
With Optimist, the options are just a hash! No optstrings attached.
-------------------------------------------------------------------
xup.js:
````javascript
#!/usr/bin/env node
var argv = require('optimist').argv;
if (argv.rif - 5 * argv.xup > 7.138) {
console.log('Buy more riffiwobbles');
}
else {
console.log('Sell the xupptumblers');
}
````
***
$ ./xup.js --rif=55 --xup=9.52
Buy more riffiwobbles
$ ./xup.js --rif 12 --xup 8.1
Sell the xupptumblers
![This one's optimistic.](http://substack.net/images/optimistic.png)
But wait! There's more! You can do short options:
-------------------------------------------------
short.js:
````javascript
#!/usr/bin/env node
var argv = require('optimist').argv;
console.log('(%d,%d)', argv.x, argv.y);
````
***
$ ./short.js -x 10 -y 21
(10,21)
And booleans, both long and short (and grouped):
----------------------------------
bool.js:
````javascript
#!/usr/bin/env node
var util = require('util');
var argv = require('optimist').argv;
if (argv.s) {
util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: ');
}
console.log(
(argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '')
);
````
***
$ ./bool.js -s
The cat says: meow
$ ./bool.js -sp
The cat says: meow.
$ ./bool.js -sp --fr
Le chat dit: miaou.
And non-hypenated options too! Just use `argv._`!
-------------------------------------------------
nonopt.js:
````javascript
#!/usr/bin/env node
var argv = require('optimist').argv;
console.log('(%d,%d)', argv.x, argv.y);
console.log(argv._);
````
***
$ ./nonopt.js -x 6.82 -y 3.35 moo
(6.82,3.35)
[ 'moo' ]
$ ./nonopt.js foo -x 0.54 bar -y 1.12 baz
(0.54,1.12)
[ 'foo', 'bar', 'baz' ]
Plus, Optimist comes with .usage() and .demand()!
-------------------------------------------------
divide.js:
````javascript
#!/usr/bin/env node
var argv = require('optimist')
.usage('Usage: $0 -x [num] -y [num]')
.demand(['x','y'])
.argv;
console.log(argv.x / argv.y);
````
***
$ ./divide.js -x 55 -y 11
5
$ node ./divide.js -x 4.91 -z 2.51
Usage: node ./divide.js -x [num] -y [num]
Options:
-x [required]
-y [required]
Missing required arguments: y
EVEN MORE HOLY COW
------------------
default_singles.js:
````javascript
#!/usr/bin/env node
var argv = require('optimist')
.default('x', 10)
.default('y', 10)
.argv
;
console.log(argv.x + argv.y);
````
***
$ ./default_singles.js -x 5
15
default_hash.js:
````javascript
#!/usr/bin/env node
var argv = require('optimist')
.default({ x : 10, y : 10 })
.argv
;
console.log(argv.x + argv.y);
````
***
$ ./default_hash.js -y 7
17
And if you really want to get all descriptive about it...
---------------------------------------------------------
boolean_single.js
````javascript
#!/usr/bin/env node
var argv = require('optimist')
.boolean('v')
.argv
;
console.dir(argv);
````
***
$ ./boolean_single.js -v foo bar baz
true
[ 'bar', 'baz', 'foo' ]
boolean_double.js
````javascript
#!/usr/bin/env node
var argv = require('optimist')
.boolean(['x','y','z'])
.argv
;
console.dir([ argv.x, argv.y, argv.z ]);
console.dir(argv._);
````
***
$ ./boolean_double.js -x -z one two three
[ true, false, true ]
[ 'one', 'two', 'three' ]
Optimist is here to help...
---------------------------
You can describe parameters for help messages and set aliases. Optimist figures
out how to format a handy help string automatically.
line_count.js
````javascript
#!/usr/bin/env node
var argv = require('optimist')
.usage('Count the lines in a file.\nUsage: $0')
.demand('f')
.alias('f', 'file')
.describe('f', 'Load a file')
.argv
;
var fs = require('fs');
var s = fs.createReadStream(argv.file);
var lines = 0;
s.on('data', function (buf) {
lines += buf.toString().match(/\n/g).length;
});
s.on('end', function () {
console.log(lines);
});
````
***
$ node line_count.js
Count the lines in a file.
Usage: node ./line_count.js
Options:
-f, --file Load a file [required]
Missing required arguments: f
$ node line_count.js --file line_count.js
20
$ node line_count.js -f line_count.js
20
methods
=======
By itself,
````javascript
require('optimist').argv
`````
will use `process.argv` array to construct the `argv` object.
You can pass in the `process.argv` yourself:
````javascript
require('optimist')([ '-x', '1', '-y', '2' ]).argv
````
or use .parse() to do the same thing:
````javascript
require('optimist').parse([ '-x', '1', '-y', '2' ])
````
The rest of these methods below come in just before the terminating `.argv`.
.alias(key, alias)
------------------
Set key names as equivalent such that updates to a key will propagate to aliases
and vice-versa.
Optionally `.alias()` can take an object that maps keys to aliases.
.default(key, value)
--------------------
Set `argv[key]` to `value` if no option was specified on `process.argv`.
Optionally `.default()` can take an object that maps keys to default values.
.demand(key)
------------
If `key` is a string, show the usage information and exit if `key` wasn't
specified in `process.argv`.
If `key` is a number, demand at least as many non-option arguments, which show
up in `argv._`.
If `key` is an Array, demand each element.
.describe(key, desc)
--------------------
Describe a `key` for the generated usage information.
Optionally `.describe()` can take an object that maps keys to descriptions.
.options(key, opt)
------------------
Instead of chaining together `.alias().demand().default()`, you can specify
keys in `opt` for each of the chainable methods.
For example:
````javascript
var argv = require('optimist')
.options('f', {
alias : 'file',
default : '/etc/passwd',
})
.argv
;
````
is the same as
````javascript
var argv = require('optimist')
.alias('f', 'file')
.default('f', '/etc/passwd')
.argv
;
````
Optionally `.options()` can take an object that maps keys to `opt` parameters.
.usage(message)
---------------
Set a usage message to show which commands to use. Inside `message`, the string
`$0` will get interpolated to the current script name or node command for the
present script similar to how `$0` works in bash or perl.
.check(fn)
----------
Check that certain conditions are met in the provided arguments.
If `fn` throws or returns `false`, show the thrown error, usage information, and
exit.
.boolean(key)
-------------
Interpret `key` as a boolean. If a non-flag option follows `key` in
`process.argv`, that string won't get set as the value of `key`.
If `key` never shows up as a flag in `process.arguments`, `argv[key]` will be
`false`.
If `key` is an Array, interpret all the elements as booleans.
.string(key)
------------
Tell the parser logic not to interpret `key` as a number or boolean.
This can be useful if you need to preserve leading zeros in an input.
If `key` is an Array, interpret all the elements as strings.
.wrap(columns)
--------------
Format usage output to wrap at `columns` many columns.
.help()
-------
Return the generated usage string.
.showHelp(fn=console.error)
---------------------------
Print the usage data using `fn` for printing.
.parse(args)
------------
Parse `args` instead of `process.argv`. Returns the `argv` object.
.argv
-----
Get the arguments as a plain old object.
Arguments without a corresponding flag show up in the `argv._` array.
The script name or node command is available at `argv.$0` similarly to how `$0`
works in bash or perl.
parsing tricks
==============
stop parsing
------------
Use `--` to stop parsing flags and stuff the remainder into `argv._`.
$ node examples/reflect.js -a 1 -b 2 -- -c 3 -d 4
{ _: [ '-c', '3', '-d', '4' ],
'$0': 'node ./examples/reflect.js',
a: 1,
b: 2 }
negate fields
-------------
If you want to explicity set a field to false instead of just leaving it
undefined or to override a default you can do `--no-key`.
$ node examples/reflect.js -a --no-b
{ _: [],
'$0': 'node ./examples/reflect.js',
a: true,
b: false }
numbers
-------
Every argument that looks like a number (`!isNaN(Number(arg))`) is converted to
one. This way you can just `net.createConnection(argv.port)` and you can add
numbers out of `argv` with `+` without having that mean concatenation,
which is super frustrating.
duplicates
----------
If you specify a flag multiple times it will get turned into an array containing
all the values in order.
$ node examples/reflect.js -x 5 -x 8 -x 0
{ _: [],
'$0': 'node ./examples/reflect.js',
x: [ 5, 8, 0 ] }
installation
============
With [npm](http://github.com/isaacs/npm), just do:
npm install optimist
or clone this project on github:
git clone http://github.com/substack/node-optimist.git
To run the tests with [expresso](http://github.com/visionmedia/expresso),
just do:
expresso
inspired By
===========
This module is loosely inspired by Perl's
[Getopt::Casual](http://search.cpan.org/~photo/Getopt-Casual-0.13.1/Casual.pm).
-10
View File
@@ -1,10 +0,0 @@
#!/usr/bin/env node
var util = require('util');
var argv = require('optimist').argv;
if (argv.s) {
util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: ');
}
console.log(
(argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '')
);
-7
View File
@@ -1,7 +0,0 @@
#!/usr/bin/env node
var argv = require('optimist')
.boolean(['x','y','z'])
.argv
;
console.dir([ argv.x, argv.y, argv.z ]);
console.dir(argv._);
-7
View File
@@ -1,7 +0,0 @@
#!/usr/bin/env node
var argv = require('optimist')
.boolean('v')
.argv
;
console.dir(argv.v);
console.dir(argv._);
-8
View File
@@ -1,8 +0,0 @@
#!/usr/bin/env node
var argv = require('optimist')
.default({ x : 10, y : 10 })
.argv
;
console.log(argv.x + argv.y);
-7
View File
@@ -1,7 +0,0 @@
#!/usr/bin/env node
var argv = require('optimist')
.default('x', 10)
.default('y', 10)
.argv
;
console.log(argv.x + argv.y);
-8
View File
@@ -1,8 +0,0 @@
#!/usr/bin/env node
var argv = require('optimist')
.usage('Usage: $0 -x [num] -y [num]')
.demand(['x','y'])
.argv;
console.log(argv.x / argv.y);
-20
View File
@@ -1,20 +0,0 @@
#!/usr/bin/env node
var argv = require('optimist')
.usage('Count the lines in a file.\nUsage: $0')
.demand('f')
.alias('f', 'file')
.describe('f', 'Load a file')
.argv
;
var fs = require('fs');
var s = fs.createReadStream(argv.file);
var lines = 0;
s.on('data', function (buf) {
lines += buf.toString().match(/\n/g).length;
});
s.on('end', function () {
console.log(lines);
});
-29
View File
@@ -1,29 +0,0 @@
#!/usr/bin/env node
var argv = require('optimist')
.usage('Count the lines in a file.\nUsage: $0')
.options({
file : {
demand : true,
alias : 'f',
description : 'Load a file'
},
base : {
alias : 'b',
description : 'Numeric base to use for output',
default : 10,
},
})
.argv
;
var fs = require('fs');
var s = fs.createReadStream(argv.file);
var lines = 0;
s.on('data', function (buf) {
lines += buf.toString().match(/\n/g).length;
});
s.on('end', function () {
console.log(lines.toString(argv.base));
});
-29
View File
@@ -1,29 +0,0 @@
#!/usr/bin/env node
var argv = require('optimist')
.usage('Count the lines in a file.\nUsage: $0')
.wrap(80)
.demand('f')
.alias('f', [ 'file', 'filename' ])
.describe('f',
"Load a file. It's pretty important."
+ " Required even. So you'd better specify it."
)
.alias('b', 'base')
.describe('b', 'Numeric base to display the number of lines in')
.default('b', 10)
.describe('x', 'Super-secret optional parameter which is secret')
.default('x', '')
.argv
;
var fs = require('fs');
var s = fs.createReadStream(argv.file);
var lines = 0;
s.on('data', function (buf) {
lines += buf.toString().match(/\n/g).length;
});
s.on('end', function () {
console.log(lines.toString(argv.base));
});
-4
View File
@@ -1,4 +0,0 @@
#!/usr/bin/env node
var argv = require('optimist').argv;
console.log('(%d,%d)', argv.x, argv.y);
console.log(argv._);
-2
View File
@@ -1,2 +0,0 @@
#!/usr/bin/env node
console.dir(require('optimist').argv);
-3
View File
@@ -1,3 +0,0 @@
#!/usr/bin/env node
var argv = require('optimist').argv;
console.log('(%d,%d)', argv.x, argv.y);
-11
View File
@@ -1,11 +0,0 @@
#!/usr/bin/env node
var argv = require('optimist')
.string('x', 'y')
.argv
;
console.dir([ argv.x, argv.y ]);
/* Turns off numeric coercion:
./node string.js -x 000123 -y 9876
[ '000123', '9876' ]
*/
-19
View File
@@ -1,19 +0,0 @@
var optimist = require('./../index');
var argv = optimist.usage('This is my awesome program', {
'about': {
description: 'Provide some details about the author of this program',
required: true,
short: 'a',
},
'info': {
description: 'Provide some information about the node.js agains!!!!!!',
boolean: true,
short: 'i'
}
}).argv;
optimist.showHelp();
console.log('\n\nInspecting options');
console.dir(argv);
-10
View File
@@ -1,10 +0,0 @@
#!/usr/bin/env node
var argv = require('optimist').argv;
if (argv.rif - 5 * argv.xup > 7.138) {
console.log('Buy more riffiwobbles');
}
else {
console.log('Sell the xupptumblers');
}
-457
View File
@@ -1,457 +0,0 @@
var path = require('path');
var wordwrap = require('wordwrap');
/* Hack an instance of Argv with process.argv into Argv
so people can do
require('optimist')(['--beeble=1','-z','zizzle']).argv
to parse a list of args and
require('optimist').argv
to get a parsed version of process.argv.
*/
var inst = Argv(process.argv.slice(2));
Object.keys(inst).forEach(function (key) {
Argv[key] = typeof inst[key] == 'function'
? inst[key].bind(inst)
: inst[key];
});
var exports = module.exports = Argv;
function Argv (args, cwd) {
var self = {};
if (!cwd) cwd = process.cwd();
self.$0 = process.argv
.slice(0,2)
.map(function (x) {
var b = rebase(cwd, x);
return x.match(/^\//) && b.length < x.length
? b : x
})
.join(' ')
;
if (process.argv[1] == process.env._) {
self.$0 = process.env._.replace(
path.dirname(process.execPath) + '/', ''
);
}
var flags = { bools : {}, strings : {} };
self.boolean = function (bools) {
if (!Array.isArray(bools)) {
bools = [].slice.call(arguments);
}
bools.forEach(function (name) {
flags.bools[name] = true;
});
return self;
};
self.string = function (strings) {
if (!Array.isArray(strings)) {
strings = [].slice.call(arguments);
}
strings.forEach(function (name) {
flags.strings[name] = true;
});
return self;
};
var aliases = {};
self.alias = function (x, y) {
if (typeof x === 'object') {
Object.keys(x).forEach(function (key) {
self.alias(key, x[key]);
});
}
else if (Array.isArray(y)) {
y.forEach(function (yy) {
self.alias(x, yy);
});
}
else {
var zs = (aliases[x] || []).concat(aliases[y] || []).concat(x, y);
aliases[x] = zs.filter(function (z) { return z != x });
aliases[y] = zs.filter(function (z) { return z != y });
}
return self;
};
var demanded = {};
self.demand = function (keys) {
if (typeof keys == 'number') {
if (!demanded._) demanded._ = 0;
demanded._ += keys;
}
else if (Array.isArray(keys)) {
keys.forEach(function (key) {
self.demand(key);
});
}
else {
demanded[keys] = true;
}
return self;
};
var usage;
self.usage = function (msg, opts) {
if (!opts && typeof msg === 'object') {
opts = msg;
msg = null;
}
usage = msg;
if (opts) self.options(opts);
return self;
};
function fail (msg) {
self.showHelp();
if (msg) console.error(msg);
process.exit(1);
}
var checks = [];
self.check = function (f) {
checks.push(f);
return self;
};
var defaults = {};
self.default = function (key, value) {
if (typeof key === 'object') {
Object.keys(key).forEach(function (k) {
self.default(k, key[k]);
});
}
else {
defaults[key] = value;
}
return self;
};
var descriptions = {};
self.describe = function (key, desc) {
if (typeof key === 'object') {
Object.keys(key).forEach(function (k) {
self.describe(k, key[k]);
});
}
else {
descriptions[key] = desc;
}
return self;
};
self.parse = function (args) {
return Argv(args).argv;
};
self.option = self.options = function (key, opt) {
if (typeof key === 'object') {
Object.keys(key).forEach(function (k) {
self.options(k, key[k]);
});
}
else {
if (opt.alias) self.alias(key, opt.alias);
if (opt.demand) self.demand(key);
if (opt.default) self.default(key, opt.default);
if (opt.boolean || opt.type === 'boolean') {
self.boolean(key);
}
if (opt.string || opt.type === 'string') {
self.string(key);
}
var desc = opt.describe || opt.description || opt.desc;
if (desc) {
self.describe(key, desc);
}
}
return self;
};
var wrap = null;
self.wrap = function (cols) {
wrap = cols;
return self;
};
self.showHelp = function (fn) {
if (!fn) fn = console.error;
fn(self.help());
};
self.help = function () {
var keys = Object.keys(
Object.keys(descriptions)
.concat(Object.keys(demanded))
.concat(Object.keys(defaults))
.reduce(function (acc, key) {
if (key !== '_') acc[key] = true;
return acc;
}, {})
);
var help = keys.length ? [ 'Options:' ] : [];
if (usage) {
help.unshift(usage.replace(/\$0/g, self.$0), '');
}
var switches = keys.reduce(function (acc, key) {
acc[key] = [ key ].concat(aliases[key] || [])
.map(function (sw) {
return (sw.length > 1 ? '--' : '-') + sw
})
.join(', ')
;
return acc;
}, {});
var switchlen = longest(Object.keys(switches).map(function (s) {
return switches[s] || '';
}));
var desclen = longest(Object.keys(descriptions).map(function (d) {
return descriptions[d] || '';
}));
keys.forEach(function (key) {
var kswitch = switches[key];
var desc = descriptions[key] || '';
if (wrap) {
desc = wordwrap(switchlen + 4, wrap)(desc)
.slice(switchlen + 4)
;
}
var spadding = new Array(
Math.max(switchlen - kswitch.length + 3, 0)
).join(' ');
var dpadding = new Array(
Math.max(desclen - desc.length + 1, 0)
).join(' ');
var type = null;
if (flags.bools[key]) type = '[boolean]';
if (flags.strings[key]) type = '[string]';
if (!wrap && dpadding.length > 0) {
desc += dpadding;
}
var prelude = ' ' + kswitch + spadding;
var extra = [
type,
demanded[key]
? '[required]'
: null
,
defaults[key] !== undefined
? '[default: ' + JSON.stringify(defaults[key]) + ']'
: null
,
].filter(Boolean).join(' ');
var body = [ desc, extra ].filter(Boolean).join(' ');
if (wrap) {
var dlines = desc.split('\n');
var dlen = dlines.slice(-1)[0].length
+ (dlines.length === 1 ? prelude.length : 0)
body = desc + (dlen + extra.length > wrap - 2
? '\n'
+ new Array(wrap - extra.length + 1).join(' ')
+ extra
: new Array(wrap - extra.length - dlen + 1).join(' ')
+ extra
);
}
help.push(prelude + body);
});
help.push('');
return help.join('\n');
};
Object.defineProperty(self, 'argv', {
get : parseArgs,
enumerable : true,
});
function parseArgs () {
var argv = { _ : [], $0 : self.$0 };
Object.keys(flags.bools).forEach(function (key) {
setArg(key, defaults[key] || false);
});
function setArg (key, val) {
var num = Number(val);
var value = typeof val !== 'string' || isNaN(num) ? val : num;
if (flags.strings[key]) value = val;
if (key in argv && !flags.bools[key]) {
if (!Array.isArray(argv[key])) {
argv[key] = [ argv[key] ];
}
argv[key].push(value);
}
else {
argv[key] = value;
}
(aliases[key] || []).forEach(function (x) {
argv[x] = argv[key];
});
}
for (var i = 0; i < args.length; i++) {
var arg = args[i];
if (arg === '--') {
argv._.push.apply(argv._, args.slice(i + 1));
break;
}
else if (arg.match(/^--.+=/)) {
var m = arg.match(/^--([^=]+)=(.*)/);
setArg(m[1], m[2]);
}
else if (arg.match(/^--no-.+/)) {
var key = arg.match(/^--no-(.+)/)[1];
setArg(key, false);
}
else if (arg.match(/^--.+/)) {
var key = arg.match(/^--(.+)/)[1];
var next = args[i + 1];
if (next !== undefined && !next.match(/^-/)
&& !flags.bools[key]) {
setArg(key, next);
i++;
}
else if (flags.bools[key] && /true|false/.test(next)) {
setArg(key, next === 'true');
i++;
}
else {
setArg(key, true);
}
}
else if (arg.match(/^-[^-]+/)) {
var letters = arg.slice(1,-1).split('');
var broken = false;
for (var j = 0; j < letters.length; j++) {
if (letters[j+1] && letters[j+1].match(/\W/)) {
setArg(letters[j], arg.slice(j+2));
broken = true;
break;
}
else {
setArg(letters[j], true);
}
}
if (!broken) {
var key = arg.slice(-1)[0];
if (args[i+1] && !args[i+1].match(/^-/)
&& !flags.bools[key]) {
setArg(key, args[i+1]);
i++;
}
else if (args[i+1] && flags.bools[key] && /true|false/.test(args[i+1])) {
setArg(key, args[i+1] === 'true');
i++;
}
else {
setArg(key, true);
}
}
}
else {
var n = Number(arg);
argv._.push(flags.strings['_'] || isNaN(n) ? arg : n);
}
}
Object.keys(defaults).forEach(function (key) {
if (!(key in argv)) {
argv[key] = defaults[key];
}
});
if (demanded._ && argv._.length < demanded._) {
fail('Not enough non-option arguments: got '
+ argv._.length + ', need at least ' + demanded._
);
}
var missing = [];
Object.keys(demanded).forEach(function (key) {
if (!argv[key]) missing.push(key);
});
if (missing.length) {
fail('Missing required arguments: ' + missing.join(', '));
}
checks.forEach(function (f) {
try {
if (f(argv) === false) {
fail('Argument check failed: ' + f.toString());
}
}
catch (err) {
fail(err)
}
});
return argv;
}
function longest (xs) {
return Math.max.apply(
null,
xs.map(function (x) { return x.length })
);
}
return self;
};
// rebase an absolute path to a relative one with respect to a base directory
// exported for tests
exports.rebase = rebase;
function rebase (base, dir) {
var ds = path.normalize(dir).split('/').slice(1);
var bs = path.normalize(base).split('/').slice(1);
for (var i = 0; ds[i] && ds[i] == bs[i]; i++);
ds.splice(0, i); bs.splice(0, i);
var p = path.normalize(
bs.map(function () { return '..' }).concat(ds).join('/')
).replace(/\/$/,'').replace(/^$/, '.');
return p.match(/^[.\/]/) ? p : './' + p;
};
-43
View File
@@ -1,43 +0,0 @@
{
"name" : "optimist",
"version" : "0.2.8",
"description" : "Light-weight option parsing with an argv hash. No optstrings attached.",
"main" : "./index.js",
"directories" : {
"lib" : ".",
"test" : "test",
"example" : "examples"
},
"dependencies" : {
"wordwrap" : ">=0.0.1 <0.1.0"
},
"devDependencies" : {
"hashish": "0.0.x",
"expresso" : "0.7.x"
},
"scripts" : {
"test" : "expresso"
},
"repository" : {
"type" : "git",
"url" : "http://github.com/substack/node-optimist.git"
},
"keywords" : [
"argument",
"args",
"option",
"parser",
"parsing",
"cli",
"command"
],
"author" : {
"name" : "James Halliday",
"email" : "mail@substack.net",
"url" : "http://substack.net"
},
"license" : "MIT/X11",
"engine" : {
"node" : ">=0.4"
}
}
-66
View File
@@ -1,66 +0,0 @@
var spawn = require('child_process').spawn;
var assert = require('assert');
exports.dotSlashEmpty = function () {
testCmd('./bin.js', []);
};
exports.dotSlashArgs = function () {
testCmd('./bin.js', [ 'a', 'b', 'c' ]);
};
exports.nodeEmpty = function () {
testCmd('node bin.js', []);
};
exports.nodeArgs = function () {
testCmd('node bin.js', [ 'x', 'y', 'z' ]);
};
exports.whichNodeEmpty = function () {
var which = spawn('which', ['node']);
which.stdout.on('data', function (buf) {
testCmd(buf.toString().trim() + ' bin.js', []);
});
which.stderr.on('data', function (err) {
assert.fail(err.toString());
});
};
exports.whichNodeArgs = function () {
var which = spawn('which', ['node']);
which.stdout.on('data', function (buf) {
testCmd(buf.toString().trim() + ' bin.js', [ 'q', 'r' ]);
});
which.stderr.on('data', function (err) {
assert.fail(err.toString());
});
};
function testCmd (cmd, args) {
var to = setTimeout(function () {
assert.fail('Never got stdout data.')
}, 5000);
var oldDir = process.cwd();
process.chdir(__dirname + '/_');
var cmds = cmd.split(' ');
var bin = spawn(cmds[0], cmds.slice(1).concat(args.map(String)));
process.chdir(oldDir);
bin.stderr.on('data', function (err) {
assert.fail(err.toString());
});
bin.stdout.on('data', function (buf) {
clearTimeout(to);
var _ = JSON.parse(buf.toString());
assert.eql(_.map(String), args.map(String));
});
}
-2
View File
@@ -1,2 +0,0 @@
#!/usr/bin/env node
console.log(JSON.stringify(process.argv));
-3
View File
@@ -1,3 +0,0 @@
#!/usr/bin/env node
var argv = require('../../index').argv
console.log(JSON.stringify(argv._));
-304
View File
@@ -1,304 +0,0 @@
var optimist = require('../index');
var assert = require('assert');
var path = require('path');
var localExpresso = path.normalize(
__dirname + '/../node_modules/.bin/expresso'
);
var expresso = process.argv[1] === localExpresso
? 'node ./node_modules/.bin/expresso'
: 'expresso'
;
exports['short boolean'] = function () {
var parse = optimist.parse([ '-b' ]);
assert.eql(parse, { b : true, _ : [], $0 : expresso });
assert.eql(typeof parse.b, 'boolean');
};
exports['long boolean'] = function () {
assert.eql(
optimist.parse([ '--bool' ]),
{ bool : true, _ : [], $0 : expresso }
);
};
exports.bare = function () {
assert.eql(
optimist.parse([ 'foo', 'bar', 'baz' ]),
{ _ : [ 'foo', 'bar', 'baz' ], $0 : expresso }
);
};
exports['short group'] = function () {
assert.eql(
optimist.parse([ '-cats' ]),
{ c : true, a : true, t : true, s : true, _ : [], $0 : expresso }
);
};
exports['short group next'] = function () {
assert.eql(
optimist.parse([ '-cats', 'meow' ]),
{ c : true, a : true, t : true, s : 'meow', _ : [], $0 : expresso }
);
};
exports['short capture'] = function () {
assert.eql(
optimist.parse([ '-h', 'localhost' ]),
{ h : 'localhost', _ : [], $0 : expresso }
);
};
exports['short captures'] = function () {
assert.eql(
optimist.parse([ '-h', 'localhost', '-p', '555' ]),
{ h : 'localhost', p : 555, _ : [], $0 : expresso }
);
};
exports['long capture sp'] = function () {
assert.eql(
optimist.parse([ '--pow', 'xixxle' ]),
{ pow : 'xixxle', _ : [], $0 : expresso }
);
};
exports['long capture eq'] = function () {
assert.eql(
optimist.parse([ '--pow=xixxle' ]),
{ pow : 'xixxle', _ : [], $0 : expresso }
);
};
exports['long captures sp'] = function () {
assert.eql(
optimist.parse([ '--host', 'localhost', '--port', '555' ]),
{ host : 'localhost', port : 555, _ : [], $0 : expresso }
);
};
exports['long captures eq'] = function () {
assert.eql(
optimist.parse([ '--host=localhost', '--port=555' ]),
{ host : 'localhost', port : 555, _ : [], $0 : expresso }
);
};
exports['mixed short bool and capture'] = function () {
assert.eql(
optimist.parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]),
{
f : true, p : 555, h : 'localhost',
_ : [ 'script.js' ], $0 : expresso,
}
);
};
exports['short and long'] = function () {
assert.eql(
optimist.parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]),
{
f : true, p : 555, h : 'localhost',
_ : [ 'script.js' ], $0 : expresso,
}
);
};
exports.no = function () {
assert.eql(
optimist.parse([ '--no-moo' ]),
{ moo : false, _ : [], $0 : expresso }
);
};
exports.multi = function () {
assert.eql(
optimist.parse([ '-v', 'a', '-v', 'b', '-v', 'c' ]),
{ v : ['a','b','c'], _ : [], $0 : expresso }
);
};
exports.comprehensive = function () {
assert.eql(
optimist.parse([
'--name=meowmers', 'bare', '-cats', 'woo',
'-h', 'awesome', '--multi=quux',
'--key', 'value',
'-b', '--bool', '--no-meep', '--multi=baz',
'--', '--not-a-flag', 'eek'
]),
{
c : true,
a : true,
t : true,
s : 'woo',
h : 'awesome',
b : true,
bool : true,
key : 'value',
multi : [ 'quux', 'baz' ],
meep : false,
name : 'meowmers',
_ : [ 'bare', '--not-a-flag', 'eek' ],
$0 : expresso
}
);
};
exports.nums = function () {
var argv = optimist.parse([
'-x', '1234',
'-y', '5.67',
'-z', '1e7',
'-w', '10f',
'--hex', '0xdeadbeef',
'789',
]);
assert.eql(argv, {
x : 1234,
y : 5.67,
z : 1e7,
w : '10f',
hex : 0xdeadbeef,
_ : [ 789 ],
$0 : expresso
});
assert.eql(typeof argv.x, 'number');
assert.eql(typeof argv.y, 'number');
assert.eql(typeof argv.z, 'number');
assert.eql(typeof argv.w, 'string');
assert.eql(typeof argv.hex, 'number');
assert.eql(typeof argv._[0], 'number');
};
exports['flag boolean'] = function () {
var parse = optimist([ '-t', 'moo' ]).boolean(['t']).argv;
assert.eql(parse, { t : true, _ : [ 'moo' ], $0 : expresso });
assert.eql(typeof parse.t, 'boolean');
};
exports['flag boolean value'] = function () {
var parse = optimist(['--verbose', 'false', 'moo', '-t', 'true'])
.boolean(['t', 'verbose']).default('verbose', true).argv;
assert.eql(parse, {
verbose: false,
t: true,
_: ['moo'],
$0 : expresso
});
assert.eql(typeof parse.verbose, 'boolean');
assert.eql(typeof parse.t, 'boolean');
};
exports['flag boolean default false'] = function () {
var parse = optimist(['moo'])
.boolean(['t', 'verbose'])
.default('verbose', false)
.default('t', false).argv;
assert.eql(parse, {
verbose: false,
t: false,
_: ['moo'],
$0 : expresso
});
assert.eql(typeof parse.verbose, 'boolean');
assert.eql(typeof parse.t, 'boolean');
};
exports['boolean groups'] = function () {
var parse = optimist([ '-x', '-z', 'one', 'two', 'three' ])
.boolean(['x','y','z']).argv;
assert.eql(parse, {
x : true,
y : false,
z : true,
_ : [ 'one', 'two', 'three' ],
$0 : expresso
});
assert.eql(typeof parse.x, 'boolean');
assert.eql(typeof parse.y, 'boolean');
assert.eql(typeof parse.z, 'boolean');
};
exports.strings = function () {
var s = optimist([ '-s', '0001234' ]).string('s').argv.s;
assert.eql(s, '0001234');
assert.eql(typeof s, 'string');
var x = optimist([ '-x', '56' ]).string('x').argv.x;
assert.eql(x, '56');
assert.eql(typeof x, 'string');
};
exports.stringArgs = function () {
var s = optimist([ ' ', ' ' ]).string('_').argv._;
assert.eql(s.length, 2);
assert.eql(typeof s[0], 'string');
assert.eql(s[0], ' ');
assert.eql(typeof s[1], 'string');
assert.eql(s[1], ' ');
};
exports.slashBreak = function () {
assert.eql(
optimist.parse([ '-I/foo/bar/baz' ]),
{ I : '/foo/bar/baz', _ : [], $0 : expresso }
);
assert.eql(
optimist.parse([ '-xyz/foo/bar/baz' ]),
{ x : true, y : true, z : '/foo/bar/baz', _ : [], $0 : expresso }
);
};
exports.alias = function () {
var argv = optimist([ '-f', '11', '--zoom', '55' ])
.alias('z', 'zoom')
.argv
;
assert.equal(argv.zoom, 55);
assert.equal(argv.z, argv.zoom);
assert.equal(argv.f, 11);
};
exports.multiAlias = function () {
var argv = optimist([ '-f', '11', '--zoom', '55' ])
.alias('z', [ 'zm', 'zoom' ])
.argv
;
assert.equal(argv.zoom, 55);
assert.equal(argv.z, argv.zoom);
assert.equal(argv.z, argv.zm);
assert.equal(argv.f, 11);
};
exports['boolean default true'] = function () {
var argv = optimist.options({
sometrue: {
boolean: true,
default: true
}
}).argv;
assert.equal(argv.sometrue, true);
};
exports['boolean default false'] = function () {
var argv = optimist.options({
somefalse: {
boolean: true,
default: false
}
}).argv;
assert.equal(argv.somefalse, false);
};
-256
View File
@@ -1,256 +0,0 @@
var Hash = require('hashish');
var optimist = require('../index');
var assert = require('assert');
exports.usageFail = function () {
var r = checkUsage(function () {
return optimist('-x 10 -z 20'.split(' '))
.usage('Usage: $0 -x NUM -y NUM')
.demand(['x','y'])
.argv;
});
assert.deepEqual(
r.result,
{ x : 10, z : 20, _ : [], $0 : './usage' }
);
assert.deepEqual(
r.errors.join('\n').split(/\n+/),
[
'Usage: ./usage -x NUM -y NUM',
'Options:',
' -x [required]',
' -y [required]',
'Missing required arguments: y',
]
);
assert.deepEqual(r.logs, []);
assert.ok(r.exit);
};
exports.usagePass = function () {
var r = checkUsage(function () {
return optimist('-x 10 -y 20'.split(' '))
.usage('Usage: $0 -x NUM -y NUM')
.demand(['x','y'])
.argv;
});
assert.deepEqual(r, {
result : { x : 10, y : 20, _ : [], $0 : './usage' },
errors : [],
logs : [],
exit : false,
});
};
exports.checkPass = function () {
var r = checkUsage(function () {
return optimist('-x 10 -y 20'.split(' '))
.usage('Usage: $0 -x NUM -y NUM')
.check(function (argv) {
if (!('x' in argv)) throw 'You forgot about -x';
if (!('y' in argv)) throw 'You forgot about -y';
})
.argv;
});
assert.deepEqual(r, {
result : { x : 10, y : 20, _ : [], $0 : './usage' },
errors : [],
logs : [],
exit : false,
});
};
exports.checkFail = function () {
var r = checkUsage(function () {
return optimist('-x 10 -z 20'.split(' '))
.usage('Usage: $0 -x NUM -y NUM')
.check(function (argv) {
if (!('x' in argv)) throw 'You forgot about -x';
if (!('y' in argv)) throw 'You forgot about -y';
})
.argv;
});
assert.deepEqual(
r.result,
{ x : 10, z : 20, _ : [], $0 : './usage' }
);
assert.deepEqual(
r.errors.join('\n').split(/\n+/),
[
'Usage: ./usage -x NUM -y NUM',
'You forgot about -y'
]
);
assert.deepEqual(r.logs, []);
assert.ok(r.exit);
};
exports.checkCondPass = function () {
function checker (argv) {
return 'x' in argv && 'y' in argv;
}
var r = checkUsage(function () {
return optimist('-x 10 -y 20'.split(' '))
.usage('Usage: $0 -x NUM -y NUM')
.check(checker)
.argv;
});
assert.deepEqual(r, {
result : { x : 10, y : 20, _ : [], $0 : './usage' },
errors : [],
logs : [],
exit : false,
});
};
exports.checkCondFail = function () {
function checker (argv) {
return 'x' in argv && 'y' in argv;
}
var r = checkUsage(function () {
return optimist('-x 10 -z 20'.split(' '))
.usage('Usage: $0 -x NUM -y NUM')
.check(checker)
.argv;
});
assert.deepEqual(
r.result,
{ x : 10, z : 20, _ : [], $0 : './usage' }
);
assert.deepEqual(
r.errors.join('\n').split(/\n+/).join('\n'),
'Usage: ./usage -x NUM -y NUM\n'
+ 'Argument check failed: ' + checker.toString()
);
assert.deepEqual(r.logs, []);
assert.ok(r.exit);
};
exports.countPass = function () {
var r = checkUsage(function () {
return optimist('1 2 3 --moo'.split(' '))
.usage('Usage: $0 [x] [y] [z] {OPTIONS}')
.demand(3)
.argv;
});
assert.deepEqual(r, {
result : { _ : [ '1', '2', '3' ], moo : true, $0 : './usage' },
errors : [],
logs : [],
exit : false,
});
};
exports.countFail = function () {
var r = checkUsage(function () {
return optimist('1 2 --moo'.split(' '))
.usage('Usage: $0 [x] [y] [z] {OPTIONS}')
.demand(3)
.argv;
});
assert.deepEqual(
r.result,
{ _ : [ '1', '2' ], moo : true, $0 : './usage' }
);
assert.deepEqual(
r.errors.join('\n').split(/\n+/),
[
'Usage: ./usage [x] [y] [z] {OPTIONS}',
'Not enough non-option arguments: got 2, need at least 3',
]
);
assert.deepEqual(r.logs, []);
assert.ok(r.exit);
};
exports.defaultSingles = function () {
var r = checkUsage(function () {
return optimist('--foo 50 --baz 70 --powsy'.split(' '))
.default('foo', 5)
.default('bar', 6)
.default('baz', 7)
.argv
;
});
assert.eql(r.result, {
foo : '50',
bar : 6,
baz : '70',
powsy : true,
_ : [],
$0 : './usage',
});
};
exports.defaultHash = function () {
var r = checkUsage(function () {
return optimist('--foo 50 --baz 70'.split(' '))
.default({ foo : 10, bar : 20, quux : 30 })
.argv
;
});
assert.eql(r.result, {
foo : '50',
bar : 20,
baz : 70,
quux : 30,
_ : [],
$0 : './usage',
});
};
exports.rebase = function () {
assert.equal(
optimist.rebase('/home/substack', '/home/substack/foo/bar/baz'),
'./foo/bar/baz'
);
assert.equal(
optimist.rebase('/home/substack/foo/bar/baz', '/home/substack'),
'../../..'
);
assert.equal(
optimist.rebase('/home/substack/foo', '/home/substack/pow/zoom.txt'),
'../pow/zoom.txt'
);
};
function checkUsage (f) {
var _process = process;
process = Hash.copy(process);
var exit = false;
process.exit = function () { exit = true };
process.env = Hash.merge(process.env, { _ : 'node' });
process.argv = [ './usage' ];
var errors = [];
var logs = [];
console._error = console.error;
console.error = function (msg) { errors.push(msg) };
console._log = console.log;
console.log = function (msg) { logs.push(msg) };
var result = f();
process = _process;
console.error = console._error;
console.log = console._log;
return {
errors : errors,
logs : logs,
exit : exit,
result : result,
};
};
+41 -7
View File
@@ -1,16 +1,50 @@
{ {
"author": "Craig Condon <craig.j.condon@gmail.com>", "author": "Jared Allard <jaredallard@outlook.com>",
"name": "nexe", "name": "nexe",
"description": "Roll node.s applications into a single executable", "description": "create single executables out of your [node/io].js applications",
"version": "0.0.1", "license": "MIT",
"version": "0.4.1",
"contributors": [
{
"name": "Criag Condon",
"email": "craig.j.condon@gmail.com",
"url": "http://crcn.io/"
}
],
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git://github.com/crcn/nexe.git" "url": "git://github.com/jaredallard/nexe.git"
}, },
"main": "./lib/index.js", "main": "./lib/index.js",
"dependencies": { "dependencies": {
"optimist":"*", "async": "1.2.1",
"sardines":"*" "builtins": "1.0.1",
"colors": "^1.0.3",
"glob": "^5.0.5",
"mkdirp": "^0.5.0",
"module-deps": "^3.6.4",
"ncp": "^2.0.0",
"outcome": "0.0.18",
"progress": "^1.1.8",
"request": "^2.53.0",
"sprintf": "~0.1.5",
"step": "0.0.x",
"tar.gz": "0.1.1",
"through": "^2.3.6",
"yargs": "^3.2.1"
}, },
"devDependencies": {} "nexe": {
"input": "./bin/nexe",
"output": "nexe^$",
"temp": "src",
"runtime": {
"framework": "iojs",
"version": "2.3.1",
"ignoreFlags": true
}
},
"preferGlobal": "true",
"bin": {
"nexe": "./bin/nexe"
}
} }
-23
View File
@@ -1,23 +0,0 @@
{
"folders":
[
{
"path": "."
}
],
"build_systems":
[
{
"name":"cbd make",
"cmd":["cbd","make","nexe"]
},
{
"name":"cbd start",
"cmd":["cbd","start","nexe"]
},
{
"name":"cbd make+start",
"cmd":["cbd","make+start","nexe"]
}
]
}