Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71452f692e | ||
|
|
c24526d7ff | ||
|
|
43dcd4b4f1 | ||
|
|
ff90c0f238 | ||
|
|
f85752e4bc | ||
|
|
4b20c13a4f | ||
|
|
ef61605e0c | ||
|
|
a5291d95dd | ||
|
|
9de10e791c | ||
|
|
1162ed95b0 | ||
|
|
6cdbc0b058 | ||
|
|
dc7239637d | ||
|
|
b735c9c15c | ||
|
|
417e19a330 | ||
|
|
40ab0929e1 | ||
|
|
6dabe60839 | ||
|
|
2680512c71 | ||
|
|
f444566a23 | ||
|
|
99cb110ee2 | ||
|
|
536704705c | ||
|
|
d919a81dae | ||
|
|
fe8100ea30 |
@@ -19,3 +19,4 @@ coverage/
|
||||
.DS_Store
|
||||
config/web_readme.md
|
||||
.dist/
|
||||
config/config.js
|
||||
|
||||
66
History.md
66
History.md
@@ -1,4 +1,34 @@
|
||||
|
||||
1.4.0 / 2014-08-20
|
||||
==================
|
||||
|
||||
* different version, different color badge, add version badge. fixed #427
|
||||
* add download and node version badge
|
||||
|
||||
1.3.2 / 2014-08-18
|
||||
==================
|
||||
|
||||
* remove unused eventproxy
|
||||
* add custom config in tools/sync_not_exist.js
|
||||
|
||||
1.3.1 / 2014-08-18
|
||||
==================
|
||||
|
||||
* add sync not exist tools, close [#424](https://github.com/cnpm/cnpmjs.org/issues/424)
|
||||
* use gittip instand of alipay. close [#425](https://github.com/cnpm/cnpmjs.org/issues/425)
|
||||
* update registry api doc
|
||||
|
||||
1.3.0 / 2014-08-11
|
||||
==================
|
||||
|
||||
* ignore config/config.js
|
||||
* Merge pull request [#421](https://github.com/cnpm/cnpmjs.org/issues/421) from cnpm/qn-cnpm
|
||||
* fix test case
|
||||
* use fs-cnpm
|
||||
* fix test
|
||||
* use qn-cnpm
|
||||
* bump cfork
|
||||
|
||||
1.2.2 / 2014-08-08
|
||||
==================
|
||||
|
||||
@@ -14,17 +44,17 @@
|
||||
|
||||
* show deprecated message
|
||||
* Sync deprecated field if it missing
|
||||
* Support $ cnpm deprecate [pkgname]@[version] "message". fixed #415
|
||||
* Support $ cnpm deprecate [pkgname]@[version] "message". fixed [#415](https://github.com/cnpm/cnpmjs.org/issues/415)
|
||||
|
||||
1.1.0 / 2014-08-07
|
||||
==================
|
||||
|
||||
* Add user to maintainers when publish. fixed #395
|
||||
* List all npm registry api. close #413
|
||||
* Add user to maintainers when publish. fixed [#395](https://github.com/cnpm/cnpmjs.org/issues/395)
|
||||
* List all npm registry api. close [#413](https://github.com/cnpm/cnpmjs.org/issues/413)
|
||||
* limit list since
|
||||
* change deps by "~"
|
||||
* use cfork to make sure worker fork and restart
|
||||
* handle master uncaughtException. fixed #403
|
||||
* handle master uncaughtException. fixed [#403](https://github.com/cnpm/cnpmjs.org/issues/403)
|
||||
|
||||
1.0.6 / 2014-08-02
|
||||
==================
|
||||
@@ -34,12 +64,12 @@
|
||||
1.0.5 / 2014-08-02
|
||||
==================
|
||||
|
||||
* unpublish pkg@version bug hotfix. fixed #400
|
||||
* unpublish pkg@version bug hotfix. fixed [#400](https://github.com/cnpm/cnpmjs.org/issues/400)
|
||||
|
||||
1.0.4 / 2014-08-01
|
||||
==================
|
||||
|
||||
* hotfix #399 use not exists
|
||||
* hotfix [#399](https://github.com/cnpm/cnpmjs.org/issues/399) use not exists
|
||||
|
||||
1.0.3 / 2014-08-01
|
||||
==================
|
||||
@@ -54,7 +84,7 @@
|
||||
1.0.1 / 2014-08-01
|
||||
==================
|
||||
|
||||
* Merge pull request #398 from cnpm/fix-auth
|
||||
* Merge pull request [#398](https://github.com/cnpm/cnpmjs.org/issues/398) from cnpm/fix-auth
|
||||
* hot fix auth error
|
||||
|
||||
1.0.0 / 2014-08-01
|
||||
@@ -85,7 +115,7 @@
|
||||
* remove session middleware
|
||||
* add DefaultUserService
|
||||
* check scopes in module.getAdapt
|
||||
* test public mode, fix some logic, close #382
|
||||
* test public mode, fix some logic, close [#382](https://github.com/cnpm/cnpmjs.org/issues/382)
|
||||
* move scope.js into publishable.js, add forcePublishWithScope
|
||||
* config.scopes not exist, means do not support scope
|
||||
* add assert scope middleware
|
||||
@@ -98,12 +128,12 @@
|
||||
0.8.6 / 2014-07-23
|
||||
==================
|
||||
|
||||
* show unpublished info on web package page. fixes #381
|
||||
* show unpublished info on web package page. fixes [#381](https://github.com/cnpm/cnpmjs.org/issues/381)
|
||||
|
||||
0.8.5 / 2014-07-22
|
||||
==================
|
||||
|
||||
* Only private package support default scoped. fixed #378
|
||||
* Only private package support default scoped. fixed [#378](https://github.com/cnpm/cnpmjs.org/issues/378)
|
||||
|
||||
0.8.4 / 2014-07-22
|
||||
==================
|
||||
@@ -124,20 +154,20 @@
|
||||
==================
|
||||
|
||||
* add more test cases
|
||||
* support default @org. close #376
|
||||
* support default @org. close [#376](https://github.com/cnpm/cnpmjs.org/issues/376)
|
||||
* hotfix redis init error
|
||||
|
||||
0.8.0 / 2014-07-21
|
||||
==================
|
||||
|
||||
* support "scoped" packages. close #352
|
||||
* support "scoped" packages. close [#352](https://github.com/cnpm/cnpmjs.org/issues/352)
|
||||
* use safe jsonp
|
||||
* Stop support old publish flow. fix #368
|
||||
* Stop support old publish flow. fix [#368](https://github.com/cnpm/cnpmjs.org/issues/368)
|
||||
* update SQLs
|
||||
* use sync_info and sync_error categories
|
||||
* add categories to loggers. fix #370
|
||||
* add categories to loggers. fix [#370](https://github.com/cnpm/cnpmjs.org/issues/370)
|
||||
* fix get latest tag always not exists bug
|
||||
* support `npm publish --tag beta`. fix #366
|
||||
* support `npm publish --tag beta`. fix [#366](https://github.com/cnpm/cnpmjs.org/issues/366)
|
||||
* use mini-logger and error-formater
|
||||
|
||||
0.7.0 / 2014-07-07
|
||||
@@ -145,7 +175,7 @@
|
||||
|
||||
* use module_maintainers on GET /pakcage/:name page
|
||||
* use new module_maintainers on GET /:name
|
||||
* admin user should never publish to other user's packages. fix #363
|
||||
* admin user should never publish to other user's packages. fix [#363](https://github.com/cnpm/cnpmjs.org/issues/363)
|
||||
* Add a new table for module-maintainers.
|
||||
* gravatar use https
|
||||
* support https
|
||||
@@ -160,8 +190,8 @@
|
||||
0.6.0 / 2014-06-16
|
||||
==================
|
||||
|
||||
* sync unpublished info. close #353
|
||||
* Delete not exists versions on sync worker. #353
|
||||
* sync unpublished info. close [#353](https://github.com/cnpm/cnpmjs.org/issues/353)
|
||||
* Delete not exists versions on sync worker. [#353](https://github.com/cnpm/cnpmjs.org/issues/353)
|
||||
|
||||
0.5.3 / 2014-06-13
|
||||
==================
|
||||
|
||||
1
Makefile
1
Makefile
@@ -16,6 +16,7 @@ pretest:
|
||||
@mysql -uroot -e 'CREATE DATABASE cnpmjs_test;'
|
||||
@mysql -uroot 'cnpmjs_test' < ./docs/db.sql
|
||||
@mysql -uroot 'cnpmjs_test' -e 'show tables;'
|
||||
@rm -rf .tmp/dist
|
||||
|
||||
test: install pretest
|
||||
@NODE_ENV=test ./node_modules/.bin/mocha \
|
||||
|
||||
37
README.md
37
README.md
@@ -6,17 +6,23 @@ cnpmjs.org
|
||||
[![Test coverage][coveralls-image]][coveralls-url]
|
||||
[![Gittip][gittip-image]][gittip-url]
|
||||
[![David deps][david-image]][david-url]
|
||||
[![node version][node-image]][node-url]
|
||||
[![npm download][download-image]][download-url]
|
||||
|
||||
[npm-image]: https://img.shields.io/npm/v/cnpmjs.org.svg?style=flat
|
||||
[npm-url]: https://npmjs.org/package/cnpmjs.org
|
||||
[travis-image]: https://img.shields.io/travis/cnpm/cnpmjs.org.svg?style=flat
|
||||
[npm-image]: http://cnpmjs.org/badge/v/cnpmjs.org.svg?style=flat-square
|
||||
[npm-url]: http://cnpmjs.org/package/cnpmjs.org
|
||||
[travis-image]: https://img.shields.io/travis/cnpm/cnpmjs.org.svg?style=flat-square
|
||||
[travis-url]: https://travis-ci.org/cnpm/cnpmjs.org
|
||||
[coveralls-image]: https://img.shields.io/coveralls/cnpm/cnpmjs.org.svg?style=flat
|
||||
[coveralls-image]: https://img.shields.io/coveralls/cnpm/cnpmjs.org.svg?style=flat-square
|
||||
[coveralls-url]: https://coveralls.io/r/cnpm/cnpmjs.org?branch=master
|
||||
[gittip-image]: https://img.shields.io/gittip/fengmk2.svg?style=flat
|
||||
[gittip-image]: https://img.shields.io/gittip/fengmk2.svg?style=flat-square
|
||||
[gittip-url]: https://www.gittip.com/fengmk2/
|
||||
[david-image]: https://img.shields.io/david/cnpm/cnpmjs.org.svg?style=flat
|
||||
[david-image]: https://img.shields.io/david/cnpm/cnpmjs.org.svg?style=flat-square
|
||||
[david-url]: https://david-dm.org/cnpm/cnpmjs.org
|
||||
[node-image]: https://img.shields.io/badge/node.js-%3E=_0.11-red.svg?style=flat-square
|
||||
[node-url]: http://nodejs.org/download/
|
||||
[download-image]: https://img.shields.io/npm/dm/cnpmjs.org.svg?style=flat-square
|
||||
[download-url]: https://npmjs.org/package/cnpmjs.org
|
||||
|
||||

|
||||
|
||||
@@ -48,6 +54,7 @@ to extend `npm` with more features(`sync` command, [gzip](https://github.com/npm
|
||||
And it easy to wrap for your own registry which build with `cnpmjs.org`.
|
||||
* **Compatible with NPM client**: you can use the origin NPM client with `cnpmjs.org`,
|
||||
only need to change the registry in config. Even include manual synchronization (through `install` command).
|
||||
* **Version badge**: base on [shields.io](http://shields.io/) 
|
||||
|
||||
## Getting Start
|
||||
|
||||
@@ -104,24 +111,6 @@ $ node --harmony_generators dispatch.js
|
||||
|
||||
Tips: make sure your code is following the [node-style-guide](https://github.com/felixge/node-style-guide).
|
||||
|
||||
## Authors
|
||||
|
||||
```bash
|
||||
$ git summary
|
||||
|
||||
project : cnpmjs.org
|
||||
repo age : 4 months ago
|
||||
commits : 472
|
||||
active : 167 days
|
||||
files : 104
|
||||
authors :
|
||||
272 fengmk2 57.6%
|
||||
195 dead_horse 41.3%
|
||||
2 4simple 0.4%
|
||||
2 Stanley Zheng 0.4%
|
||||
1 Alsotang 0.2%
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
(The MIT License)
|
||||
|
||||
@@ -15,11 +15,5 @@
|
||||
*/
|
||||
|
||||
var config = require('../config');
|
||||
var nfs = config.nfs;
|
||||
|
||||
if (!nfs) {
|
||||
// use qnfs by default
|
||||
nfs = require('./qnfs');
|
||||
}
|
||||
|
||||
module.exports = nfs;
|
||||
module.exports = config.nfs;
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
/*!
|
||||
* cnpmjs.org - common/qnfs.js
|
||||
*
|
||||
* Copyright(c) cnpmjs.org and other contributors.
|
||||
* MIT Licensed
|
||||
*
|
||||
* Authors:
|
||||
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var thunkify = require('thunkify-wrap');
|
||||
var qn = require('qn');
|
||||
var fs = require('fs');
|
||||
var config = require('../config');
|
||||
var client = qn.create(config.qn);
|
||||
|
||||
thunkify(client, ['delete', 'uploadFile', 'upload', 'download']);
|
||||
|
||||
exports._client = client;
|
||||
|
||||
/**
|
||||
* Upload file
|
||||
*
|
||||
* @param {String} filepath
|
||||
* @param {Object} options
|
||||
* - {String} key
|
||||
* - {Number} size
|
||||
*/
|
||||
exports.upload = function *(filepath, options) {
|
||||
try {
|
||||
yield client.delete(options.key);
|
||||
} catch (err) {
|
||||
// ignore error here
|
||||
}
|
||||
|
||||
var res = yield client.uploadFile(filepath, {
|
||||
key: options.key,
|
||||
size: options.size
|
||||
});
|
||||
var url = res && res[0] ? res[0].url : '';
|
||||
return { url: url };
|
||||
};
|
||||
|
||||
exports.uploadBuffer = function *(buf, options) {
|
||||
try {
|
||||
yield client.delete(options.key);
|
||||
} catch (err) {
|
||||
// ignore error here
|
||||
}
|
||||
|
||||
var res = yield client.upload(buf, {key: options.key});
|
||||
var url = res && res[0] ? res[0].url : '';
|
||||
return { url: url };
|
||||
};
|
||||
|
||||
exports.url = function (key) {
|
||||
return client.resourceURL(key);
|
||||
};
|
||||
|
||||
exports.download = function* (key, filepath, options) {
|
||||
var writeStream = fs.createWriteStream(filepath);
|
||||
yield client.download(key, {
|
||||
timeout: options.timeout,
|
||||
writeStream: writeStream
|
||||
});
|
||||
};
|
||||
|
||||
exports.remove = function *(key) {
|
||||
try {
|
||||
return yield client.delete(key);
|
||||
} catch (err) {
|
||||
if (err.name === 'QiniuFileNotExistsError') {
|
||||
return;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
@@ -126,14 +126,10 @@ var config = {
|
||||
// use for koa-limit module as storage
|
||||
redis: null,
|
||||
|
||||
// package tarball store in qn by default
|
||||
// qiniu cdn: http://www.qiniu.com/, it free for dev.
|
||||
qn: {
|
||||
accessKey: "5UyUq-l6jsWqZMU6tuQ85Msehrs3Dr58G-mCZ9rE",
|
||||
secretKey: "YaRsPKiYm4nGUt8mdz2QxeV5Q_yaUzVxagRuWTfM",
|
||||
bucket: "qiniu-sdk-test",
|
||||
domain: "http://qiniu-sdk-test.qiniudn.com",
|
||||
},
|
||||
// package tarball store in local filesystem by default
|
||||
nfs: require('fs-cnpm')({
|
||||
dir: path.join(root, '.tmp', 'dist')
|
||||
}),
|
||||
|
||||
// registry url name
|
||||
registryHost: 'r.cnpmjs.org',
|
||||
@@ -190,6 +186,9 @@ var config = {
|
||||
syncConcurrency: 1,
|
||||
// sync interval, default is 10 minutes
|
||||
syncInterval: '10m',
|
||||
|
||||
// badge subject on http://shields.io/
|
||||
badgeSubject: 'cnpm',
|
||||
};
|
||||
|
||||
// load config/config.js, everything in config.js will cover the same key in index.js
|
||||
|
||||
@@ -24,9 +24,9 @@ exports.total = function (name, callback) {
|
||||
name = null;
|
||||
}
|
||||
var end = moment();
|
||||
var start = end.clone().subtract('months', 1).startOf('month');
|
||||
var lastday = end.clone().subtract('days', 1).format('YYYY-MM-DD');
|
||||
var lastweekStart = end.clone().subtract('weeks', 1).startOf('week');
|
||||
var start = end.clone().subtract(1, 'months').startOf('month');
|
||||
var lastday = end.clone().subtract(1, 'days').format('YYYY-MM-DD');
|
||||
var lastweekStart = end.clone().subtract(1, 'weeks').startOf('week');
|
||||
var lastweekEnd = lastweekStart.clone().endOf('week').format('YYYY-MM-DD');
|
||||
var lastmonthEnd = start.clone().endOf('month').format('YYYY-MM-DD');
|
||||
var thismonthStart = end.clone().startOf('month').format('YYYY-MM-DD');
|
||||
|
||||
@@ -32,7 +32,7 @@ exports.show = function *() {
|
||||
total.instance_start_time = startTime;
|
||||
total.node_version = process.version;
|
||||
total.app_version = version;
|
||||
total.donate = 'https://me.alipay.com/imk2';
|
||||
total.donate = 'https://www.gittip.com/fengmk2';
|
||||
total.sync_model = config.syncModel;
|
||||
|
||||
this.body = total;
|
||||
|
||||
47
controllers/web/badge.js
Normal file
47
controllers/web/badge.js
Normal file
@@ -0,0 +1,47 @@
|
||||
/**!
|
||||
* cnpmjs.org - controllers/web/badge.js
|
||||
*
|
||||
* Copyright(c) fengmk2 and other contributors.
|
||||
* MIT Licensed
|
||||
*
|
||||
* Authors:
|
||||
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var config = require('../../config');
|
||||
var Module = require('../../proxy/module');
|
||||
|
||||
exports.version = function* (next) {
|
||||
var color = 'lightgrey';
|
||||
var version = 'invalid';
|
||||
var name = this.params[0];
|
||||
var latestTag = yield* Module.getTag(name, 'latest');
|
||||
if (latestTag) {
|
||||
version = latestTag.version;
|
||||
if (/^0\.0\./.test(version)) {
|
||||
// <0.1.0 & >=0.0.0
|
||||
color = 'red';
|
||||
} else if (/^0\./.test(version)) {
|
||||
// <1.0.0 & >=0.1.0
|
||||
color = 'green';
|
||||
} else {
|
||||
// >=1.0.0
|
||||
color = 'blue';
|
||||
}
|
||||
}
|
||||
|
||||
var url = 'https://img.shields.io/badge/' + config.badgeSubject + '-' + version + '-' + color + '.svg';
|
||||
if (this.querystring) {
|
||||
url += '?' + this.querystring;
|
||||
} else {
|
||||
url += '?style=flat-square';
|
||||
}
|
||||
|
||||
this.redirect(url);
|
||||
};
|
||||
@@ -161,6 +161,41 @@ exports.display = function* (next) {
|
||||
pkg.name = orginalName;
|
||||
}
|
||||
|
||||
// pkg.engines = {
|
||||
// "python": ">= 0.11.9",
|
||||
// "node": ">= 0.11.9",
|
||||
// "node1": ">= 0.8.9",
|
||||
// "node2": ">= 0.10.9",
|
||||
// "node3": ">= 0.6.9",
|
||||
// };
|
||||
if (pkg.engines) {
|
||||
for (var k in pkg.engines) {
|
||||
var engine = String(pkg.engines[k] || '').trim();
|
||||
var color = 'blue';
|
||||
if (k.indexOf('node') === 0) {
|
||||
color = 'yellowgreen';
|
||||
var version = /(\d+\.\d+\.\d+)/.exec(engine);
|
||||
if (version) {
|
||||
version = version[0];
|
||||
if (/^0\.11\.\d+/.test(version)) {
|
||||
color = 'red';
|
||||
} else if (/^0\.10\./.test(version) ||
|
||||
/^0\.12\./.test(version) ||
|
||||
/^0\.14\./.test(version) ||
|
||||
/^[^0]+\./.test(version)) {
|
||||
color = 'brightgreen';
|
||||
}
|
||||
}
|
||||
}
|
||||
pkg.engines[k] = {
|
||||
version: engine,
|
||||
title: k + ': ' + engine,
|
||||
badgeURL: 'https://img.shields.io/badge/' + encodeURIComponent(k) +
|
||||
'-' + encodeURIComponent(engine) + '-' + color + '.svg?style=flat-square',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
yield this.render('package', {
|
||||
title: 'Package - ' + pkg.name,
|
||||
package: pkg,
|
||||
|
||||
@@ -245,7 +245,9 @@ Content-Length: 2243
|
||||
}
|
||||
```
|
||||
|
||||
### Get a special version or tag package
|
||||
### ~~Get a special version or tag package~~
|
||||
|
||||
__deprecated__
|
||||
|
||||
```
|
||||
GET /:package/:tag_or_version
|
||||
@@ -505,6 +507,7 @@ Status: 201 Created
|
||||
### Remove one version from package
|
||||
|
||||
* Authentication required.
|
||||
* In any delete, note that __the version number still cannot be reused__.
|
||||
|
||||
```
|
||||
PUT /:package/-rev/:rev
|
||||
@@ -512,6 +515,8 @@ PUT /:package/-rev/:rev
|
||||
|
||||
#### Input
|
||||
|
||||
Remove that specific version from the versions hash in the `PUT` body.
|
||||
|
||||
Example for removing `0.0.1` version:
|
||||
|
||||
```json
|
||||
@@ -551,6 +556,25 @@ Status: 201 Created
|
||||
}
|
||||
```
|
||||
|
||||
### Remove all versions of a package
|
||||
|
||||
* Authentication required.
|
||||
* In any delete, note that __the version number still cannot be reused__.
|
||||
|
||||
```
|
||||
DELETE /:package/-rev/:rev
|
||||
```
|
||||
|
||||
#### Response
|
||||
|
||||
```json
|
||||
Status: 201 Created
|
||||
|
||||
{
|
||||
"ok": true
|
||||
}
|
||||
```
|
||||
|
||||
### Remove a tgz file from package
|
||||
|
||||
* Authentication required.
|
||||
|
||||
@@ -104,6 +104,16 @@ $(function () {
|
||||
});
|
||||
</script>
|
||||
|
||||
## Version Badge
|
||||
|
||||
Default style is `flat-square`.
|
||||
|
||||
Badge URL: `http://cnpmjs.org/badge/v/cnpmjs.org.svg` 
|
||||
|
||||
* `<0.1.0 & >=0.0.0`: 
|
||||
* `<1.0.0 & >=0.1.0`: 
|
||||
* `>=1.0.0`: 
|
||||
|
||||
## Usage
|
||||
|
||||
use our npm client [cnpm](https://github.com/cnpm/cnpm)(More suitable with cnpmjs.org and gzip support), you can get our client through npm:
|
||||
|
||||
12
package.json
12
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cnpmjs.org",
|
||||
"version": "1.2.2",
|
||||
"version": "1.4.0",
|
||||
"description": "Private npm registry and web for Enterprise, base on MySQL and Simple Store Service",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
@@ -11,7 +11,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"bytes": "~1.0.0",
|
||||
"cfork": "~1.0.1",
|
||||
"cfork": "~1.1.0",
|
||||
"cheerio": "~0.17.0",
|
||||
"co": "~3.1.0",
|
||||
"co-defer": "~0.1.0",
|
||||
@@ -24,11 +24,12 @@
|
||||
"debug": "~1.0.4",
|
||||
"error-formater": "~1.0.3",
|
||||
"eventproxy": "~0.3.1",
|
||||
"fs-cnpm": "~1.0.2",
|
||||
"giturl": "~0.0.3",
|
||||
"graceful": "~0.1.0",
|
||||
"gravatar": "~1.0.6",
|
||||
"humanize-number": "~0.0.2",
|
||||
"koa": "~0.9.0",
|
||||
"koa": "~0.10.0",
|
||||
"koa-limit": "~1.0.2",
|
||||
"koa-markdown": "~0.0.3",
|
||||
"koa-middlewares": "~1.2.0",
|
||||
@@ -38,12 +39,11 @@
|
||||
"mkdirp": "~0.5.0",
|
||||
"moment": "~2.8.1",
|
||||
"ms": "~0.6.2",
|
||||
"multiline": "~0.3.4",
|
||||
"multiline": "~1.0.0",
|
||||
"mysql": "~2.4.2",
|
||||
"nodemailer": "0.7.1",
|
||||
"qn": "~0.2.2",
|
||||
"ready": "~0.1.1",
|
||||
"redis": "~0.11.0",
|
||||
"redis": "~0.12.1",
|
||||
"semver": "~3.0.1",
|
||||
"thunkify-wrap": "~1.0.2",
|
||||
"utility": "~1.0.0"
|
||||
|
||||
@@ -762,3 +762,7 @@ exports.updateReadme = function* (id, readme) {
|
||||
data.package.readme = readme;
|
||||
return yield* exports.updatePackage(id, data.package);
|
||||
};
|
||||
|
||||
exports.getTag = function* (name, tag) {
|
||||
return yield mysql.queryOne(SELECT_TAG_SQL, [name, tag]);
|
||||
};
|
||||
|
||||
@@ -20,6 +20,7 @@ var user = require('../controllers/web/user');
|
||||
var sync = require('../controllers/sync');
|
||||
var total = require('../controllers/total');
|
||||
var dist = require('../controllers/web/dist');
|
||||
var badge = require('../controllers/web/badge');
|
||||
|
||||
function routes(app) {
|
||||
app.get('/total', total.show);
|
||||
@@ -51,6 +52,8 @@ function routes(app) {
|
||||
app.get('/_list/search/search', pkg.rangeSearch);
|
||||
|
||||
app.get(/^\/dist(\/.*)?/, dist.list);
|
||||
|
||||
app.get(/^\/badge\/v\/([@\w\-\.\/]+)\.svg$/, badge.version);
|
||||
}
|
||||
|
||||
module.exports = routes;
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
|
||||
var debug = require('debug')('cnpmjs.org:sync:sync_all');
|
||||
var eventproxy = require('eventproxy');
|
||||
var ms = require('ms');
|
||||
var utility = require('utility');
|
||||
var config = require('../config');
|
||||
|
||||
@@ -18,9 +18,8 @@ var config = require('../config');
|
||||
var Npm = require('../proxy/npm');
|
||||
var Module = require('../proxy/module');
|
||||
var Total = require('../proxy/total');
|
||||
var eventproxy = require('eventproxy');
|
||||
var SyncModuleWorker = require('../proxy/sync_module_worker');
|
||||
var debug = require('debug')('cnpmjs.org:sync:sync_hot');
|
||||
var debug = require('debug')('cnpmjs.org:sync:sync_exist');
|
||||
var utility = require('utility');
|
||||
var Status = require('./status');
|
||||
var ms = require('ms');
|
||||
|
||||
@@ -779,11 +779,10 @@ describe('controllers/registry/module.test.js', function () {
|
||||
});
|
||||
|
||||
describe('GET /:name/download/:filename', function () {
|
||||
it('should download a file with 302 redirect', function (done) {
|
||||
it('should download a file with 200', function (done) {
|
||||
request(app)
|
||||
.get('/cutter/download/cutter-0.0.2.tgz')
|
||||
.expect('Location', config.qn.domain + '/cutter/-/cutter-0.0.2.tgz')
|
||||
.expect(302, done);
|
||||
.get('/mk2testmodule/download/mk2testmodule-0.0.1.tgz')
|
||||
.expect(200, done);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -145,8 +145,7 @@ describe('controllers/registry/module/scope_package.test.js', function () {
|
||||
it('should download work', function (done) {
|
||||
request(app)
|
||||
.get('/@cnpm/test-scope-package/download/@cnpm/test-scope-package-0.0.2.tgz')
|
||||
.expect('Location', /\.tgz$/)
|
||||
.expect(302, done);
|
||||
.expect(200, done);
|
||||
});
|
||||
|
||||
describe('support adaptScope', function () {
|
||||
|
||||
93
test/controllers/web/badge.test.js
Normal file
93
test/controllers/web/badge.test.js
Normal file
@@ -0,0 +1,93 @@
|
||||
/*!
|
||||
* cnpmjs.org - test/controllers/web/badge.test.js
|
||||
*
|
||||
* Copyright(c) cnpmjs.org and other contributors.
|
||||
* MIT Licensed
|
||||
*
|
||||
* Authors:
|
||||
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var should = require('should');
|
||||
var request = require('supertest');
|
||||
var mm = require('mm');
|
||||
var path = require('path');
|
||||
var pedding = require('pedding');
|
||||
var mysql = require('../../../common/mysql');
|
||||
var app = require('../../../servers/web');
|
||||
var registry = require('../../../servers/registry');
|
||||
var pkg = require('../../../controllers/web/package');
|
||||
var utils = require('../../utils');
|
||||
var config = require('../../../config');
|
||||
|
||||
var fixtures = path.join(path.dirname(path.dirname(__dirname)), 'fixtures');
|
||||
|
||||
describe('controllers/web/badge.test.js', function () {
|
||||
before(function (done) {
|
||||
done = pedding(2, done);
|
||||
registry = registry.listen(0, done);
|
||||
app = app.listen(0, done);
|
||||
});
|
||||
|
||||
afterEach(mm.restore);
|
||||
|
||||
describe('GET /badge/v/:name.svg', function () {
|
||||
it('should show blue version on >=1.0.0 when package exists', function (done) {
|
||||
var pkg = utils.getPackage('badge-test-module', '1.0.1', utils.admin);
|
||||
request(registry)
|
||||
.put('/' + pkg.name)
|
||||
.set('authorization', utils.adminAuth)
|
||||
.send(pkg)
|
||||
.end(function (err) {
|
||||
should.not.exists(err);
|
||||
request(app)
|
||||
.get('/badge/v/badge-test-module.svg?style=flat-square')
|
||||
.expect('Location', 'https://img.shields.io/badge/cnpm-1.0.1-blue.svg?style=flat-square')
|
||||
.expect(302, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('should show green version on <1.0.0 & >=0.1.0 when package exists', function (done) {
|
||||
var pkg = utils.getPackage('badge-test-module', '0.1.0', utils.admin);
|
||||
request(registry)
|
||||
.put('/' + pkg.name)
|
||||
.set('authorization', utils.adminAuth)
|
||||
.send(pkg)
|
||||
.end(function (err) {
|
||||
should.not.exists(err);
|
||||
request(app)
|
||||
.get('/badge/v/badge-test-module.svg?style=flat-square')
|
||||
.expect('Location', 'https://img.shields.io/badge/cnpm-0.1.0-green.svg?style=flat-square')
|
||||
.expect(302, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('should show green version on <0.1.0 & >=0.0.0 when package exists', function (done) {
|
||||
var pkg = utils.getPackage('badge-test-module', '0.0.0', utils.admin);
|
||||
request(registry)
|
||||
.put('/' + pkg.name)
|
||||
.set('authorization', utils.adminAuth)
|
||||
.send(pkg)
|
||||
.end(function (err) {
|
||||
should.not.exists(err);
|
||||
request(app)
|
||||
.get('/badge/v/badge-test-module.svg?style=flat-square')
|
||||
.expect('Location', 'https://img.shields.io/badge/cnpm-0.0.0-red.svg?style=flat-square')
|
||||
.expect(302, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('should show invalid when package not exists', function (done) {
|
||||
request(app)
|
||||
.get('/badge/v/badge-test-module-not-exists.svg?style=flat')
|
||||
.expect('Location', 'https://img.shields.io/badge/cnpm-invalid-lightgrey.svg?style=flat')
|
||||
.expect(302, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -18,6 +18,8 @@ var should = require('should');
|
||||
var request = require('supertest');
|
||||
var pedding = require('pedding');
|
||||
var mm = require('mm');
|
||||
var fs = require('fs');
|
||||
var nfs = require('../../../common/nfs');
|
||||
var app = require('../../../servers/web');
|
||||
var Dist = require('../../../proxy/dist');
|
||||
|
||||
@@ -127,7 +129,7 @@ describe('controllers/web/dist.test.js', function () {
|
||||
url: '/dist/v0.10.28/SHASUMS.txt'
|
||||
};
|
||||
});
|
||||
|
||||
fs.writeFileSync(nfs._getpath('/dist/v0.10.28/SHASUMS.txt'), '6eff580cc8460741155d42ef1ef537961194443f');
|
||||
request(app)
|
||||
.get('/dist/v0.10.28/SHASUMS.txt')
|
||||
.expect(200)
|
||||
|
||||
@@ -16,34 +16,40 @@
|
||||
|
||||
var should = require('should');
|
||||
var Dist = require('../../proxy/dist');
|
||||
var fs = require('fs');
|
||||
var nfs = require('../../common/nfs');
|
||||
|
||||
describe('proxy/dist.test.js', function () {
|
||||
describe('savefile() and getfile', function () {
|
||||
it('should save and get /npm-versions.txt', function* () {
|
||||
var name = 'npm-versions.txt';
|
||||
var info = {
|
||||
name: 'npm-versions.txt',
|
||||
name: name,
|
||||
parent: '/',
|
||||
date: '15-Sep-2011 23:48',
|
||||
size: 1676,
|
||||
url: 'http://cnpmjs.org/dist/npm-versions.txt',
|
||||
url: name,
|
||||
sha1: '104731881047318810473188'
|
||||
};
|
||||
yield* Dist.savefile(info);
|
||||
fs.writeFileSync(nfs._getpath('npm-versions.txt'), 'npm version');
|
||||
var got = yield* Dist.getfile('/npm-versions.txt');
|
||||
should.exist(got);
|
||||
got.should.eql(info);
|
||||
});
|
||||
|
||||
it('should save and get /v1.0.0/npm-versions.txt', function* () {
|
||||
var name = 'v1.0.0/npm-versions.txt';
|
||||
var info = {
|
||||
name: 'npm-versions.txt',
|
||||
parent: '/v1.0.0/',
|
||||
date: '15-Sep-2011 23:48',
|
||||
size: 1676,
|
||||
url: 'http://cnpmjs.org/dist/v1.0.0/npm-versions.txt',
|
||||
url: 'v1.0.0/npm-versions.txt',
|
||||
sha1: '104731881047318810473188'
|
||||
};
|
||||
yield* Dist.savefile(info);
|
||||
fs.writeFileSync(nfs._getpath('npm-versions.txt'), 'npm version 1.0.0');
|
||||
var got = yield* Dist.getfile('/v1.0.0/npm-versions.txt');
|
||||
should.exist(got);
|
||||
got.should.eql(info);
|
||||
|
||||
83
tools/sync_not_exist.js
Normal file
83
tools/sync_not_exist.js
Normal file
@@ -0,0 +1,83 @@
|
||||
/*!
|
||||
* cnpmjs.org - tools/sync_not_exist.js
|
||||
*
|
||||
* Copyright(c) cnpmjs.org and other contributors.
|
||||
* MIT Licensed
|
||||
*
|
||||
* Authors:
|
||||
* dead_horse <dead_horse@qq.com> (http://deadhorse.me)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var debug = require('debug')('cnpmjs.org:tools:sync_not_exist');
|
||||
var SyncModuleWorker = require('../proxy/sync_module_worker');
|
||||
var thunkify = require('thunkify-wrap');
|
||||
var Module = require('../proxy/module');
|
||||
var config = require('../config');
|
||||
var Npm = require('../proxy/npm');
|
||||
var utility = require('utility');
|
||||
var co = require('co');
|
||||
|
||||
function subtraction(arrOne, arrTwo) {
|
||||
arrOne = arrOne || [];
|
||||
arrTwo = arrTwo || [];
|
||||
var map = {};
|
||||
var results = [];
|
||||
arrTwo.forEach(function (name) {
|
||||
map[name] = true;
|
||||
});
|
||||
arrOne.forEach(function (name) {
|
||||
!map[name] && results.push(name);
|
||||
});
|
||||
return results;
|
||||
}
|
||||
|
||||
function *sync(conf) {
|
||||
if (conf) {
|
||||
debug('load custom config');
|
||||
config.loadConfig(conf);
|
||||
}
|
||||
|
||||
var allExists = yield Module.listShort();
|
||||
var existPackages = allExists.map(function (p) {
|
||||
return p.name;
|
||||
});
|
||||
var allPackages = yield Npm.getShort();
|
||||
var packages = subtraction(allPackages, existPackages);
|
||||
if (!packages.length) {
|
||||
debug('no packages need be sync');
|
||||
return;
|
||||
}
|
||||
debug('Total %d packages to sync', packages.length);
|
||||
|
||||
var worker = new SyncModuleWorker({
|
||||
username: 'admin',
|
||||
name: packages,
|
||||
concurrency: config.syncConcurrency
|
||||
});
|
||||
worker.start();
|
||||
var end = thunkify.event(worker);
|
||||
yield end();
|
||||
|
||||
debug('All packages sync done, successes %d, fails %d',
|
||||
worker.successes.length, worker.fails.length);
|
||||
|
||||
return {
|
||||
successes: worker.successes,
|
||||
fails: worker.fails
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = function (config, callback) {
|
||||
co(sync(config))(callback);
|
||||
};
|
||||
|
||||
if (!module.parent) {
|
||||
console.log('[tools/sync_not_exist.js] start sync not exist modules');
|
||||
module.exports();
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
<div id="package">
|
||||
<h1>
|
||||
<%= package.name %>
|
||||
<img title="<%= package.version %>" src="/badge/v/<%= package.name %>.svg?style=flat-square">
|
||||
<small>
|
||||
<% if (package._publish_on_cnpm) { %>
|
||||
(Private package)
|
||||
@@ -76,9 +77,7 @@
|
||||
<tr>
|
||||
<th>Version</th>
|
||||
<td>
|
||||
<b>
|
||||
<%= package.version %>
|
||||
</b>
|
||||
<img title="<%= package.version %>" src="/badge/v/<%= package.name %>.svg?style=flat-square">
|
||||
<% if (package.fromNow) { %>
|
||||
last updated
|
||||
<%= package.fromNow %>
|
||||
@@ -89,11 +88,11 @@
|
||||
<tr>
|
||||
<th>Engines</th>
|
||||
<td>
|
||||
<ul>
|
||||
<% for (var k in package.engines) { %>
|
||||
<li><%= k %>: <%= package.engines[k] %></li>
|
||||
<% } %>
|
||||
</ul>
|
||||
<% for (var k in package.engines) {
|
||||
var engine = package.engines[k];
|
||||
%>
|
||||
<img title="<%= engine.title %>" src="<%- engine.badgeURL %>">
|
||||
<% } %>
|
||||
</td>
|
||||
</tr>
|
||||
<% } %>
|
||||
|
||||
Reference in New Issue
Block a user