| #!/usr/bin/env node | ||
| require("./cmd.js") |
| {compile} = require('./jspackage') | ||
| fs = require('fs') | ||
| optparse = require('optparse') | ||
| switches = [ | ||
| ['-h', '--help', "shows this help section"] | ||
| ['-b', '--bare', "compile without a top-level function wrapper"] | ||
| ['-w', '--watch', "watch source files and recompile when any change"] | ||
| ['-l', '--lib PATH', "add an additional search directory for source files"] | ||
| ] | ||
| parser = new optparse.OptionParser(switches) | ||
| printUsage = -> | ||
| parser.banner = "Usage: jspackage input_file output_file [options]" | ||
| console.log(parser.toString()) | ||
| parser.on 'help', -> | ||
| printUsage() | ||
| process.exit(1) | ||
| options = {} | ||
| parser.on 0, (arg) -> | ||
| options.mainfile = arg | ||
| output = null | ||
| parser.on 1, (arg) -> | ||
| output = arg | ||
| parser.on "bare", -> | ||
| options.bare = true | ||
| parser.on "watch", -> | ||
| options.watch = true | ||
| parser.on "lib", (name, value) -> | ||
| (options.libs ?= []).push value | ||
| parser.parse(process.argv.splice(2)) | ||
| if not options.mainfile or not output | ||
| printUsage() | ||
| process.exit(1) | ||
| compile options, (err, code) -> | ||
| if options.watch | ||
| timestamp = (new Date()).toLocaleTimeString() | ||
| if err | ||
| console.error("#{timestamp} - error: #{err}") | ||
| else | ||
| console.info("#{timestamp} - generated #{output}") | ||
| fs.writeFile(output, code) | ||
| else | ||
| if (err) then throw err | ||
| fs.writeFile(output, code) |
| ./path3/derp/hurr | ||
| ./path3/joy | ||
| ./path2/electric | ||
| ./path1/robin | ||
| ./thing | ||
| main |
Sorry, the diff of this file is not supported yet
| console.log("./path1/thing"); |
| //import "joy" | ||
| console.log("./path2/electric"); |
| console.log "./path2/robin" |
| console.log("./path2/thing"); |
| console.log("./path3/derp/hurr"); |
| console.log("./path3/electric"); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
| console.log("./path3/thing"); |
| -b | ||
| --lib tests/libfun/path1 | ||
| --lib tests/libfun/path2 | ||
| --lib tests/libfun/path3 |
| #import "thing" | ||
| console.log "main" |
| //import "robin" | ||
| console.log("./thing"); |
+47
-40
@@ -1,65 +0,72 @@ | ||
| #!/usr/local/bin/node | ||
| // Generated by CoffeeScript 1.3.3 | ||
| var compile, fs, options, optparse, output, parser, printUsage, switches; | ||
| var compile = require('./jspackage').compile, | ||
| fs = require('fs'), | ||
| optparse = require('optparse'); | ||
| compile = require('./jspackage').compile; | ||
| var switches = [ | ||
| ['-h', '--help', "shows this help section"], | ||
| ['-b', '--bare', "compile without a top-level function wrapper"], | ||
| ['-w', '--watch', "watch source files and recompile when any change"], | ||
| ]; | ||
| fs = require('fs'); | ||
| var parser = new optparse.OptionParser(switches); | ||
| optparse = require('optparse'); | ||
| var printUsage = function() { | ||
| parser.banner = "Usage: jspackage input_file [output_file] [options]" | ||
| console.log(parser.toString()); | ||
| switches = [['-h', '--help', "shows this help section"], ['-b', '--bare', "compile without a top-level function wrapper"], ['-w', '--watch', "watch source files and recompile when any change"], ['-l', '--lib PATH', "add an additional search directory for source files"]]; | ||
| parser = new optparse.OptionParser(switches); | ||
| printUsage = function() { | ||
| parser.banner = "Usage: jspackage input_file output_file [options]"; | ||
| return console.log(parser.toString()); | ||
| }; | ||
| parser.on('help', function() { | ||
| printUsage(); | ||
| process.exit(1); | ||
| printUsage(); | ||
| return process.exit(1); | ||
| }); | ||
| var options = {}; | ||
| options = {}; | ||
| parser.on(0, function(arg) { | ||
| options.mainfile = arg; | ||
| return options.mainfile = arg; | ||
| }); | ||
| var output; | ||
| output = null; | ||
| parser.on(1, function(arg) { | ||
| output = arg; | ||
| return output = arg; | ||
| }); | ||
| parser.on("bare", function() { | ||
| options.bare = true; | ||
| return options.bare = true; | ||
| }); | ||
| parser.on("watch", function() { | ||
| options.watch = true; | ||
| return options.watch = true; | ||
| }); | ||
| parser.on("lib", function(name, value) { | ||
| var _ref; | ||
| return ((_ref = options.libs) != null ? _ref : options.libs = []).push(value); | ||
| }); | ||
| parser.parse(process.argv.splice(2)); | ||
| if (!options.mainfile) { | ||
| printUsage(); | ||
| process.exit(1); | ||
| if (!options.mainfile || !output) { | ||
| printUsage(); | ||
| process.exit(1); | ||
| } | ||
| if (output) { | ||
| compile(options, function(err, code) { | ||
| if (options.watch) { | ||
| var timestamp = (new Date()).toLocaleTimeString() | ||
| if (err) { | ||
| console.error(timestamp + " - error: " + err); | ||
| } else { | ||
| console.info(timestamp + " - generated " + output); | ||
| fs.writeFile(output, code); | ||
| } | ||
| } else { | ||
| if (err) throw err; | ||
| fs.writeFile(output, code); | ||
| } | ||
| }); | ||
| } | ||
| compile(options, function(err, code) { | ||
| var timestamp; | ||
| if (options.watch) { | ||
| timestamp = (new Date()).toLocaleTimeString(); | ||
| if (err) { | ||
| return console.error("" + timestamp + " - error: " + err); | ||
| } else { | ||
| console.info("" + timestamp + " - generated " + output); | ||
| return fs.writeFile(output, code); | ||
| } | ||
| } else { | ||
| if (err) { | ||
| throw err; | ||
| } | ||
| return fs.writeFile(output, code); | ||
| } | ||
| }); |
+280
-253
| // Generated by CoffeeScript 1.3.3 | ||
| (function() { | ||
| var async, cached_files, collectDependencies, compile, extensions, fs, options, parseFile, path, resolveDependencyChain, resolvePath, root, watchFile, watchFileFallback, watchFiles; | ||
| var async, cached_files, collectDependencies, compile, extensions, fs, libs, options, parseFile, path, resolveDependencyChain, resolveImport, root, watchFile, watchFileFallback, watchFiles; | ||
| fs = require('fs'); | ||
| fs = require('fs'); | ||
| path = require('path'); | ||
| path = require('path'); | ||
| async = require('async'); | ||
| async = require('async'); | ||
| cached_files = {}; | ||
| cached_files = {}; | ||
| root = null; | ||
| root = null; | ||
| options = null; | ||
| options = null; | ||
| parseFile = function(full_path, cb) { | ||
| var file; | ||
| file = { | ||
| path: full_path, | ||
| compiled_js: null, | ||
| mtime: null, | ||
| deps: [] | ||
| }; | ||
| return fs.stat(full_path, function(err, stat) { | ||
| parseFile = function(full_path, cb) { | ||
| var file; | ||
| file = { | ||
| path: full_path, | ||
| compiled_js: null, | ||
| mtime: null, | ||
| deps: [] | ||
| }; | ||
| return fs.stat(full_path, function(err, stat) { | ||
| if (err) { | ||
| cb(err); | ||
| return; | ||
| } | ||
| file.mtime = +stat.mtime; | ||
| return fs.readFile(full_path, 'utf8', function(err, source) { | ||
| var import_string, parser, re, result, timestamp; | ||
| if (err) { | ||
@@ -30,73 +36,94 @@ cb(err); | ||
| } | ||
| file.mtime = +stat.mtime; | ||
| return fs.readFile(full_path, 'utf8', function(err, source) { | ||
| var import_string, parser, re, result, timestamp; | ||
| if (err) { | ||
| cb(err); | ||
| return; | ||
| } | ||
| parser = extensions[path.extname(full_path)]; | ||
| try { | ||
| file.compiled_js = parser.compile(source); | ||
| } catch (err) { | ||
| cb("" + full_path + "\n" + err, file); | ||
| return; | ||
| } | ||
| if (options.watch) { | ||
| timestamp = (new Date()).toLocaleTimeString(); | ||
| console.info("" + timestamp + " - compiled " + file.path); | ||
| } | ||
| re = parser.import_re; | ||
| re.lastIndex = 0; | ||
| while (result = re.exec(source)) { | ||
| import_string = result[1].slice(1, -1); | ||
| if (import_string[0] !== '/') { | ||
| import_string = path.join(path.dirname(full_path), import_string); | ||
| } | ||
| file.deps.push(import_string); | ||
| } | ||
| return cb(null, file); | ||
| }); | ||
| parser = extensions[path.extname(full_path)]; | ||
| try { | ||
| file.compiled_js = parser.compile(source); | ||
| } catch (err) { | ||
| cb("" + full_path + "\n" + err, file); | ||
| return; | ||
| } | ||
| if (options.watch) { | ||
| timestamp = (new Date()).toLocaleTimeString(); | ||
| console.info("" + timestamp + " - compiled " + file.path); | ||
| } | ||
| re = parser.import_re; | ||
| re.lastIndex = 0; | ||
| while (result = re.exec(source)) { | ||
| import_string = result[1].slice(1, -1); | ||
| file.deps.push(import_string); | ||
| } | ||
| return cb(null, file); | ||
| }); | ||
| }; | ||
| }); | ||
| }; | ||
| resolvePath = function(import_string, doneResolvingPath) { | ||
| var resolveWithExt; | ||
| resolveWithExt = function(ext, cb) { | ||
| return fs.realpath(path.resolve(import_string + ext), function(err, real_path) { | ||
| if (err) { | ||
| cb(null, null); | ||
| return; | ||
| } | ||
| return fs.stat(real_path, function(err, stat) { | ||
| if (err || stat.isDirectory()) { | ||
| return cb(null, null); | ||
| } else { | ||
| return cb(null, real_path); | ||
| resolveImport = function(cwd, import_string, doneResolvingImport) { | ||
| var lib_index, tryNextLib, try_exts; | ||
| try_exts = [""].concat(Object.keys(extensions)); | ||
| lib_index = 0; | ||
| tryNextLib = function() { | ||
| var resolveWithExt, try_lib; | ||
| if ((try_lib = libs[lib_index++]) != null) { | ||
| resolveWithExt = function(ext, cb) { | ||
| var resolved_path; | ||
| resolved_path = path.resolve(cwd, try_lib, import_string + ext); | ||
| return fs.realpath(resolved_path, function(err, real_path) { | ||
| if (err) { | ||
| cb(null, null); | ||
| return; | ||
| } | ||
| return fs.stat(real_path, function(err, stat) { | ||
| if (err || stat.isDirectory()) { | ||
| return cb(null, null); | ||
| } else { | ||
| return cb(null, real_path); | ||
| } | ||
| }); | ||
| }); | ||
| }; | ||
| return async.map(try_exts, resolveWithExt, function(err, results) { | ||
| return async.filter(results, (function(item, cb) { | ||
| return cb(item != null); | ||
| }), function(results) { | ||
| if (results.length === 1) { | ||
| doneResolvingImport(null, results[0]); | ||
| } else if (results.length === 0) { | ||
| tryNextLib(); | ||
| } else if (results.length > 1) { | ||
| doneResolvingImport("ambiguous import: " + import_string); | ||
| } | ||
| }); | ||
| }); | ||
| } else { | ||
| return doneResolvingImport("unable to resolve import: " + import_string); | ||
| } | ||
| }; | ||
| return tryNextLib(); | ||
| }; | ||
| resolveDependencyChain = function(root, doneResolvingDependencyChain) { | ||
| var deps, processNode, seen; | ||
| deps = []; | ||
| seen = {}; | ||
| processNode = function(node, doneProcessingNode) { | ||
| var resolveFromDep; | ||
| resolveFromDep = function(dep, cb) { | ||
| return resolveImport(path.dirname(node.path), dep, cb); | ||
| }; | ||
| return async.map([""].concat(Object.keys(extensions)), resolveWithExt, function(err, results) { | ||
| return async.filter(results, (function(item, cb) { | ||
| return cb(item != null); | ||
| }), function(results) { | ||
| if (results.length === 1) { | ||
| doneResolvingPath(null, results[0]); | ||
| } else if (results.length === 0) { | ||
| doneResolvingPath("unable to resolve import: " + import_string); | ||
| } else if (results.length > 1) { | ||
| doneResolvingPath("ambiguous import: " + import_string); | ||
| return async.map(node.deps, resolveFromDep, function(err, resolved_deps) { | ||
| var dep, dep_path, funcs, _i, _len; | ||
| if (err) { | ||
| doneResolvingDependencyChain(err); | ||
| return; | ||
| } | ||
| funcs = []; | ||
| for (_i = 0, _len = resolved_deps.length; _i < _len; _i++) { | ||
| dep_path = resolved_deps[_i]; | ||
| dep = cached_files[dep_path]; | ||
| if (seen[dep.path] != null) { | ||
| continue; | ||
| } | ||
| }); | ||
| }); | ||
| }; | ||
| resolveDependencyChain = function(root, doneResolvingDependencyChain) { | ||
| var deps, processNode, seen; | ||
| deps = []; | ||
| seen = {}; | ||
| processNode = function(node, doneProcessingNode) { | ||
| return async.map(node.deps, resolvePath, function(err, resolved_deps) { | ||
| var dep, dep_path, funcs, _i, _len; | ||
| seen[dep.path] = true; | ||
| funcs.push(async.apply(processNode, dep)); | ||
| } | ||
| return async.parallel(funcs, function(err, results) { | ||
| if (err) { | ||
@@ -106,197 +133,197 @@ doneResolvingDependencyChain(err); | ||
| } | ||
| funcs = []; | ||
| for (_i = 0, _len = resolved_deps.length; _i < _len; _i++) { | ||
| dep_path = resolved_deps[_i]; | ||
| dep = cached_files[dep_path]; | ||
| if (seen[dep.path] != null) { | ||
| continue; | ||
| } | ||
| seen[dep.path] = true; | ||
| funcs.push(async.apply(processNode, dep)); | ||
| } | ||
| return async.parallel(funcs, function(err, results) { | ||
| if (err) { | ||
| doneResolvingDependencyChain(err); | ||
| return; | ||
| } | ||
| deps.push(node); | ||
| return doneProcessingNode(); | ||
| }); | ||
| deps.push(node); | ||
| return doneProcessingNode(); | ||
| }); | ||
| }; | ||
| return processNode(root, function() { | ||
| return doneResolvingDependencyChain(null, deps); | ||
| }); | ||
| }; | ||
| return processNode(root, function() { | ||
| return doneResolvingDependencyChain(null, deps); | ||
| }); | ||
| }; | ||
| collectDependencies = function(import_string, doneCollectingDependencies) { | ||
| return resolvePath(import_string, function(err, canonical_path) { | ||
| var cached_file, callNext, parseAndHandleErr; | ||
| if (err) { | ||
| doneCollectingDependencies(err); | ||
| return; | ||
| } | ||
| parseAndHandleErr = function(cb) { | ||
| return parseFile(canonical_path, function(err, file) { | ||
| if (file) { | ||
| cached_files[file.path] = file; | ||
| if (root == null) { | ||
| root = file; | ||
| } | ||
| collectDependencies = function(cwd, import_string, doneCollectingDependencies) { | ||
| return resolveImport(cwd, import_string, function(err, canonical_path) { | ||
| var cached_file, callNext, parseAndHandleErr; | ||
| if (err) { | ||
| doneCollectingDependencies(err); | ||
| return; | ||
| } | ||
| parseAndHandleErr = function(cb) { | ||
| return parseFile(canonical_path, function(err, file) { | ||
| if (file) { | ||
| cached_files[file.path] = file; | ||
| if (root == null) { | ||
| root = file; | ||
| } | ||
| if (err) { | ||
| doneCollectingDependencies(err); | ||
| } else { | ||
| cb(file); | ||
| } | ||
| }); | ||
| } | ||
| if (err) { | ||
| doneCollectingDependencies(err); | ||
| } else { | ||
| cb(file); | ||
| } | ||
| }); | ||
| }; | ||
| callNext = function(file) { | ||
| var collectFromFile; | ||
| collectFromFile = function(dep, cb) { | ||
| return collectDependencies(path.dirname(file.path), dep, cb); | ||
| }; | ||
| callNext = function(file) { | ||
| return async.map(file.deps, collectDependencies, doneCollectingDependencies); | ||
| }; | ||
| if ((cached_file = cached_files[canonical_path]) != null) { | ||
| return fs.stat(canonical_path, function(err, stat) { | ||
| if (cached_file.mtime === +stat.mtime) { | ||
| if (root == null) { | ||
| root = cached_file; | ||
| } | ||
| return callNext(cached_file); | ||
| } else { | ||
| return parseAndHandleErr(callNext); | ||
| return async.map(file.deps, collectFromFile, doneCollectingDependencies); | ||
| }; | ||
| if ((cached_file = cached_files[canonical_path]) != null) { | ||
| return fs.stat(canonical_path, function(err, stat) { | ||
| if (cached_file.mtime === +stat.mtime) { | ||
| if (root == null) { | ||
| root = cached_file; | ||
| } | ||
| }); | ||
| } else { | ||
| return parseAndHandleErr(callNext); | ||
| } | ||
| }); | ||
| return callNext(cached_file); | ||
| } else { | ||
| return parseAndHandleErr(callNext); | ||
| } | ||
| }); | ||
| } else { | ||
| return parseAndHandleErr(callNext); | ||
| } | ||
| }); | ||
| }; | ||
| watchFileFallback = function(filename, options, cb) { | ||
| options.interval = 701; | ||
| fs.watchFile(filename, options, function(curr, prev) { | ||
| if (curr.mtime !== prev.mtime) { | ||
| return cb("change", filename); | ||
| } | ||
| }); | ||
| return { | ||
| close: function() { | ||
| return fs.unwatchFile(filename); | ||
| } | ||
| }; | ||
| }; | ||
| watchFileFallback = function(filename, options, cb) { | ||
| options.interval = 701; | ||
| fs.watchFile(filename, options, function(curr, prev) { | ||
| if (curr.mtime !== prev.mtime) { | ||
| return cb("change", filename); | ||
| watchFile = fs.watch || watchFileFallback; | ||
| watchFiles = function(files, cb) { | ||
| var doCallback, file, watcher, watchers, _i, _len, _results; | ||
| watchers = []; | ||
| doCallback = function(event) { | ||
| var watcher, _i, _len; | ||
| if (event === "change") { | ||
| for (_i = 0, _len = watchers.length; _i < _len; _i++) { | ||
| watcher = watchers[_i]; | ||
| watcher.close(); | ||
| } | ||
| }); | ||
| return { | ||
| close: function() { | ||
| return fs.unwatchFile(filename); | ||
| } | ||
| }; | ||
| return cb(); | ||
| } | ||
| }; | ||
| _results = []; | ||
| for (_i = 0, _len = files.length; _i < _len; _i++) { | ||
| file = files[_i]; | ||
| try { | ||
| watcher = fs.watch(file, doCallback); | ||
| } catch (err) { | ||
| watcher = watchFileFallback(file, doCallback); | ||
| } | ||
| _results.push(watchers.push(watcher)); | ||
| } | ||
| return _results; | ||
| }; | ||
| watchFile = fs.watch || watchFileFallback; | ||
| libs = null; | ||
| watchFiles = function(files, cb) { | ||
| var doCallback, file, watcher, watchers, _i, _len, _results; | ||
| console.log("watching", files); | ||
| watchers = []; | ||
| doCallback = function(event) { | ||
| var watcher, _i, _len; | ||
| if (event === "change") { | ||
| for (_i = 0, _len = watchers.length; _i < _len; _i++) { | ||
| watcher = watchers[_i]; | ||
| watcher.close(); | ||
| } | ||
| return cb(); | ||
| } | ||
| }; | ||
| compile = function(_options, cb) { | ||
| var lib, _ref; | ||
| options = _options; | ||
| libs = (_ref = options.libs) != null ? _ref : []; | ||
| libs = (function() { | ||
| var _i, _len, _results; | ||
| _results = []; | ||
| for (_i = 0, _len = files.length; _i < _len; _i++) { | ||
| file = files[_i]; | ||
| try { | ||
| watcher = fs.watch(file, doCallback); | ||
| } catch (err) { | ||
| watcher = watchFileFallback(file, doCallback); | ||
| } | ||
| _results.push(watchers.push(watcher)); | ||
| for (_i = 0, _len = libs.length; _i < _len; _i++) { | ||
| lib = libs[_i]; | ||
| _results.push(path.resolve(lib)); | ||
| } | ||
| return _results; | ||
| }; | ||
| compile = function(_options, cb) { | ||
| options = _options; | ||
| root = null; | ||
| return collectDependencies(options.mainfile, function(collect_err) { | ||
| if (collect_err && !(root != null)) { | ||
| })(); | ||
| libs.unshift("."); | ||
| root = null; | ||
| return collectDependencies(process.cwd(), options.mainfile, function(collect_err) { | ||
| if (collect_err && !(root != null)) { | ||
| cb(collect_err); | ||
| return; | ||
| } | ||
| return resolveDependencyChain(root, function(err, dependency_chain) { | ||
| var dep, output; | ||
| if (_options.watch) { | ||
| watchFiles((function() { | ||
| var _i, _len, _results; | ||
| _results = []; | ||
| for (_i = 0, _len = dependency_chain.length; _i < _len; _i++) { | ||
| dep = dependency_chain[_i]; | ||
| _results.push(dep.path); | ||
| } | ||
| return _results; | ||
| })(), function() { | ||
| return compile(_options, cb); | ||
| }); | ||
| } | ||
| if (err) { | ||
| cb(err); | ||
| } else if (collect_err) { | ||
| cb(collect_err); | ||
| return; | ||
| } else { | ||
| output = ((function() { | ||
| var _i, _len, _results; | ||
| _results = []; | ||
| for (_i = 0, _len = dependency_chain.length; _i < _len; _i++) { | ||
| dep = dependency_chain[_i]; | ||
| _results.push(dep.compiled_js); | ||
| } | ||
| return _results; | ||
| })()).join("\n"); | ||
| cb(null, output); | ||
| } | ||
| return resolveDependencyChain(root, function(err, dependency_chain) { | ||
| var dep, output; | ||
| if (_options.watch) { | ||
| watchFiles((function() { | ||
| var _i, _len, _results; | ||
| _results = []; | ||
| for (_i = 0, _len = dependency_chain.length; _i < _len; _i++) { | ||
| dep = dependency_chain[_i]; | ||
| _results.push(dep.path); | ||
| } | ||
| return _results; | ||
| })(), function() { | ||
| return compile(_options, cb); | ||
| }); | ||
| } | ||
| if (err) { | ||
| cb(err); | ||
| } else if (collect_err) { | ||
| cb(collect_err); | ||
| } else { | ||
| output = ((function() { | ||
| var _i, _len, _results; | ||
| _results = []; | ||
| for (_i = 0, _len = dependency_chain.length; _i < _len; _i++) { | ||
| dep = dependency_chain[_i]; | ||
| _results.push(dep.compiled_js); | ||
| } | ||
| return _results; | ||
| })()).join("\n"); | ||
| cb(null, output); | ||
| } | ||
| }); | ||
| }); | ||
| }; | ||
| }); | ||
| }; | ||
| extensions = { | ||
| '.coffee': { | ||
| compile: function(code) { | ||
| return require('coffee-script').compile(code, { | ||
| bare: options.bare | ||
| }); | ||
| }, | ||
| import_re: /^#import (".+")$/gm | ||
| extensions = { | ||
| '.coffee': { | ||
| compile: function(code) { | ||
| return require('coffee-script').compile(code, { | ||
| bare: options.bare | ||
| }); | ||
| }, | ||
| '.js': { | ||
| compile: function(code) { | ||
| if (options.bare) { | ||
| return code; | ||
| } else { | ||
| return "(function(){\n" + code + "}).call(this);"; | ||
| } | ||
| }, | ||
| import_re: /^\/\/import (".+");?$/gm | ||
| import_re: /^#import (".+")$/gm | ||
| }, | ||
| '.js': { | ||
| compile: function(code) { | ||
| if (options.bare) { | ||
| return code; | ||
| } else { | ||
| return "(function(){\n" + code + "}).call(this);"; | ||
| } | ||
| }, | ||
| '.co': { | ||
| compile: function(code) { | ||
| return require('coco').compile(code, { | ||
| bare: options.bare | ||
| }); | ||
| }, | ||
| import_re: /^#import (".+")$/gm | ||
| import_re: /^\/\/import (".+");?$/gm | ||
| }, | ||
| '.co': { | ||
| compile: function(code) { | ||
| return require('coco').compile(code, { | ||
| bare: options.bare | ||
| }); | ||
| }, | ||
| '.ls': { | ||
| compile: function(code) { | ||
| return require('LiveScript').compile(code, { | ||
| bare: options.bare | ||
| }); | ||
| }, | ||
| import_re: /^#import (".+")$/gm | ||
| } | ||
| }; | ||
| import_re: /^#import (".+")$/gm | ||
| }, | ||
| '.ls': { | ||
| compile: function(code) { | ||
| return require('LiveScript').compile(code, { | ||
| bare: options.bare | ||
| }); | ||
| }, | ||
| import_re: /^#import (".+")$/gm | ||
| } | ||
| }; | ||
| module.exports = { | ||
| compile: compile, | ||
| extensions: extensions | ||
| }; | ||
| }).call(this); | ||
| module.exports = { | ||
| compile: compile, | ||
| extensions: extensions | ||
| }; |
+2
-2
| { | ||
| "name": "jspackage", | ||
| "description": "build tool which adds client-side import syntax", | ||
| "version": "0.1.0", | ||
| "version": "0.2.0", | ||
| "author": { | ||
@@ -31,5 +31,5 @@ "name": "Andrew Kelley", | ||
| "bin": { | ||
| "jspackage": "./cmd.js" | ||
| "jspackage": "./cmd_wrapper.js" | ||
| }, | ||
| "main": "jspackage.js" | ||
| } |
+3
-3
@@ -58,7 +58,7 @@ Client side build tool with dependency management | ||
| compile 'mainfile', (err, code) -> | ||
| compile 'mainfile', (err, compiled_code) -> | ||
| if err | ||
| res.end 'throw unescape("' + escape(err.toString()) + '");' | ||
| else | ||
| res.end code | ||
| res.end compiled_code | ||
@@ -92,3 +92,3 @@ server.listen(8080) | ||
| coffee -wco . src/ | ||
| coffee -wbco . src/ | ||
@@ -95,0 +95,0 @@ To run the tests: |
+44
-31
@@ -39,6 +39,2 @@ fs = require('fs') | ||
| import_string = result[1].slice(1, -1) | ||
| # relative dependencies should default to the | ||
| # same directory as the parent | ||
| if import_string[0] isnt '/' | ||
| import_string = path.join(path.dirname(full_path), import_string) | ||
| file.deps.push import_string | ||
@@ -48,25 +44,33 @@ cb null, file | ||
| resolvePath = (import_string, doneResolvingPath) -> | ||
| resolveWithExt = (ext, cb) -> | ||
| fs.realpath path.resolve(import_string + ext), (err, real_path) -> | ||
| if err | ||
| cb null, null | ||
| return | ||
| fs.stat real_path, (err, stat) -> | ||
| if err or stat.isDirectory() | ||
| cb null, null | ||
| else | ||
| cb null, real_path | ||
| resolveImport = (cwd, import_string, doneResolvingImport) -> | ||
| # try each of the supported extensions | ||
| async.map [""].concat(Object.keys(extensions)), resolveWithExt, (err, results) -> | ||
| async.filter results, ((item, cb) -> cb(item?)), (results) -> | ||
| if results.length is 1 | ||
| doneResolvingPath null, results[0] | ||
| else if results.length is 0 | ||
| doneResolvingPath("unable to resolve import: #{import_string}") | ||
| else if results.length > 1 | ||
| doneResolvingPath("ambiguous import: #{import_string}") | ||
| return | ||
| try_exts = [""].concat(Object.keys(extensions)) | ||
| # try each of the libs, but stop upon first success | ||
| lib_index = 0 | ||
| tryNextLib = -> | ||
| if (try_lib = libs[lib_index++])? | ||
| resolveWithExt = (ext, cb) -> | ||
| resolved_path = path.resolve(cwd, try_lib, import_string + ext) | ||
| fs.realpath resolved_path, (err, real_path) -> | ||
| if err | ||
| cb null, null | ||
| return | ||
| fs.stat real_path, (err, stat) -> | ||
| if err or stat.isDirectory() | ||
| cb null, null | ||
| else | ||
| cb null, real_path | ||
| async.map try_exts, resolveWithExt, (err, results) -> | ||
| async.filter results, ((item, cb) -> cb(item?)), (results) -> | ||
| if results.length is 1 | ||
| doneResolvingImport null, results[0] | ||
| else if results.length is 0 | ||
| tryNextLib() | ||
| else if results.length > 1 | ||
| doneResolvingImport("ambiguous import: #{import_string}") | ||
| return | ||
| else | ||
| doneResolvingImport("unable to resolve import: #{import_string}") | ||
| tryNextLib() | ||
| resolveDependencyChain = (root, doneResolvingDependencyChain) -> | ||
@@ -76,3 +80,4 @@ deps = [] | ||
| processNode = (node, doneProcessingNode) -> | ||
| async.map node.deps, resolvePath, (err, resolved_deps) -> | ||
| resolveFromDep = (dep, cb) -> resolveImport(path.dirname(node.path), dep, cb) | ||
| async.map node.deps, resolveFromDep, (err, resolved_deps) -> | ||
| if err | ||
@@ -97,4 +102,4 @@ doneResolvingDependencyChain err | ||
| collectDependencies = (import_string, doneCollectingDependencies) -> | ||
| resolvePath import_string, (err, canonical_path) -> | ||
| collectDependencies = (cwd, import_string, doneCollectingDependencies) -> | ||
| resolveImport cwd, import_string, (err, canonical_path) -> | ||
| if err | ||
@@ -118,3 +123,5 @@ doneCollectingDependencies(err) | ||
| callNext = (file) -> | ||
| async.map file.deps, collectDependencies, doneCollectingDependencies | ||
| collectFromFile = (dep, cb) -> | ||
| collectDependencies(path.dirname(file.path), dep, cb) | ||
| async.map file.deps, collectFromFile, doneCollectingDependencies | ||
@@ -155,6 +162,12 @@ if (cached_file = cached_files[canonical_path])? | ||
| libs = null | ||
| compile = (_options, cb) -> | ||
| options = _options | ||
| libs = options.libs ? [] | ||
| libs = (path.resolve(lib) for lib in libs) | ||
| libs.unshift "." | ||
| root = null | ||
| collectDependencies options.mainfile, (collect_err) -> | ||
| collectDependencies process.cwd(), options.mainfile, (collect_err) -> | ||
| if collect_err and not root? | ||
@@ -161,0 +174,0 @@ cb(collect_err) |
+84
-87
| // Generated by CoffeeScript 1.3.3 | ||
| (function() { | ||
| var async, exec, fail_count, fs, msg, pass_count, path, temp, tests_dir, tmp_js_file; | ||
| var async, exec, fail_count, fs, msg, pass_count, path, temp, tests_dir, tmp_js_file; | ||
| exec = require("child_process").exec; | ||
| exec = require("child_process").exec; | ||
| fs = require("fs"); | ||
| fs = require("fs"); | ||
| path = require("path"); | ||
| path = require("path"); | ||
| async = require("async"); | ||
| async = require("async"); | ||
| temp = require("temp"); | ||
| temp = require("temp"); | ||
| tests_dir = "./tests/"; | ||
| tests_dir = "./tests/"; | ||
| tmp_js_file = "./.test_out.tmp.js"; | ||
| tmp_js_file = "./.test_out.tmp.js"; | ||
| msg = ""; | ||
| msg = ""; | ||
| pass_count = 0; | ||
| pass_count = 0; | ||
| fail_count = 0; | ||
| fail_count = 0; | ||
| fs.readdir(tests_dir, function(err, files) { | ||
| var doTest; | ||
| doTest = function(test_dir, testDone) { | ||
| var expect_file, main_file, switches_file; | ||
| main_file = path.join(tests_dir, test_dir, "test"); | ||
| expect_file = path.join(tests_dir, test_dir, "expected.txt"); | ||
| switches_file = path.join(tests_dir, test_dir, "switches.txt"); | ||
| return (function(exec_result, expected_output) { | ||
| var execTest, readExpected; | ||
| execTest = function(cb) { | ||
| return fs.readFile(switches_file, 'utf8', function(err, switches) { | ||
| switches = (switches || "").replace(/\n/g, " "); | ||
| return temp.open("", function(err, tmp_js_file) { | ||
| var cmdline; | ||
| cmdline = "node ./cmd.js " + switches + " " + main_file + " " + tmp_js_file.path; | ||
| return exec(cmdline, function(err, stdout, stderr) { | ||
| fs.readdir(tests_dir, function(err, files) { | ||
| var doTest; | ||
| doTest = function(test_dir, testDone) { | ||
| var expect_file, main_file, switches_file; | ||
| main_file = path.join(tests_dir, test_dir, "test"); | ||
| expect_file = path.join(tests_dir, test_dir, "expected.txt"); | ||
| switches_file = path.join(tests_dir, test_dir, "switches.txt"); | ||
| return (function(exec_result, expected_output) { | ||
| var execTest, readExpected; | ||
| execTest = function(cb) { | ||
| return fs.readFile(switches_file, 'utf8', function(err, switches) { | ||
| switches = (switches || "").replace(/\n/g, " "); | ||
| return temp.open("", function(err, tmp_js_file) { | ||
| var cmdline; | ||
| cmdline = "node ./cmd.js " + switches + " " + main_file + " " + tmp_js_file.path; | ||
| return exec(cmdline, function(err, stdout, stderr) { | ||
| if (stderr.length > 0) { | ||
| exec_result = { | ||
| compile: false, | ||
| msg: stderr | ||
| }; | ||
| cb(); | ||
| } | ||
| return exec("node " + tmp_js_file.path, function(err, stdout, stderr) { | ||
| fs.close(tmp_js_file.fd, function() { | ||
| return fs.unlink(tmp_js_file.path); | ||
| }); | ||
| if (stderr.length > 0) { | ||
| exec_result = { | ||
| compile: false, | ||
| compile: true, | ||
| run: false, | ||
| msg: stderr | ||
| }; | ||
| cb(); | ||
| } else { | ||
| exec_result = { | ||
| compile: true, | ||
| run: true, | ||
| output: stdout | ||
| }; | ||
| } | ||
| return exec("node " + tmp_js_file.path, function(err, stdout, stderr) { | ||
| fs.close(tmp_js_file.fd, function() { | ||
| return fs.unlink(tmp_js_file.path); | ||
| }); | ||
| if (stderr.length > 0) { | ||
| exec_result = { | ||
| compile: true, | ||
| run: false, | ||
| msg: stderr | ||
| }; | ||
| } else { | ||
| exec_result = { | ||
| compile: true, | ||
| run: true, | ||
| output: stdout | ||
| }; | ||
| } | ||
| return cb(); | ||
| }); | ||
| return cb(); | ||
| }); | ||
| }); | ||
| }); | ||
| }; | ||
| readExpected = function(cb) { | ||
| return fs.readFile(expect_file, 'utf8', function(err, out) { | ||
| expected_output = out; | ||
| return cb(); | ||
| }); | ||
| }; | ||
| return async.parallel([execTest, readExpected], function() { | ||
| if (exec_result.compile) { | ||
| if (exec_result.run) { | ||
| if (exec_result.output === expected_output) { | ||
| process.stdout.write("."); | ||
| pass_count += 1; | ||
| } else { | ||
| process.stdout.write("F"); | ||
| fail_count += 1; | ||
| msg += "\n\n======== " + test_dir + " failed =========\n-------- Expected Output: ---------\n" + expected_output + "\n-------------------------------------\n-------- Actual Output: ---------\n" + exec_result.output + "\n-------------------------------------"; | ||
| } | ||
| }); | ||
| }; | ||
| readExpected = function(cb) { | ||
| return fs.readFile(expect_file, 'utf8', function(err, out) { | ||
| expected_output = out; | ||
| return cb(); | ||
| }); | ||
| }; | ||
| return async.parallel([execTest, readExpected], function() { | ||
| if (exec_result.compile) { | ||
| if (exec_result.run) { | ||
| if (exec_result.output === expected_output) { | ||
| process.stdout.write("."); | ||
| pass_count += 1; | ||
| } else { | ||
| process.stdout.write("E"); | ||
| process.stdout.write("F"); | ||
| fail_count += 1; | ||
| msg += "\n\n======== " + test_dir + " crashed ========\n-------- stderr: ---------\n" + exec_result.msg + "\n-------------------------------------"; | ||
| msg += "\n\n======== " + test_dir + " failed =========\n-------- Expected Output: ---------\n" + expected_output + "\n-------------------------------------\n-------- Actual Output: ---------\n" + exec_result.output + "\n-------------------------------------"; | ||
| } | ||
| } else { | ||
| process.stdout.write("X"); | ||
| process.stdout.write("E"); | ||
| fail_count += 1; | ||
| msg += "\n\n======== " + test_dir + " compile error ==\n-------- stderr: ---------\n" + exec_result.msg + "\n-------------------------------------"; | ||
| msg += "\n\n======== " + test_dir + " crashed ========\n-------- stderr: ---------\n" + exec_result.msg + "\n-------------------------------------"; | ||
| } | ||
| return testDone(); | ||
| }); | ||
| })(null, null); | ||
| }; | ||
| return async.map(files, doTest, function() { | ||
| if (msg.length > 0) { | ||
| process.stdout.write(msg); | ||
| } | ||
| process.stdout.write("\n" + pass_count + " passed, " + fail_count + " failed.\n"); | ||
| fs.unlink(tmp_js_file); | ||
| if (fail_count > 0) { | ||
| return process.exit(1); | ||
| } | ||
| }); | ||
| } else { | ||
| process.stdout.write("X"); | ||
| fail_count += 1; | ||
| msg += "\n\n======== " + test_dir + " compile error ==\n-------- stderr: ---------\n" + exec_result.msg + "\n-------------------------------------"; | ||
| } | ||
| return testDone(); | ||
| }); | ||
| })(null, null); | ||
| }; | ||
| return async.map(files, doTest, function() { | ||
| if (msg.length > 0) { | ||
| process.stdout.write(msg); | ||
| } | ||
| process.stdout.write("\n" + pass_count + " passed, " + fail_count + " failed.\n"); | ||
| fs.unlink(tmp_js_file); | ||
| if (fail_count > 0) { | ||
| return process.exit(1); | ||
| } | ||
| }); | ||
| }).call(this); | ||
| }); |
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
29869
10.13%41
64%498
8.26%