Skip to content
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.
You can’t perform that action at this time.