docs: Deploy a private npm registry in 5 minutes
This commit is contained in:
@@ -22,3 +22,4 @@ config/web_readme.md
|
||||
config/config.js
|
||||
*.sqlite
|
||||
.node-dev.json
|
||||
nohup.out
|
||||
|
||||
@@ -42,7 +42,7 @@ Our goal is to provide a low cost maintenance and easy to use solution for priva
|
||||
* Build a mirror NPM. (we use it to build a mirror in China: [cnpmjs.org](http://cnpmjs.org/))
|
||||
* Build a completely independent NPM registry to store whatever you like.
|
||||
|
||||
### Features
|
||||
## Features
|
||||
|
||||
* **Support "scoped" packages**: [npm/npm#5239](https://github.com/npm/npm/issues/5239)
|
||||
* **Support [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing)**
|
||||
@@ -66,6 +66,7 @@ as well as [New features in 2.x](https://github.com/cnpm/cnpmjs.org/wiki/New-fea
|
||||
|
||||
## Getting Start
|
||||
|
||||
* [Deploy a private npm registry in 5 minutes](https://github.com/cnpm/cnpmjs.org/wiki/Deploy-a-private-npm-registry-in-5-minutes)
|
||||
* @[dead-horse](https://github.com/dead-horse): [What is cnpm?](http://deadhorse.me/slides/cnpmjs.html)
|
||||
* install and deploy cnpmjs.org through npm: [examples](https://github.com/cnpm/custom-cnpm-example)
|
||||
* Mirror NPM in China: [cnpmjs.org](http://cnpmjs.org)
|
||||
|
||||
131
bin/cli.js
Executable file
131
bin/cli.js
Executable file
@@ -0,0 +1,131 @@
|
||||
#!/usr/bin/env node --harmony
|
||||
|
||||
/**!
|
||||
* cnpmjs.org - bin/cli.js
|
||||
*
|
||||
* Copyright(c) fengmk2 and other contributors.
|
||||
* MIT Licensed
|
||||
*
|
||||
* Authors:
|
||||
* fengmk2 <m@fengmk2.com> (http://fengmk2.com)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var debug = require('debug')('cnpmjs.org:cli');
|
||||
var program = require('commander');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var mkdirp = require('mkdirp');
|
||||
var treekill = require('treekill');
|
||||
var version = require('../package.json').version;
|
||||
|
||||
function list(val) {
|
||||
return val.split(',');
|
||||
}
|
||||
|
||||
program
|
||||
.version(version);
|
||||
|
||||
program
|
||||
.command('start')
|
||||
.description('start cnpmjs.org server')
|
||||
.option('--admins <admins>', 'set admins', list)
|
||||
.option('--scopes <scopes>', 'set scopes', list)
|
||||
// .option('--cluster', 'enable cluster mode')
|
||||
.option('--dataDir <dataDir>', 'cnpmjs.org data dir, default is `$HOME/.cnpmjs.org`')
|
||||
.action(start);
|
||||
|
||||
program
|
||||
.command('stop')
|
||||
.description('stop cnpmjs.org server')
|
||||
.option('--dataDir <dataDir>', 'cnpmjs.org data dir, default is `$HOME/.cnpmjs.org`')
|
||||
.action(stop);
|
||||
|
||||
program.parse(process.argv);
|
||||
|
||||
|
||||
function start(options) {
|
||||
var dataDir = options.dataDir || path.join(process.env.HOME, '.cnpmjs.org');
|
||||
mkdirp.sync(dataDir);
|
||||
|
||||
var configfile = path.join(dataDir, 'config.json');
|
||||
var config = {};
|
||||
if (fs.existsSync(configfile)) {
|
||||
try {
|
||||
config = require(configfile);
|
||||
} catch (err) {
|
||||
console.warn('load old %s error: %s', configfile, err);
|
||||
}
|
||||
}
|
||||
// config.enableCluster = !!options.cluster;
|
||||
if (options.admins) {
|
||||
config.admins = {};
|
||||
for (var i = 0; i < options.admins.length; i++) {
|
||||
config.admins[options.admins[i]] = options.admins[i] + '@localhost.com';
|
||||
}
|
||||
}
|
||||
if (options.scopes) {
|
||||
config.scopes = options.scopes.map(function (name) {
|
||||
if (name[0] !== '@') {
|
||||
name = '@' + name;
|
||||
}
|
||||
return name;
|
||||
});
|
||||
}
|
||||
|
||||
var configJSON = JSON.stringify(config, null, 2);
|
||||
fs.writeFileSync(configfile, configJSON);
|
||||
|
||||
debug('save config %s to %s', configJSON, configfile);
|
||||
|
||||
// if sqlite db file not exists, init first
|
||||
initDatabase();
|
||||
|
||||
require('../dispatch');
|
||||
fs.writeFileSync(path.join(dataDir, 'pid'), process.pid + '');
|
||||
}
|
||||
|
||||
function stop(options) {
|
||||
var dataDir = options.dataDir || path.join(process.env.HOME, '.cnpmjs.org');
|
||||
var pidfile = path.join(dataDir, 'pid');
|
||||
if (fs.existsSync(pidfile)) {
|
||||
var pid = Number(fs.readFileSync(pidfile, 'utf8'));
|
||||
treekill(pid, function (err) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
throw err;
|
||||
}
|
||||
console.log('cnpmjs.org server:%d stop', pid);
|
||||
fs.unlinkSync(pidfile);
|
||||
});
|
||||
} else {
|
||||
console.log('cnpmjs.org server not start');
|
||||
}
|
||||
}
|
||||
|
||||
function initDatabase() {
|
||||
var models = require('../models');
|
||||
|
||||
models.sequelize.sync({ force: false })
|
||||
.then(function () {
|
||||
models.Total.init(function (err) {
|
||||
if (err) {
|
||||
console.error('[models/init_script.js] sequelize init fail');
|
||||
console.error(err);
|
||||
throw err;
|
||||
} else {
|
||||
console.log('[models/init_script.js] `sqlite` sequelize sync and init success');
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(function (err) {
|
||||
console.error('[models/init_script.js] sequelize sync fail');
|
||||
console.error(err);
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
@@ -18,7 +18,6 @@
|
||||
var mkdirp = require('mkdirp');
|
||||
var copy = require('copy-to');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var os = require('os');
|
||||
|
||||
var version = require('../package.json').version;
|
||||
@@ -159,10 +158,7 @@ var config = {
|
||||
enablePrivate: false,
|
||||
|
||||
// registry scopes, if don't set, means do not support scopes
|
||||
scopes: [
|
||||
'@cnpm',
|
||||
'@cnpmtest'
|
||||
],
|
||||
scopes: [ '@cnpm', '@cnpmtest' ],
|
||||
|
||||
// some registry already have some private packages in global scope
|
||||
// but we want to treat them as scoped private packages,
|
||||
@@ -219,10 +215,20 @@ var config = {
|
||||
userService: null,
|
||||
};
|
||||
|
||||
// load config/config.js, everything in config.js will cover the same key in index.js
|
||||
var customConfig = path.join(root, 'config/config.js');
|
||||
if (fs.existsSync(customConfig)) {
|
||||
copy(require(customConfig)).override(config);
|
||||
if (process.env.NODE_ENV !== 'test') {
|
||||
// 1. try to load `$dataDir/config.js` first, not exists then goto 2.
|
||||
// 2. load config/config.js, everything in config.js will cover the same key in index.js
|
||||
var customConfig = path.join(dataDir, 'config');
|
||||
try {
|
||||
copy(require(customConfig)).override(config);
|
||||
} catch (err) {
|
||||
customConfig = path.join(root, 'config', 'config');
|
||||
try {
|
||||
copy(require(customConfig)).override(config);
|
||||
} catch (err) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mkdirp.sync(config.logdir);
|
||||
|
||||
@@ -146,10 +146,6 @@ SyncModuleWorker.prototype.start = function () {
|
||||
return;
|
||||
}
|
||||
|
||||
if (config.syncModel === 'none') {
|
||||
return;
|
||||
}
|
||||
|
||||
var arr = [];
|
||||
for (var i = 0; i < that.concurrency; i++) {
|
||||
arr.push(that.next(i));
|
||||
@@ -283,6 +279,10 @@ SyncModuleWorker.prototype.syncUser = function* () {
|
||||
};
|
||||
|
||||
SyncModuleWorker.prototype.next = function* (concurrencyId) {
|
||||
if (config.syncModel === 'none') {
|
||||
return this.finish();
|
||||
}
|
||||
|
||||
var name = this.names.shift();
|
||||
if (!name) {
|
||||
return setImmediate(this.finish.bind(this));
|
||||
|
||||
@@ -23,6 +23,9 @@ var config = require('./config');
|
||||
var workerPath = path.join(__dirname, 'worker.js');
|
||||
var syncPath = path.join(__dirname, 'sync');
|
||||
|
||||
console.log('Starting cnpmjs.org ...\ncluster: %s\nadmins: %j\nscopes: %j\nsourceNpmRegistry: %s',
|
||||
config.enableCluster, config.admins, config.scopes, config.sourceNpmRegistry);
|
||||
|
||||
if (config.enableCluster) {
|
||||
forkWorker();
|
||||
if (config.syncModel !== 'none') {
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
"status": "./bin/nodejsctl status",
|
||||
"stop": "./bin/nodejsctl stop"
|
||||
},
|
||||
"bin": {
|
||||
"cnpmjs.org": "bin/cli.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"agentkeepalive": "~1.2.0",
|
||||
"bluebird": "~2.9.6",
|
||||
@@ -18,10 +21,11 @@
|
||||
"co-defer": "~0.1.2",
|
||||
"co-gather": "~0.0.1",
|
||||
"co-sleep": "~0.0.1",
|
||||
"commander": "~2.6.0",
|
||||
"copy-to": "~2.0.1",
|
||||
"debug": "~2.1.1",
|
||||
"error-formater": "~1.0.3",
|
||||
"fs-cnpm": "~1.1.0",
|
||||
"fs-cnpm": "~1.2.0",
|
||||
"giturl": "~0.0.3",
|
||||
"graceful": "~1.0.0",
|
||||
"gravatar": "~1.1.0",
|
||||
@@ -42,6 +46,7 @@
|
||||
"semver": "~4.2.0",
|
||||
"sequelize": "~2.0.0-rc8",
|
||||
"thunkify-wrap": "~1.0.4",
|
||||
"treekill": "~1.0.0",
|
||||
"urllib": "~2.2.2",
|
||||
"utility": "~1.3.0",
|
||||
"xss": "~0.1.20"
|
||||
@@ -53,7 +58,6 @@
|
||||
"contributors": "*",
|
||||
"istanbul-harmony": "*",
|
||||
"jshint": "*",
|
||||
"koa-mock": "~1.1.4",
|
||||
"mm": "*",
|
||||
"mocha": "*",
|
||||
"node-dev": "*",
|
||||
|
||||
Reference in New Issue
Block a user