This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

Initial drop. Ugly, sketchy, and not even yet quite a "work in progre…

…ss".
  • Loading branch information...
isaacs
isaacs committed Sep 29, 2009
0 parents commit 4626dfa73b7847e9c42c1f799935f8242794d020
Showing with 288 additions and 0 deletions.
  1. +61 −0 README.md
  2. +3 −0 install.js
  3. +77 −0 npm.js
  4. +5 −0 sources.json
  5. +96 −0 src/bootstrap.js
  6. +46 −0 src/queue.js
@@ -0,0 +1,61 @@
# npm – The Node Package Manager
npm is a little package manager for the Node javascript library.
## 5-Second(ish) Install
You should already have node installed and working. If you don't, go do that first.
Then, come back here, and run:
./install.js
and it'll install itself and its requirements.
## Commands
You can get more details on any of these by doing `npm <command> --help`. Here are the basics.
All flags with two hyphens can be abbreviated to a single hyphen with the first letter, so you can also do `npm <command> -h` to get its info.
All commands return 0 if they succeed, and usually 1 if they don't. Normal output is on stdout, and oddness goes to stderr. Use the `--verbose` flag with any command to send extra debugging output to stderr.
### Managing Sources
npm learns all it knows about packages by looking at the JSON files specified in its catalog list. Manage this catalog list via the `npm source` commands.
### Update Package Metadata
Fetch the latest info from every source by doing `npm refresh`. Throw a `--force` on there if you want to clear the cache first.
It's a good idea to update every so often, maybe even put it on a weekly cron or something.
@TODO: Keep track of which packages were updated, and then
add them to an "outdated" list. Then, `npm update` could
be an alias to `npm refresh && npm install --force --outdated`
### Update Package Code
Version numbers aren't yet supported, so npm can't tell when a package has new code for you. If you know that it does, you can do `npm install --force <package>` to force-install the latest version.
### Find a Package
Find a package in the list by doing `npm search <string>`. If you only want to search through installed packages, then do `npm search --installed <string>`. If you only want to search through activated packages, then do `npm search --active <string>`.
### Activating/Deactivating Packages
Use `npm activate <package>`. Note that installing a package activates it by default, and uninstalling it deactivates it first.
### Starting/stopping Packages
Some packages are servers and the like that must be activated after being installed. To do this, do `npm start <package>`. To stop it, do `npm stop <package>`.
### Remove a Package
You can uninstall a package by doing `npm remove <package>`. This will first `stop` it if it's running, then remove its files from your system.
## Setting Defaults and Aliases via `$HOME/.npmrc`
Gee, it'd sure be nice to be able to have a `$HOME/.npmrc` file that could maybe pre-fix some of these options, dotcha think?
Write it, and send me a pull request, kthx.
@@ -0,0 +1,3 @@
#!/usr/bin/env node
setTimeout(require("./src/bootstrap.js").bootstrap);
77 npm.js
@@ -0,0 +1,77 @@
// the main guts
var npm = exports,
queue = require("./src/queue.js").queue,
http = require("/http.js");
include("/utils.js");
npm.install = function npm_install () {
return dummyPromise()
};
npm.refresh = function npm_refresh () {
// return dummyPromise()
// get my list of sources.
var p = new node.Promise();
npm.getSources().addCallback(function (srcArr) {
queue(srcArr, function (src) {
return npm.refreshSource(src)
}).addCallback(function () {
p.emitSuccess();
}).addErrback(function () {
p.emitError();
});
});
return p;
};
npm.getSources = function npm_getSources () {
var p = new node.Promise();
node.fs.cat(node.path.join(ENV.HOME, ".npm", "sources.json"))
.addErrback(function () {
p.emitError(new Error(
"Couldn't read " + node.path.join(ENV.HOME, ".npm", "sources.json") + "\n"
));
})
.addCallback(function (data) {
try {
data = JSON.parse(data);
if (data) p.emitSuccess(data);
} catch (ex) { p.emitError(ex); return; }
});
return p;
};
npm.refreshSource = function npm_refreshSource (src) {
debug("refresh the source: "+src);
var p = new node.Promise();
// var u = http.parseUri(src);
// var httpClient = http.createClient(uri.port || 80, uri.host);
// client.get(uri.path || "/", headers || {})
http.cat(src, "utf-8", { "User-Agent" : "nodejs" })
.addCallback(function (data) {
debug("do something");
p.emitSuccess(data);
})
.addErrback(function (er) {
debug("error "+JSON.stringify(er)+ " " + JSON.stringify(res));
p.emitError(er);
});
return p;
};
function dummyPromise (name) {
var promise = new node.Promise();
name = name || arguments.callee.caller.name;
setTimeout(function () {
node.stdio.writeError("TODO: implement "+ name + "\n");
promise.emitSuccess("dummy");
});
return promise;
};
@@ -0,0 +1,5 @@
[
"http://localhost/dev/sandbox/phpinfo.php",
"../npm-data/catalog.json",
"http://github.com/isaacs/npm-data/raw/master/catalog.json"
]
@@ -0,0 +1,96 @@
include("/utils.js");
var npmDir = node.path.dirname(node.path.dirname(__filename)),
HOME = ENV.HOME,
npm = require("../npm.js"),
queuePromise = new node.Promise();
exports.bootstrap = function bootstrap () {
node.stdio.writeError("npm: bootstrapping\n");
queuePromise.addCallback(function () {
node.stdio.write("ok");
});
next();
}
function statTester (thing, test, success, failure) {
return function () {
node.fs.stat(thing).addCallback(function (stats) {
return (stats[test]()) ? success.apply(this, arguments)
: failure.apply(this, arguments);
}).addErrback(failure);
};
};
// mkdir if not already existent.
// Doesn't handle mkdir -p, which would be nice, but is not necessary for this
function dirMaker (dir, mode, success, failure) {
return statTester(dir, "isDirectory", success, function () {
node.fs.mkdir(dir, mode).addErrback(failure).addCallback(success);
});
};
function fail (msg) { return function () {
node.stdio.writeError("npm bootstrap failed: "+msg);
}}
function next () {
return script.shift()();
}
function done () {
queuePromise.emitSuccess();
}
var script = [
// make sure that the ~/.node_libraries and ~/.npm exist.
dirMaker(node.path.join(HOME, ".node_libraries"), 0755, next, fail(
"couldn't create " + node.path.join(HOME, ".node_libraries")
)),
dirMaker(node.path.join(HOME, ".npm"), 0755, next, fail(
"couldn't create " + node.path.join(HOME, ".npm")
)),
// If no in ~/.npm/sources.json, then copy over the local one
statTester(
node.path.join(HOME, ".npm", "sources.json"), "isFile", next,
function () {
// try to copy the file over.
// seems like there outta be a node.fs.cp
node.fs.cat(
node.path.join(npmDir, "sources.json")
).addErrback(fail(
"couldn't read " + node.path.join(npmDir, "sources.json")
)).addCallback(function (content) {
node.fs.open(
node.path.join(HOME, ".npm", "sources.json"),
node.O_WRONLY | node.O_TRUNC | node.O_CREAT,
0666
).addErrback(fail(
"couldn't open "+node.path.join(HOME, ".npm", "sources.json")+" for writing"
)).addCallback(function (fd) {
node.fs.write(fd, content, 0).addErrback(fail(
"couldn't write to "+node.path.join(HOME, ".npm", "sources.json")
)).addCallback(next);
});
});
}
),
// call npm.refresh()
function () {
npm.refresh().addErrback(fail(
"Failed calling npm.refresh()"
)).addCallback(next);
},
// call npm.install("--force", "npm")
function () {
npm.install("--force", "npm").addErrback(fail(
"Failed installing npm with npm"
)).addCallback(next);
},
done
];
@@ -0,0 +1,46 @@
exports.queue = function queue (items, fn) {
return new Queue(items, fn).start();
};
// items are the things
// fn is what to do to each one.
// promise is the promise that is fulfilled when it works.
function Queue (items, fn) {
this.items = [];
for (var i = 0, l = items.length; i < l; i ++) if (i in items) {
this.push(items[i]);
}
this.fn = fn;
}
function Queue_next () {
if (this.items.length <= 0) return this.promise.emitSuccess();
var np = new node.Promise(),
self = this
np.addCallback(function () { Queue_next.call(self) });
setTimeout(function () {
try {
var fnP = self.fn.call(null, self.items.shift());
if (fnP instanceof node.Promise) fnP.addCallback(function () {
np.emitSuccess();
}).addErrback(function () {
np.emitError();
});
else np.emitSuccess();
} catch (ex) {
self.promise.emitError(ex);
}
});
return this.promise;
};
Queue.prototype = {
start : function Queue_start () {
if (this._started) return;
this._started = true;
this.promise = new node.Promise();
return Queue_next.call(this);
},
push : function (i) { this.items.push(i); }
};

0 comments on commit 4626dfa

Please sign in to comment.