Compare commits

..

2 Commits

Author SHA1 Message Date
Chen Yangjian
31294a819b fix: model init (#1626) 2021-03-02 10:52:32 +08:00
fengmk2
9d9b834488 feat: use leoric for the ORM solution
https://www.cyj.me/leoric/zh/
2021-03-02 09:49:06 +08:00
54 changed files with 259 additions and 1323 deletions

3
.eslintrc Normal file
View File

@@ -0,0 +1,3 @@
{
"extends": "eslint-config-egg"
}

1
.gitignore vendored
View File

@@ -30,3 +30,4 @@ config/web_readme.md
.tmp/
*.sqlite
run/

View File

@@ -1,7 +0,0 @@
node_modules/
coverage/
.tmp/
.git/
tools/
public/
test/

View File

@@ -1,95 +0,0 @@
{
// JSHint Default Configuration File (as on JSHint website)
// See http://jshint.com/docs/ for more details
"maxerr" : 50, // {int} Maximum error before stopping
// Enforcing
"bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.)
"camelcase" : false, // true: Identifiers must be in camelCase
"curly" : true, // true: Require {} for every new block or scope
"eqeqeq" : true, // true: Require triple equals (===) for comparison
"forin" : false, // true: Require filtering for..in loops with obj.hasOwnProperty()
"immed" : false, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());`
"indent" : false, // {int} Number of spaces to use for indentation
"latedef" : false, // true: Require variables/functions to be defined before being used
"newcap" : false, // true: Require capitalization of all constructor functions e.g. `new F()`
"noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee`
"noempty" : true, // true: Prohibit use of empty blocks
"nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment)
"plusplus" : false, // true: Prohibit use of `++` & `--`
"quotmark" : false, // Quotation mark consistency:
// false : do nothing (default)
// true : ensure whatever is used is consistent
// "single" : require single quotes
// "double" : require double quotes
"undef" : true, // true: Require all non-global variables to be declared (prevents global leaks)
"unused" : true, // true: Require all defined variables be used
"strict" : true, // true: Requires all functions run in ES5 Strict Mode
"trailing" : false, // true: Prohibit trailing whitespaces
"maxparams" : false, // {int} Max number of formal params allowed per function
"maxdepth" : false, // {int} Max depth of nested blocks (within functions)
"maxstatements" : false, // {int} Max number statements per function
"maxcomplexity" : false, // {int} Max cyclomatic complexity per function
"maxlen" : false, // {int} Max number of characters per line
// Relaxing
"asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons)
"boss" : true, // true: Tolerate assignments where comparisons would be expected
"debug" : false, // true: Allow debugger statements e.g. browser breakpoints.
"eqnull" : false, // true: Tolerate use of `== null`
"es5" : false, // true: Allow ES5 syntax (ex: getters and setters)
"esnext" : true, // true: Allow ES.next (ES6) syntax (ex: `const`)
"moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features)
// (ex: `for each`, multiple try/catch, function expression…)
"evil" : false, // true: Tolerate use of `eval` and `new Function()`
"expr" : true, // true: Tolerate `ExpressionStatement` as Programs
"funcscope" : false, // true: Tolerate defining variables inside control statements"
"globalstrict" : false, // true: Allow global "use strict" (also enables 'strict')
"iterator" : false, // true: Tolerate using the `__iterator__` property
"lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block
"laxbreak" : true, // true: Tolerate possibly unsafe line breakings
"laxcomma" : false, // true: Tolerate comma-first style coding
"loopfunc" : false, // true: Tolerate functions being defined in loops
"multistr" : true, // true: Tolerate multi-line strings
"proto" : false, // true: Tolerate using the `__proto__` property
"scripturl" : false, // true: Tolerate script-targeted URLs
"smarttabs" : false, // true: Tolerate mixed tabs/spaces when used for alignment
"shadow" : true, // true: Allows re-define variables later in code e.g. `var x=1; x=2;`
"sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation
"supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;`
"validthis" : true, // true: Tolerate using this in a non-constructor function
// Environments
"browser" : true, // Web Browser (window, document, etc)
"couch" : false, // CouchDB
"devel" : true, // Development/debugging (alert, confirm, etc)
"dojo" : false, // Dojo Toolkit
"jquery" : false, // jQuery
"mootools" : false, // MooTools
"node" : true, // Node.js
"nonstandard" : false, // Widely adopted globals (escape, unescape, etc)
"prototypejs" : false, // Prototype and Scriptaculous
"rhino" : false, // Rhino
"worker" : false, // Web Workers
"wsh" : false, // Windows Scripting Host
"yui" : false, // Yahoo User Interface
"noyield" : true, // allow generators without a yield
// Legacy
"nomen" : false, // true: Prohibit dangling `_` in variables
"onevar" : false, // true: Allow only one `var` statement per function
"passfail" : false, // true: Stop on first error
"white" : false, // true: Check against strict whitespace and indentation rules
// Custom Globals
"globals" : { // additional predefined global variables
// mocha
"describe": true,
"it": true,
"before": true,
"afterEach": true,
"beforeEach": true,
"after": true
}
}

View File

@@ -1,3 +0,0 @@
{
"notify": false
}

View File

@@ -1,10 +0,0 @@
language: node_js
node_js:
- '10'
- '12'
services:
- mysql
- postgresql
script: 'make test-travis-all'
after_script:
- 'npm i codecov && codecov'

View File

@@ -1,24 +1,3 @@
3.0.0-rc.44 / 2021-06-11
==================
**features**
* [[`a1e8a82`](https://github.com/cnpm/cnpmjs.org/commit/a1e8a8289276275b995d15b3c254fbdbace6dbae)] - feat: impl npm owner hooks (#1645) (killa <<killa123@126.com>>)
3.0.0-rc.43 / 2021-05-36
==================
**features**
* [[`a21aed0`](https://github.com/cnpm/cnpmjs.org/commit/a21aed08c5fe1ea09f4fda157ac3c12bd609781d)] - feat: impl sync to/from backup files (#1612) (killa <<killa123@126.com>>)
**fixes**
* [[`2245dc2`](https://github.com/cnpm/cnpmjs.org/commit/2245dc2967ec070b8bcc618ebfad0cd4cd297fb8)] - feat: impl accelerate request (#1637) (killa <<killa123@126.com>>)
3.0.0-rc.42 / 2021-04-30
==================
**features**
* [[`a21aed0`](https://github.com/cnpm/cnpmjs.org/commit/a21aed08c5fe1ea09f4fda157ac3c12bd609781d)] - feat: impl sync to/from backup files (#1612) (killa <<killa123@126.com>>)
3.0.0-rc.39 / 2021-01-14
==================

6
app/model/README.md Normal file
View File

@@ -0,0 +1,6 @@
# Model
## Test
- add `TRUNCATE` script on `test/.setup.js`.
- add test case on `test/app/model/*.test.js` for the new model, please follow `test/app/model/user.test.js` example.

24
app/model/user.js Normal file
View File

@@ -0,0 +1,24 @@
'use strict';
module.exports = (app, Model) => {
const { STRING, TEXT, BIGINT, BOOLEAN } = Model.DataTypes;
class User extends Model {}
User.init({
id: { type: BIGINT.UNSIGNED, autoIncrement: true, primaryKey: true },
name: { type: STRING(100), allowNull: false },
salt: { type: STRING(100), allowNull: false },
passwordSha: { type: STRING(100), allowNull: false },
ip: { type: STRING(64), allowNull: false },
roles: { type: STRING(200), allowNull: false, defaultValue: '[]' },
rev: { type: STRING(40), allowNull: false },
email: { type: STRING(400), allowNull: false },
json: { type: TEXT, allowNull: true },
isNpmUser: { type: BOOLEAN, allowNull: false, defaultValue: false, column: 'npm_user' },
}, {
table: 'user',
});
return User;
};

View File

@@ -5,8 +5,6 @@ var urllib = require('urllib');
var HttpAgent = require('agentkeepalive');
var HttpsAgent = require('agentkeepalive').HttpsAgent;
var config = require('../config');
var url = require('url');
var URL = require('url').URL;
var httpAgent;
var httpsAgent;
@@ -59,26 +57,5 @@ var client = urllib.create({
httpsAgent: httpsAgent
});
var request = urllib.HttpClient.prototype.request;
function getAccelerateUrl(url) {
const urlObj = typeof url === 'string' ? new URL(url) : url;
const newHost = config.accelerateHostMap && config.accelerateHostMap[urlObj.host];
if (newHost) {
urlObj.host = newHost;
}
return urlObj.toString();
}
client.request = function (requestUrl, options) {
const accelerateUrl = getAccelerateUrl(requestUrl);
options = Object.assign({}, options, {
formatRedirectUrl: function (from, to) {
return getAccelerateUrl(url.resolve(from, to));
}
});
return Reflect.apply(request, client, [ accelerateUrl, options ]);
};
module.exports = client;
module.exports.USER_AGENT = urllib.USER_AGENT;

17
config/config.default.js Normal file
View File

@@ -0,0 +1,17 @@
'use strict';
module.exports = () => {
const { env } = process;
return {
orm: {
delegate: 'orm',
client: env.CNPMJS_DATABASE_CLIENT || 'mysql',
database: env.CNPMJS_DATABASE_NAME || 'cnpmjs_dev',
host: env.CNPMJS_DATABASE_HOST || 'localhost',
port: env.CNPMJS_DATABASE_PORT || 3306,
user: env.CNPMJS_DATABASE_USER || 'root',
password: env.CNPMJS_DATABASE_PASSWORD || '',
},
};
};

View File

@@ -8,7 +8,7 @@ var os = require('os');
var utility = require('utility');
var version = require('../package.json').version;
var Nfs = require('fs-cnpm');
var root = path.dirname(__dirname);
var dataDir = path.join(process.env.HOME || root, '.cnpmjs.org');
@@ -16,11 +16,6 @@ var config = {
version: version,
dataDir: dataDir,
// overriding length should alter database table length
versionLen: 70, // semver max length
nameLen: 214, // name max length
tagLen: 70, // tag name max length
/**
* Cluster mode
*/
@@ -36,9 +31,6 @@ var config = {
bindingHost: '127.0.0.1', // only binding on 127.0.0.1 for local access
// default is ctx.protocol
protocol: '',
// When sync package, cnpm not know the access protocol.
// So should set manually
backupProtocol: 'http',
// debug mode
// if in debug mode, some middleware like limit wont load
@@ -125,7 +117,7 @@ var config = {
*/
database: {
db: 'cnpmjs',
db: 'cnpmjs_test',
username: 'root',
password: '',
@@ -167,7 +159,7 @@ var config = {
enableNpmAuditsProxy: true,
// package tarball store in local filesystem by default
nfs: new Nfs({
nfs: require('fs-cnpm')({
dir: path.join(dataDir, 'nfs')
}),
// if set true, will 302 redirect to `nfs.url(dist.key)`
@@ -227,8 +219,6 @@ var config = {
// exist: only sync exist modules
// all: sync all modules
syncModel: 'none', // 'none', 'all', 'exist'
// sync package.json/dist-tag.json to sync dir
syncBackupFiles: false,
syncConcurrency: 1,
// sync interval, default is 10 minutes
@@ -308,37 +298,20 @@ var config = {
enable: false,
connectOptions: null,
},
// custom format full package list
// change `GET /:name` request response body
// use on `controllers/registry/list.js`
formatCustomFullPackageInfoAndVersions: (ctx, packageInfo) => {
return packageInfo;
},
// custom format one package version
// change `GET /:name/:version` request response body
// use on `controllers/registry/show.js`
formatCustomOnePackageVersion: (ctx, packageVersion) => {
return packageVersion;
},
// registry download accelerate map
accelerateHostMap: {},
};
if (process.env.NODE_ENV === 'test') {
config.enableAbbreviatedMetadata = true;
config.customRegistryMiddlewares.push((app) => {
config.customRegistryMiddlewares.push(() => {
return function* (next) {
this.set('x-custom-middleware', 'true');
this.set('x-custom-app-models', typeof app.models.query === 'function' ? 'true' : 'false');
yield next;
};
});
config.customWebMiddlewares.push((app) => {
config.customWebMiddlewares.push(() => {
return function* (next) {
this.set('x-custom-web-middleware', 'true');
this.set('x-custom-web-app-models', typeof app.models.query === 'function' ? 'true' : 'false');
yield next;
};
});

6
config/plugin.js Normal file
View File

@@ -0,0 +1,6 @@
'use strict';
exports.orm = {
enable: true,
package: 'egg-orm',
};

View File

@@ -258,10 +258,6 @@ module.exports = function* list() {
info.bugs = pkg.bugs;
info.license = pkg.license;
if (typeof config.formatCustomFullPackageInfoAndVersions === 'function') {
info = config.formatCustomFullPackageInfoAndVersions(this, info);
}
debug('show module %s: %s, latest: %s', name, rev, latestMod.version);
this.jsonp = info;
// use faster etag

View File

@@ -78,8 +78,8 @@ module.exports = function* save(next) {
var versionPackage = pkg.versions[version];
var maintainers = versionPackage.maintainers;
var authorizeType = common.getAuthorizeType(this);
if (!maintainers) {
var authorizeType = common.getAuthorizeType(this);
if (authorizeType === common.AuthorizeType.BEARER) {
// With the token mode, pub lib with no maintainers
// make the maintainer to be puber
@@ -104,19 +104,17 @@ module.exports = function* save(next) {
// make sure user in auth is in maintainers
// should never happened in normal request
if (authorizeType !== common.AuthorizeType.BEARER) {
var m = maintainers.filter(function (maintainer) {
return maintainer.name === username;
});
if (m.length === 0) {
this.status = 403;
const error = '[maintainers_error] ' + username + ' does not in maintainer list';
this.body = {
error,
reason: error,
};
return;
}
var m = maintainers.filter(function (maintainer) {
return maintainer.name === username;
});
if (m.length === 0) {
this.status = 403;
const error = '[maintainers_error] ' + username + ' does not in maintainer list';
this.body = {
error,
reason: error,
};
return;
}
// TODO: add this info into some table

View File

@@ -1,7 +1,9 @@
'use strict';
var debug = require('debug')('cnpmjs.org:controllers:registry:package:show');
var semver = require('semver');
var packageService = require('../../../services/package');
var setDownloadURL = require('../../../lib/common').setDownloadURL;
var SyncModuleWorker = require('../../sync_module_worker');
var config = require('../../../config');
@@ -16,13 +18,40 @@ var config = require('../../../config');
module.exports = function* show() {
var name = this.params.name || this.params[0];
var tag = this.params.version || this.params[1];
var mod = yield packageService.showPackage(name, tag, this);
if (tag === '*') {
tag = 'latest';
}
var version = semver.valid(tag);
var range = semver.validRange(tag);
var mod;
if (version) {
mod = yield packageService.getModule(name, version);
} else if (range) {
mod = yield packageService.getModuleByRange(name, range);
} else {
mod = yield packageService.getModuleByTag(name, tag);
}
if (mod) {
if (typeof config.formatCustomOnePackageVersion === 'function') {
mod.package = config.formatCustomOnePackageVersion(this, mod.package);
setDownloadURL(mod.package, this);
mod.package._cnpm_publish_time = mod.publish_time;
mod.package.publish_time = mod.package.publish_time || mod.publish_time;
var rs = yield [
packageService.listMaintainers(name),
packageService.listModuleTags(name),
];
var maintainers = rs[0];
if (maintainers.length > 0) {
mod.package.maintainers = maintainers;
}
var tags = rs[1];
var distTags = {};
for (var i = 0; i < tags.length; i++) {
var t = tags[i];
distTags[t.tag] = t.version;
}
// show tags for npminstall faster download
mod.package['dist-tags'] = distTags;
this.jsonp = mod.package;
if (config.registryCacheControlHeader) {
this.set('cache-control', config.registryCacheControlHeader);
@@ -36,7 +65,7 @@ module.exports = function* show() {
// if not fond, sync from source registry
if (!this.allowSync) {
this.status = 404;
const error = '[not_exists] version not found: ' + tag;
const error = '[not_exists] version not found: ' + version;
this.jsonp = {
error,
reason: error,

View File

@@ -4,7 +4,6 @@ var debug = require('debug')('cnpmjs.org:controllers:registry:package:update');
var packageService = require('../../../services/package');
var userService = require('../../../services/user');
var config = require('../../../config');
var hook = require('../../../services/hook');
// PUT /:name/-rev/:rev
//
@@ -159,31 +158,6 @@ function* updateMaintainers() {
var r = yield packageService.updatePrivateModuleMaintainers(name, usernames);
debug('result: %j', r);
if (r.add && r.add.length) {
const envelope = {
event: 'package:owner',
name: name,
type: 'package',
version: null,
hookOwner: null,
payload: null,
change: null,
};
hook.trigger(envelope);
}
if (r.remove && r.remove.length) {
const envelope = {
event: 'package:owner-rm',
name: name,
type: 'package',
version: null,
hookOwner: null,
payload: null,
change: null,
};
hook.trigger(envelope);
}
this.status = 201;
this.body = {

View File

@@ -19,7 +19,6 @@ exports.sync = function* () {
var publish = this.query.publish === 'true';
var noDep = this.query.nodeps === 'true';
var syncUpstreamFirst = this.query.sync_upstream === 'true';
var syncFromBackupFile = this.query.sync_from_backup === 'true';
if (!config.sourceNpmRegistryIsCNpm) {
syncUpstreamFirst = false;
}
@@ -39,7 +38,6 @@ exports.sync = function* () {
publish: publish,
noDep: noDep,
syncUpstreamFirst: syncUpstreamFirst,
syncFromBackupFile: syncFromBackupFile,
};
var logId = yield SyncModuleWorker.sync(name, username, options);

View File

@@ -8,7 +8,6 @@ var thunkify = require('thunkify-wrap');
var EventEmitter = require('events').EventEmitter;
var util = require('util');
var fs = require('fs');
var mzFs = require('mz/fs');
var path = require('path');
var crypto = require('crypto');
var sleep = require('co-sleep');
@@ -53,7 +52,6 @@ function SyncModuleWorker(options) {
this.concurrency = options.concurrency || 1;
this._publish = options.publish === true; // _publish_on_cnpm
this.syncUpstreamFirst = options.syncUpstreamFirst;
this.syncFromBackupFile = options.syncFromBackupFile;
this.syncingNames = {};
this.nameMap = {};
@@ -166,7 +164,6 @@ SyncModuleWorker.prototype.start = function () {
}
yield arr;
that._saveLog();
yield that._saveBackupFiles();
}).catch(function (err) {
logger.error(err);
that._saveLog();
@@ -325,193 +322,7 @@ SyncModuleWorker.prototype.next = function* (concurrencyId) {
yield this.syncByName(concurrencyId, name, registry);
};
// TODO unimplement unpublish
SyncModuleWorker.prototype._syncByNameFromBackupFile = function* (concurrencyId, name, retryCount) {
const that = this;
this.syncingNames[name] = true;
this.log('----------------- Syncing %s -------------------', name);
// ignore private scoped package
if (common.isPrivateScopedPackage(name)) {
this.log('[c#%d] [%s] ignore sync private scoped %j package',
concurrencyId, name, config.scopes);
yield this._doneOne(concurrencyId, name, true);
return;
}
// validate if unpublish
const unpublished = yield validateUnpublish(name);
if (unpublished) {
this.log('[c#%d] [%s] package is unpublished skip sync',
concurrencyId, name);
yield this._doneOne(concurrencyId, name, true);
return;
}
let packageJsons;
let tags;
try {
const packageDir = common.getSyncPackageDir(name);
const packageDirFiles = yield nfs.list(packageDir);
const packageJsonFileNames = packageDirFiles.filter(fileName => common.isBackupPkgFile(fileName));
const distTagDir = common.getSyncTagDir(name);
const distTagDirFiles = yield nfs.list(distTagDir);
const distTagFileNames = distTagDirFiles.filter(fileName => common.isBackupTagFile(fileName));
const packageJsonRes = yield gather(packageJsonFileNames.map(function* (packageJsonFileName) {
const version = common.getVersionFromFileName(packageJsonFileName);
return yield readPackage(name, version);
}), 5);
packageJsons = packageJsonRes.map(({ isError, error, value}) => {
if (isError) {
error.message = '[sync] read package.json failed: ' + error.message;
throw error;
}
return value;
});
packageJsons = packageJsons.sort((a, b) => {
return a.publish_time - b.publish_time;
});
const tagRes = yield gather(distTagFileNames.map(function* (tagFileName) {
const tag = common.getTagNameFromFileName(tagFileName);
const version = yield readDistTag(name, tag);
return {
tag,
version,
};
}));
tags = tagRes.map(({ isError, error, value}) => {
if (isError) {
error.message = '[sync] read dist-tag failed: ' + error.message;
throw error;
}
return value;
});
} catch (err) {
if (retryCount < 3) {
this.log('[c#%d] [%s] retry from oss after 3s, err: %s, retryCount: %s',
concurrencyId, name, err.stack, retryCount);
yield sleep(3000);
yield this._syncByNameFromBackupFile(concurrencyId, name, retryCount + 1);
return;
}
this.log('[c#%s] [error] [%s] sync error: %s', concurrencyId, name, err.stack);
yield this._doneOne(concurrencyId, name, false);
return;
}
const firstPkg = packageJsons[0];
const lastPkg = packageJsons[packageJsons.length - 1];
const times = packageJsons.reduce((times, packageJson) => {
times[packageJson.version] = new Date(packageJson.publish_time);
return times;
}, {
modified: new Date(lastPkg.publish_time),
created: new Date(firstPkg.publish_time),
});
const distTags = tags.reduce((distTags, tag) => {
distTags[tag.tag] = tag.version;
return distTags;
}, {});
const versions = packageJsons.reduce((versions, packageJson) => {
versions[packageJson.version] = packageJson;
return versions;
}, {});
const pkg = {
name,
'dist-tags': distTags,
versions: versions,
time: times,
description: lastPkg.description,
maintainers: lastPkg.maintainers,
author: lastPkg.author,
repository: lastPkg.repository,
readme: lastPkg.readme,
readmeFilename: lastPkg.readmeFilename,
homepage: lastPkg.homepage,
bugs: lastPkg.bugs,
license: lastPkg.license,
};
let syncVersions;
try {
syncVersions = yield this._sync(name, pkg);
} catch (err) {
this.log('[c#%s] [error] [%s] sync error: %s', concurrencyId, name, err.stack);
yield this._doneOne(concurrencyId, name, false);
return;
}
// has new version
if (syncVersions.length > 0) {
this.updates.push(name);
}
this.log('[c#%d] [%s] synced success, %d versions: %s',
concurrencyId, name, syncVersions.length, syncVersions.join(', '));
yield this._doneOne(concurrencyId, name, true);
return syncVersions;
function* validateUnpublish(name) {
const filePath = common.getTarballFilepath(name, '', `unpublish-package.json`);
const cdnKey = common.getUnpublishFileKey(name);
let unpublishInfo;
try {
yield nfs.download(cdnKey, filePath);
const packageJSONFile = yield mzFs.readFile(filePath, 'utf8');
unpublishInfo = JSON.parse(packageJSONFile);
} catch (_) {
// ...
return false;
} finally {
fs.unlink(filePath, utility.noop);
}
that.log('[c#%s] get unpublish info', concurrencyId, name);
yield that._unpublished(name, unpublishInfo);
return true;
}
function* readPackage(name, version) {
const filePath = common.getTarballFilepath(name, version, `package-${version}.json`);
const packageJsonKey = common.getPackageFileCDNKey(name, version);
try {
yield nfs.download(packageJsonKey, filePath);
const packageJSONFile = yield mzFs.readFile(filePath, 'utf8');
console.log('file: ', filePath, packageJSONFile);
const packageJSON = JSON.parse(packageJSONFile);
return packageJSON;
} finally {
fs.unlink(filePath, utility.noop);
}
}
function* readDistTag(name, tag) {
const filePath = common.getTarballFilepath(name, '', `tag-${tag}.json`);
const packageJsonKey = common.getDistTagCDNKey(name, tag);
try {
yield nfs.download(packageJsonKey, filePath);
const version = yield mzFs.readFile(filePath, 'utf8');
return version;
} finally {
fs.unlink(filePath, utility.noop);
}
}
};
SyncModuleWorker.prototype.syncByName = function* (concurrencyId, name, registry, retryCount) {
if (this.syncFromBackupFile) {
yield this._syncByNameFromBackupFile(concurrencyId, name, retryCount);
return;
}
retryCount = retryCount || 0;
var that = this;
that.syncingNames[name] = true;
@@ -744,39 +555,36 @@ SyncModuleWorker.prototype._unpublished = function* (name, unpublishedInfo) {
var r = yield packageService.saveUnpublishedModule(name, unpublishedInfo);
this.log(' [%s] save unpublished info: %j to row#%s',
name, unpublishedInfo, r.id);
if (mods.length) {
yield [
packageService.removeModulesByName(name),
packageService.removeModuleTags(name),
];
var keys = [];
for (var i = 0; i < mods.length; i++) {
var row = mods[i];
var dist = row.package.dist;
var key = dist.key;
if (!key) {
key = urlparse(dist.tarball).pathname;
}
key && keys.push(key);
if (mods.length === 0) {
return;
}
yield [
packageService.removeModulesByName(name),
packageService.removeModuleTags(name),
];
var keys = [];
for (var i = 0; i < mods.length; i++) {
var row = mods[i];
var dist = row.package.dist;
var key = dist.key;
if (!key) {
key = urlparse(dist.tarball).pathname;
}
if (keys.length > 0) {
try {
yield keys.map(function (key) {
return nfs.remove(key);
});
} catch (err) {
// ignore error here
this.log(' [%s] delete nfs files: %j error: %s: %s',
name, keys, err.name, err.message);
}
}
this.log(' [%s] delete nfs files: %j success', name, keys);
key && keys.push(key);
}
if (config.syncBackupFiles) {
yield this._saveUnpublishFile(name, unpublishedInfo);
if (keys.length > 0) {
try {
yield keys.map(function (key) {
return nfs.remove(key);
});
} catch (err) {
// ignore error here
this.log(' [%s] delete nfs files: %j error: %s: %s',
name, keys, err.name, err.message);
}
}
this.log(' [%s] delete nfs files: %j success', name, keys);
};
SyncModuleWorker.prototype._sync = function* (name, pkg) {
@@ -1715,141 +1523,6 @@ SyncModuleWorker.prototype._syncOneVersion = function *(versionIndex, sourcePack
}
};
SyncModuleWorker.prototype._saveBackupFiles = function *() {
if (!config.syncBackupFiles) {
return;
}
const pkgNames = Object.keys(this.nameMap);
const that = this;
yield gather(pkgNames.map(function* (pkgName) {
yield that._saveBackupFile(pkgName);
}), 5);
};
SyncModuleWorker.prototype._saveBackupFile = function *(pkgName) {
const [ mods, tags ] = yield [
packageService.listModulesByName(pkgName, [ 'version' ]),
packageService.listModuleTags(pkgName),
];
const that = this;
yield gather(mods.map(function* (mod) {
yield that._savePackageJsonBackup(pkgName, mod.version);
}), 5);
yield gather(tags.map(function* (tag) {
yield that._saveDistTagBackup(pkgName, tag.tag, tag.version);
}), 5);
yield this._clearDeletedDistTags(pkgName, tags.map(t => t.tag));
};
SyncModuleWorker.prototype._saveUnpublishFile = function* (pkgName, pkg) {
const cdnKey = common.getUnpublishFileKey(pkgName);
const filePath = common.getTarballFilepath(pkgName, '', 'unpublish-package.json');
this.log('[%s] start save unpublish-package.json', pkgName);
const file = JSON.stringify(pkg);
yield mzFs.writeFile(filePath, file);
let shasum = crypto.createHash('sha1');
shasum.update(file);
shasum = shasum.digest('hex');
yield nfs.upload(filePath, {
key: cdnKey,
size: file.length,
shasum: shasum,
});
this.log('[%s:%s] save unpublish package.json backup success', pkgName);
};
SyncModuleWorker.prototype._savePackageJsonBackup = function *(pkgName, version) {
const cdnKey = common.getPackageFileCDNKey(pkgName, version);
const filePath = common.getTarballFilepath(pkgName, version, `package-${version}.json`);
this.log('[%s:%s] start backup package.json', pkgName, version);
// If package.json exists no need to sync
try {
yield nfs.download(cdnKey, filePath);
fs.unlink(filePath, utility.noop);
this.log('[%s:%s] package.json exits skip backup', pkgName, version);
// Download success, no need to sync
return;
} catch (_) {
// ...
}
// Version is from db, so mod can not be null
const mod = yield packageService.showPackage(pkgName, version, {
protocol: config.backupProtocol,
});
const file = JSON.stringify(mod.package);
yield mzFs.writeFile(filePath, file);
let shasum = crypto.createHash('sha1');
shasum.update(file);
shasum = shasum.digest('hex');
yield nfs.upload(filePath, {
key: cdnKey,
size: file.length,
shasum: shasum,
});
this.log('[%s:%s] package.json backup success', pkgName, version);
};
SyncModuleWorker.prototype._saveDistTagBackup = function *(pkgName, tag, version) {
const cdnKey = common.getDistTagCDNKey(pkgName, tag);
const filePath = common.getTarballFilepath(pkgName, '', `tag-${tag}.json`);
this.log('[%s:%s] start backup dist-tag.json', pkgName, tag);
let oldVersion;
try {
yield nfs.download(cdnKey, filePath);
oldVersion = yield mzFs.readFile(filePath, 'utf8');
fs.unlink(filePath, utility.noop);
} catch (_) {
// ...
}
this.log('[%s:%s] backup dist tag is %j current dist tag is %j', pkgName, tag, oldVersion, version);
if (oldVersion === version) {
this.log('[%s:%s] tag equal skip sync', pkgName, tag);
return;
}
this.log('[%s:%s] tag not equal start sync', pkgName, tag);
const file = version;
yield mzFs.writeFile(filePath, file);
let shasum = crypto.createHash('sha1');
shasum.update(file);
shasum = shasum.digest('hex');
yield nfs.upload(filePath, {
key: cdnKey,
size: file.length,
shasum: shasum,
});
this.log('[%s:%s] backup dist tag success', pkgName, tag);
};
SyncModuleWorker.prototype._clearDeletedDistTags = function *(pkgName, tagNames) {
const syncDir = common.getSyncTagDir(pkgName);
const backupDistTagFiless = yield nfs.list(syncDir);
const currentTagNames = new Set(tagNames);
const shouldDelTags = backupDistTagFiless.filter(tagFileName => {
const tagName = common.getTagNameFromFileName(tagFileName);
return (
// File is an dist-tag file
tagName
// tag is deleted
&& !currentTagNames.has(tagName)
);
});
this.log('[%s] current tags %j backup tags %j should delete tags %j', pkgName, tagNames, backupDistTagFiless, shouldDelTags);
const that = this;
yield shouldDelTags.map(function* (tagFileName) {
const filePath = path.join(syncDir, tagFileName);
that.log('[%s] delete tags %s', pkgName, filePath);
yield nfs.remove(filePath);
});
this.log('[%s] delete tags success', pkgName);
};
SyncModuleWorker.sync = function* (name, username, options) {
options = options || {};
var result = yield logService.create({name: name, username: username});
@@ -1861,7 +1534,6 @@ SyncModuleWorker.sync = function* (name, username, options) {
noDep: options.noDep,
publish: options.publish,
syncUpstreamFirst: options.syncUpstreamFirst,
syncFromBackupFile: options.syncFromBackupFile,
});
worker.start();
return result.id;

View File

@@ -81,7 +81,7 @@ CREATE TABLE IF NOT EXISTS `module` (
`gmt_modified` datetime NOT NULL COMMENT 'modified time',
`author` varchar(100) NOT NULL COMMENT 'module author',
`name` varchar(214) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'module name',
`version` varchar(70) NOT NULL COMMENT 'module version',
`version` varchar(30) NOT NULL COMMENT 'module version',
`description` longtext COMMENT 'module description',
`package` longtext CHARACTER SET utf8 COLLATE utf8_general_ci COMMENT 'package.json',
`dist_shasum` varchar(100) DEFAULT NULL COMMENT 'module dist SHASUM',
@@ -104,7 +104,7 @@ CREATE TABLE IF NOT EXISTS `module` (
-- ALTER TABLE `module`
-- CHANGE `author` `author` varchar(100) NOT NULL COMMENT 'module author',
-- CHANGE `name` `name` varchar(214) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'module name',
-- CHANGE `version` `version` varchar(70) NOT NULL COMMENT 'module version',
-- CHANGE `version` `version` varchar(30) NOT NULL COMMENT 'module version',
-- CHANGE `description` `description` longtext COMMENT 'module description',
-- CHANGE `package` `package` longtext CHARACTER SET utf8 COLLATE utf8_general_ci COMMENT 'package.json',
-- CHANGE `dist_shasum` `dist_shasum` varchar(100) DEFAULT NULL COMMENT 'module dist SHASUM',
@@ -117,7 +117,7 @@ CREATE TABLE IF NOT EXISTS `module_abbreviated` (
`gmt_create` datetime NOT NULL COMMENT 'create time',
`gmt_modified` datetime NOT NULL COMMENT 'modified time',
`name` varchar(214) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'module name',
`version` varchar(70) NOT NULL COMMENT 'module version',
`version` varchar(30) NOT NULL COMMENT 'module version',
`package` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT 'the abbreviated metadata',
`publish_time` bigint(20) unsigned COMMENT 'the publish time',
PRIMARY KEY (`id`),
@@ -135,7 +135,7 @@ CREATE TABLE IF NOT EXISTS `package_readme` (
`gmt_modified` datetime NOT NULL COMMENT 'modified time',
`name` varchar(214) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'module name',
`readme` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT 'the latest version readme',
`version` varchar(70) NOT NULL COMMENT 'module version',
`version` varchar(30) NOT NULL COMMENT 'module version',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_name` (`name`),
KEY `idx_gmt_modified` (`gmt_modified`)
@@ -164,8 +164,8 @@ CREATE TABLE IF NOT EXISTS `tag` (
`gmt_create` datetime NOT NULL COMMENT 'create time',
`gmt_modified` datetime NOT NULL COMMENT 'modified time',
`name` varchar(214) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'module name',
`tag` varchar(70) NOT NULL COMMENT 'tag name',
`version` varchar(70) NOT NULL COMMENT 'module version',
`tag` varchar(30) NOT NULL COMMENT 'tag name',
`version` varchar(30) NOT NULL COMMENT 'module version',
`module_id` bigint(20) unsigned NOT NULL COMMENT 'module id',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_name` (`name`, `tag`),

View File

@@ -229,7 +229,6 @@ var config = {
// global hook function: function* (envelope) {}
// envelope format please see https://github.com/npm/registry/blob/master/docs/hooks/hooks-payload.md#payload
globalHook: null,
accelerateHostMap: {},
};
if (process.env.NODE_ENV !== 'test') {

View File

@@ -1,5 +1,17 @@
/**!
* Copyright(c) cnpmjs.org and other contributors.
* MIT Licensed
*
* Authors:
* dead_horse <dead_horse@qq.com> (http://deadhorse.me)
*/
'use strict';
/**
* Module dependencies.
*/
var config = require('./config');
exports.loadConfig = config.loadConfig;

View File

@@ -26,46 +26,6 @@ exports.getCDNKey = function (name, filename) {
return '/' + name + '/-/' + filename;
};
exports.getUnpublishFileKey = function (name) {
return `/${name}/sync/unpublish/unpublish-package.json`;
};
exports.getPackageFileCDNKey = function (name, version) {
return `/${name}/sync/packages/package-${version}.json`;
};
exports.getDistTagCDNKey = function (name, tag) {
return `/${name}/sync/tags/tag-${tag}.json`;
};
exports.getSyncTagDir = function (name) {
return `${name}/sync/tags/`;
};
exports.getSyncPackageDir = function (name) {
return `${name}/sync/packages/`;
};
const TAG_NAME_REG = /^tag-(.+)\.json$/;
exports.getTagNameFromFileName = function (fileName) {
const res = fileName.match(TAG_NAME_REG);
return res && res[1];
};
exports.isBackupTagFile = function (fileName) {
return TAG_NAME_REG.test(fileName);
};
const PACKAGE_NAME_REG = /^package-(.+)\.json$/;
exports.getVersionFromFileName = function (fileName) {
const res = fileName.match(PACKAGE_NAME_REG);
return res && res[1];
};
exports.isBackupPkgFile = function (fileName) {
return PACKAGE_NAME_REG.test(fileName);
};
exports.setDownloadURL = function (pkg, ctx, host) {
if (pkg.dist) {
host = host || config.registryHost || ctx.host;

View File

@@ -56,12 +56,10 @@
// KEY `idx_date` (`date`)
// ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='module download total info';
const config = require('../config');
module.exports = function (sequelize, DataTypes) {
return sequelize.define('DownloadTotal', {
name: {
type: DataTypes.STRING(config.nameLen),
type: DataTypes.STRING(214),
allowNull: false,
comment: 'module name',
},

View File

@@ -1,5 +1,19 @@
/**!
* cnpmjs.org - models/module.js
*
* Copyright(c) fengmk2 and other contributors.
* MIT Licensed
*
* Authors:
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
*/
'use strict';
/**
* Module dependencies.
*/
/*
CREATE TABLE IF NOT EXISTS `module` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'primary key',
@@ -7,7 +21,7 @@ CREATE TABLE IF NOT EXISTS `module` (
`gmt_modified` datetime NOT NULL COMMENT 'modified time',
`author` varchar(100) NOT NULL COMMENT 'module author',
`name` varchar(214) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'module name',
`version` varchar(70) NOT NULL COMMENT 'module version',
`version` varchar(30) NOT NULL COMMENT 'module version',
`description` longtext COMMENT 'module description',
`package` longtext CHARACTER SET utf8 COLLATE utf8_general_ci COMMENT 'package.json',
`dist_shasum` varchar(100) DEFAULT NULL COMMENT 'module dist SHASUM',
@@ -21,7 +35,6 @@ CREATE TABLE IF NOT EXISTS `module` (
KEY `idx_author` (`author`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='module info';
*/
const config = require('../config');
module.exports = function (sequelize, DataTypes) {
return sequelize.define('Module', {
@@ -31,12 +44,12 @@ module.exports = function (sequelize, DataTypes) {
comment: 'first maintainer name'
},
name: {
type: DataTypes.STRING(config.nameLen),
type: DataTypes.STRING(214),
allowNull: false,
comment: 'module name'
},
version: {
type: DataTypes.STRING(config.versionLen),
type: DataTypes.STRING(30),
allowNull: false,
comment: 'module version'
},

View File

@@ -6,7 +6,7 @@ CREATE TABLE IF NOT EXISTS `module_abbreviated` (
`gmt_create` datetime NOT NULL COMMENT 'create time',
`gmt_modified` datetime NOT NULL COMMENT 'modified time',
`name` varchar(214) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'module name',
`version` varchar(70) NOT NULL COMMENT 'module version',
`version` varchar(30) NOT NULL COMMENT 'module version',
`package` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT 'the abbreviated metadata',
`publish_time` bigint(20) unsigned COMMENT 'the publish time',
PRIMARY KEY (`id`),
@@ -16,17 +16,15 @@ CREATE TABLE IF NOT EXISTS `module_abbreviated` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='module abbreviated info';
*/
const config = require('../config');
module.exports = function (sequelize, DataTypes) {
return sequelize.define('ModuleAbbreviated', {
name: {
type: DataTypes.STRING(config.nameLen),
type: DataTypes.STRING(214),
allowNull: false,
comment: 'module name'
},
version: {
type: DataTypes.STRING(config.versionLen),
type: DataTypes.STRING(30),
allowNull: false,
comment: 'module version'
},

View File

@@ -19,18 +19,17 @@ CREATE TABLE IF NOT EXISTS `module_deps` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'primary key',
`gmt_create` datetime NOT NULL COMMENT 'create time',
`name` varchar(214) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'module name',
`deps` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'which module depend on this module',
`deps` varchar(214) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'which module depend on this module',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_name_deps` (`name`,`deps`),
KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='module deps';
*/
const config = require('../config');
module.exports = function (sequelize, DataTypes) {
return sequelize.define('ModuleDependency', {
name: {
type: DataTypes.STRING(config.nameLen),
type: DataTypes.STRING(214),
allowNull: false,
comment: 'module name',
},

View File

@@ -26,7 +26,6 @@ CREATE TABLE IF NOT EXISTS `module_keyword` (
KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='module keyword';
*/
const config = require('../config');
module.exports = function (sequelize, DataTypes) {
return sequelize.define('ModuleKeyword', {
@@ -36,7 +35,7 @@ module.exports = function (sequelize, DataTypes) {
comment: 'keyword',
},
name: {
type: DataTypes.STRING(config.nameLen),
type: DataTypes.STRING(214),
allowNull: false,
comment: 'module name',
},

View File

@@ -26,7 +26,6 @@
KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='module sync log';
*/
const config = require('../config');
module.exports = function (sequelize, DataTypes) {
return sequelize.define('ModuleLog', {
@@ -36,7 +35,7 @@ module.exports = function (sequelize, DataTypes) {
comment: 'user name'
},
name: {
type: DataTypes.STRING(config.nameLen),
type: DataTypes.STRING(214),
allowNull: false,
comment: 'module name',
},

View File

@@ -25,7 +25,6 @@ CREATE TABLE IF NOT EXISTS `module_maintainer` (
KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='private module maintainers';
*/
const config = require('../config');
module.exports = function (sequelize, DataTypes) {
return sequelize.define('ModuleMaintainer', {
@@ -35,7 +34,7 @@ module.exports = function (sequelize, DataTypes) {
comment: 'user name'
},
name: {
type: DataTypes.STRING(config.nameLen),
type: DataTypes.STRING(214),
allowNull: false,
comment: 'module name',
}

View File

@@ -25,7 +25,6 @@ CREATE TABLE IF NOT EXISTS `module_star` (
KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='module star';
*/
const config = require('../config');
module.exports = function (sequelize, DataTypes) {
return sequelize.define('ModuleStar', {
@@ -35,7 +34,7 @@ module.exports = function (sequelize, DataTypes) {
comment: 'user name'
},
name: {
type: DataTypes.STRING(config.nameLen),
type: DataTypes.STRING(214),
allowNull: false,
comment: 'module name',
}

View File

@@ -28,12 +28,11 @@ CREATE TABLE IF NOT EXISTS `module_unpublished` (
KEY `idx_gmt_modified` (`gmt_modified`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='module unpublished info';
*/
const config = require('../config');
module.exports = function (sequelize, DataTypes) {
return sequelize.define('ModuleUnpublished', {
name: {
type: DataTypes.STRING(config.nameLen),
type: DataTypes.STRING(214),
allowNull: false,
comment: 'module name',
},

View File

@@ -25,7 +25,6 @@ CREATE TABLE IF NOT EXISTS `npm_module_maintainer` (
KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='npm original module maintainers';
*/
const config = require('../config');
module.exports = function (sequelize, DataTypes) {
return sequelize.define('NpmModuleMaintainer', {
@@ -35,7 +34,7 @@ module.exports = function (sequelize, DataTypes) {
comment: 'user name'
},
name: {
type: DataTypes.STRING(config.nameLen),
type: DataTypes.STRING(214),
allowNull: false,
comment: 'module name',
}

View File

@@ -7,23 +7,22 @@ CREATE TABLE IF NOT EXISTS `package_readme` (
`gmt_modified` datetime NOT NULL COMMENT 'modified time',
`name` varchar(214) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'module name',
`readme` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT 'the latest version readme',
`version` varchar(70) NOT NULL COMMENT 'module version',
`version` varchar(30) NOT NULL COMMENT 'module version',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_name` (`name`),
KEY `idx_gmt_modified` (`gmt_modified`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='package latest readme';
*/
const config = require('../config');
module.exports = function (sequelize, DataTypes) {
return sequelize.define('PackageReadme', {
name: {
type: DataTypes.STRING(config.nameLen),
type: DataTypes.STRING(214),
allowNull: false,
comment: 'module name'
},
version: {
type: DataTypes.STRING(config.versionLen),
type: DataTypes.STRING(30),
allowNull: false,
comment: 'module latest version'
},

View File

@@ -20,30 +20,29 @@ CREATE TABLE IF NOT EXISTS `tag` (
`gmt_create` datetime NOT NULL COMMENT 'create time',
`gmt_modified` datetime NOT NULL COMMENT 'modified time',
`name` varchar(214) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'module name',
`tag` varchar(70) NOT NULL COMMENT 'tag name',
`version` varchar(70) NOT NULL COMMENT 'module version',
`tag` varchar(30) NOT NULL COMMENT 'tag name',
`version` varchar(30) NOT NULL COMMENT 'module version',
`module_id` bigint(20) unsigned NOT NULL COMMENT 'module id',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_name` (`name`, `tag`),
KEY `idx_gmt_modified` (`gmt_modified`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='module tag';
*/
const config = require('../config');
module.exports = function (sequelize, DataTypes) {
return sequelize.define('Tag', {
name: {
type: DataTypes.STRING(config.nameLen),
type: DataTypes.STRING(214),
allowNull: false,
comment: 'module name',
},
tag: {
type: DataTypes.STRING(config.tagLen),
type: DataTypes.STRING(30),
allowNull: false,
comment: 'tag name',
},
version: {
type: DataTypes.STRING(config.versionLen),
type: DataTypes.STRING(30),
allowNull: false,
comment: 'module version',
},

View File

@@ -31,12 +31,11 @@
// -- init `total` count
// INSERT INTO total(name, gmt_modified) VALUES('total', now())
// ON DUPLICATE KEY UPDATE gmt_modified=now();
const config = require('../config');
module.exports = function (sequelize, DataTypes) {
return sequelize.define('Total', {
name: {
type: DataTypes.STRING(config.nameLen),
type: DataTypes.STRING(214),
primaryKey: true,
comment: 'total name'
},

View File

@@ -1,12 +1,13 @@
{
"name": "cnpmjs.org",
"version": "3.0.0-rc.44",
"version": "4.0.0",
"description": "Private npm registry and web for Enterprise, base on MySQL and Simple Store Service",
"main": "index.js",
"scripts": {
"dev": "DEBUG=cnpm* node dispatch.js",
"test": "make jshint && make test",
"test-local": "make test",
"lint": "eslint app config test/app/",
"dev": "egg-bin dev",
"test": "TESTS=test/app/**/*/user.test.js egg-bin test",
"test-model": "TESTS=test/app/model/**/user.test.js egg-bin test",
"start": "./bin/nodejsctl start && cp History.md docs/web/history.md",
"status": "./bin/nodejsctl status",
"stop": "./bin/nodejsctl stop"
@@ -15,7 +16,6 @@
"cnpmjs.org": "bin/cli.js"
},
"dependencies": {
"agentkeepalive": "^4.0.0",
"await-event": "^2.1.0",
"bytes": "^2.5.0",
"cfork": "^1.6.1",
@@ -27,8 +27,10 @@
"commander": "^2.11.0",
"copy-to": "^2.0.1",
"debug": "^3.0.0",
"egg": "^2.29.3",
"egg-orm": "^1.1.1",
"error-formater": "^1.0.3",
"fs-cnpm": "^2.1.0",
"fs-cnpm": "^1.2.0",
"giturl": "^1.0.0",
"graceful": "^1.0.1",
"gravatar": "^1.6.0",
@@ -76,32 +78,21 @@
"autod": "*",
"chunkstream": "*",
"contributors": "*",
"intelli-espower-loader": "^1.0.1",
"istanbul": "*",
"jshint": "*",
"mm": "*",
"mocha": "3",
"node-dev": "*",
"pedding": "*",
"pg": "5",
"pg-hstore": "2",
"power-assert": "^1.4.2",
"should": "8",
"sqlite3": "*",
"supertest": "2",
"thunk-mocha": "1"
"egg-bin": "^4.15.0",
"egg-mock": "^4.0.1",
"eslint": "^7.21.0",
"eslint-config-egg": "^9.0.0"
},
"homepage": "https://github.com/cnpm/cnpmjs.org",
"repository": {
"type": "git",
"url": "git://github.com/cnpm/cnpmjs.org.git",
"web": "https://github.com/cnpm/cnpmjs.org"
"url": "git://github.com/cnpm/cnpmjs.org.git"
},
"bugs": {
"url": "https://github.com/cnpm/cnpmjs.org/issues"
},
"publishConfig": {
"tag": "latest-3"
"tag": "latest-4"
},
"keywords": [
"cnpmjs.org",
@@ -113,7 +104,7 @@
"engines": {
"node": ">= 8.0.0"
},
"author": [
"authors": [
"fengmk2 <fengmk2@gmail.com> (http://fengmk2.com)",
"dead_horse <dead_horse@qq.com> (http://deadhorse.me)"
],

View File

@@ -16,7 +16,6 @@ var block = require('../middleware/block');
var auth = require('../middleware/auth');
var staticCache = require('../middleware/static');
var notFound = require('../middleware/registry_not_found');
var models = require('../models');
var cors = require('kcors');
var proxyToNpm = require('../middleware/proxy_to_npm');
var maxrequests = require('koa-maxrequests');
@@ -53,7 +52,6 @@ app.use(notFound);
app.use(conditional());
app.use(etag());
app.models = models;
for (const middleware of config.customRegistryMiddlewares) {
app.use(middleware(app));
}

View File

@@ -17,7 +17,6 @@ var auth = require('../middleware/auth');
var proxyToNpm = require('../middleware/proxy_to_npm');
var routes = require('../routes/web');
var config = require('../config');
var models = require('../models');
var jsonp = require('koa-safe-jsonp');
var path = require('path');
var http = require('http');
@@ -43,8 +42,6 @@ if (config.pagemock) {
}));
}
// add app.models, let middleware can access models ref
app.models = models;
for (const mw of config.customWebMiddlewares) {
app.use(mw(app));
}

View File

@@ -1,10 +1,8 @@
'use strict';
var os = require('os');
var semver = require('semver');
var models = require('../models');
var common = require('./common');
var libCommon = require('../lib/common');
var config = require('../config');
var Tag = models.Tag;
var User = models.User;
@@ -543,23 +541,6 @@ exports.removeModulesByNameAndVersions = function* (name, versions) {
// tags
exports.addModuleTag = function* (name, tag, version) {
if (name.length > config.nameLen
|| tag.length > config.tagLen
|| version.length > config.versionLen) {
let errorMsg = 'addModuleTag Error:';
if (name.length > config.nameLen) {
errorMsg = `${errorMsg} length of name(${name}) > ${config.nameLen}${os.EOL}`;
}
if (tag.length > config.tagLen) {
errorMsg = `${errorMsg} length of tag(${tag}) > ${config.tagLen}${os.EOL}`;
}
if (version.length > config.versionLen) {
errorMsg = `${errorMsg} length of version(${version}) > ${config.versionLen}${os.EOL}`;
}
console.info('errorMsg: ', errorMsg);
throw new Error(errorMsg);
}
var mod = yield exports.getModule(name, version);
if (!mod) {
return null;
@@ -884,45 +865,3 @@ exports.saveUnpublishedModule = function* (name, pkg) {
exports.getUnpublishedModule = function* (name) {
return yield ModuleUnpublished.findByName(name);
};
exports.showPackage = function* (name, tag, ctx) {
if (tag === '*') {
tag = 'latest';
}
if (tag === '*') {
tag = 'latest';
}
var version = semver.valid(tag);
var range = semver.validRange(tag);
var mod;
if (version) {
mod = yield exports.getModule(name, version);
} else if (range) {
mod = yield exports.getModuleByRange(name, range);
} else {
mod = yield exports.getModuleByTag(name, tag);
}
if (mod) {
libCommon.setDownloadURL(mod.package, ctx || {});
mod.package._cnpm_publish_time = mod.publish_time;
mod.package.publish_time = mod.package.publish_time || mod.publish_time;
var rs = yield [
exports.listMaintainers(name),
exports.listModuleTags(name),
];
var maintainers = rs[0];
if (maintainers.length > 0) {
mod.package.maintainers = maintainers;
}
var tags = rs[1];
var distTags = {};
for (var i = 0; i < tags.length; i++) {
var t = tags[i];
distTags[t.tag] = t.version;
}
// show tags for npminstall faster download
mod.package['dist-tags'] = distTags;
return mod;
}
};

11
test/.setup.js Normal file
View File

@@ -0,0 +1,11 @@
'use strict';
const { app } = require('egg-mock/bootstrap');
before(async () => {
await app.orm.sync();
});
beforeEach(async () => {
await app.orm.User.driver.query('TRUNCATE user');
});

View File

@@ -0,0 +1,33 @@
'use strict';
const { app, assert } = require('egg-mock/bootstrap');
describe('test/app/model/user.test.js', () => {
describe('ctx.orm.User, app.orm.User', () => {
it('should work', async () => {
const ctx = app.mockContext();
assert(ctx.orm.User);
assert(app.orm.User);
const user = await ctx.orm.User.create({
name: 'fengmk2',
salt: 'salt',
passwordSha: 'password_sha',
ip: 'ip',
rev: 'rev',
email: 'fengmk2@gmail.com',
json: '{}',
npmUser: '0',
});
assert(user.id === 1);
assert(user.isNpmUser === false);
await user.save();
assert(user.id);
const notExistsUser = await ctx.orm.User.findOne({ name: 'not-exists' });
assert(!notExistsUser);
const existsUser = await ctx.orm.User.findOne({ name: 'fengmk2' });
assert(existsUser.id === user.id);
assert(existsUser.name === user.name);
assert(existsUser.isNpmUser === false);
});
});
});

View File

@@ -1,40 +0,0 @@
'use strict';
const assert = require('assert');
const mm = require('mm');
const urllib = require('../../common/urllib');
const config = require('../../config');
describe('test/common/urllib.test.js', () => {
describe('accelerate request', () => {
beforeEach(() => {
mm(config, 'accelerateHostMap', {
'www.alipay.com': 'www.antgroup.com',
'www.google.com': 'www.google.com'
});
});
describe('direct', () => {
it('should work', function* () {
const res = yield urllib.request('https://www.alipay.com', {
followRedirect: true,
});
assert.deepStrictEqual(res.res.requestUrls, [
'https://www.antgroup.com/',
]);
});
});
describe('redirect', () => {
it('should work', function* () {
const res = yield urllib.request('https://google.com', {
followRedirect: true,
});
assert.deepStrictEqual(res.res.requestUrls, [
'https://google.com/',
'https://www.google.com/',
]);
});
});
});
});

View File

@@ -96,20 +96,6 @@ describe('test/controllers/registry/package/dist_tag.test.js', function () {
.expect(400, done);
});
it.only('should 400 when set a version of 70+ length', function (done) {
const tag = Buffer.alloc(71, 'a').toString();
request(app)
.put(`/-/package/@cnpmtest/dist_tag_test_module_set/dist-tags/${tag}`)
.set('authorization', utils.otherUserAuth)
.set('content-type', 'application/json')
.send(JSON.stringify(`1.0.1`))
.expect({
error: '[version_error] @cnpmtest/dist_tag_test_module_set@1.0.1 not exists',
reason: '[version_error] @cnpmtest/dist_tag_test_module_set@1.0.1 not exists',
})
.expect(400, done);
});
it('should 201 set exists tag', function (done) {
request(app)
.put('/-/package/@cnpmtest/dist_tag_test_module_set/dist-tags/exists')

View File

@@ -49,7 +49,6 @@ describe('test/controllers/registry/package/list.test.js', () => {
var data = res.body;
data.name.should.equal('@cnpmtest/testmodule-list-1');
assert(res.headers['x-custom-middleware'] === 'true');
assert(res.headers['x-custom-app-models'] === 'true');
done();
});
});
@@ -230,29 +229,6 @@ describe('test/controllers/registry/package/list.test.js', () => {
}, done);
});
it('should config.formatCustomFullPackageInfoAndVersions work', async () => {
mm(config, 'formatCustomFullPackageInfoAndVersions', (ctx, info) => {
console.log('%s %s, query: %j', ctx.method, ctx.url, ctx.query);
info.description = '';
info.readme = '';
for (const version in info.versions) {
const item = info.versions[version];
item.description = '';
item.readme = '';
}
return info;
});
const res = await request(app)
.get('/@cnpmtest/testmodule-list-1?a=123123');
assert(res.status === 200);
assert(res.body.description === '');
assert(res.body.readme === '');
const firstVersion = Object.keys(res.body.versions)[0];
assert(firstVersion);
assert(res.body.versions[firstVersion].description === '');
assert(res.body.versions[firstVersion].readme === '');
});
describe.skip('unpublished', () => {
before(done => {
mm(config, 'syncModel', 'all');

View File

@@ -46,14 +46,14 @@ describe('test/controllers/registry/package/list_by_user.test.js', function () {
map['@cnpmtest/list_by_user_module1'].should.be.an.Object();
map['@cnpmtest/list_by_user_module1'].should.eql({
name: '@cnpmtest/list_by_user_module1',
description: 'mk2testmodule version description here',
description: '',
version: '1.0.1',
});
map['@cnpmtest/list_by_user_module2'].should.be.an.Object();
map['@cnpmtest/list_by_user_module2'].should.eql({
name: '@cnpmtest/list_by_user_module2',
description: 'mk2testmodule version description here',
description: '',
version: '2.0.0',
});
})

View File

@@ -215,21 +215,6 @@ describe('test/controllers/registry/package/save.test.js', function () {
.expect(403, done);
});
it('should publish when maintainers dont contain current user in token mode', function* () {
var token = yield tokenService.createToken(utils.admin);
var pkg = utils.getPackage('testmodule-new-4', '0.0.1', utils.admin);
pkg.versions['0.0.1'].maintainers[0].name += '-testuser';
yield request(app)
.put('/' + pkg.name)
.set('authorization', 'Bearer ' + token.token)
.send(pkg)
.expect(201);
yield tokenService.deleteToken(utils.admin, token.token);
});
it('should 400 when attachments missing', function (done) {
var pkg = utils.getPackage('testmodule-new-1', '0.0.1', utils.admin);
delete pkg._attachments;

View File

@@ -1,6 +1,5 @@
'use strict';
var assert = require('assert');
var should = require('should');
var request = require('supertest');
var mm = require('mm');
@@ -185,20 +184,6 @@ describe('test/controllers/registry/package/show.test.js', function () {
.expect(404, done);
});
it('should config.formatCustomOnePackageVersion work', async () => {
mm(config, 'formatCustomOnePackageVersion', (ctx, packageVersion) => {
console.log('%s %s, query: %j', ctx.method, ctx.url, ctx.query);
packageVersion.description = '';
packageVersion.readme = '';
return packageVersion;
});
const res = await request(app)
.get('/@cnpmtest/testmodule-show/0.0.1?b=123123');
assert(res.status === 200);
assert(res.body.description === '');
assert(res.body.readme === '');
});
describe('show sync package', function () {
before(function (done) {
utils.sync('baidu', done);

View File

@@ -1,6 +1,5 @@
'use strict';
var assert = require('assert');
var should = require('should');
var request = require('supertest');
var mm = require('mm');
@@ -120,13 +119,6 @@ describe('test/controllers/registry/package/update.test.js', function () {
});
it('should add again new maintainers', function (done) {
done = pedding(done, 2);
mm(config, 'globalHook', function* (envelope) {
assert(envelope.name === '@cnpmtest/testmodule-update-1');
assert(envelope.type === 'package');
assert(envelope.event === 'package:owner');
done();
});
request(app)
.put('/@cnpmtest/testmodule-update-1/-rev/1')
.send({
@@ -179,14 +171,6 @@ describe('test/controllers/registry/package/update.test.js', function () {
});
it('should rm maintainers', function (done) {
done = pedding(done, 2);
mm(config, 'globalHook', function* (envelope) {
assert(envelope.name === '@cnpmtest/testmodule-update-1');
assert(envelope.type === 'package');
assert(envelope.event === 'package:owner-rm');
done();
});
request(app)
.put('/@cnpmtest/testmodule-update-1/-rev/1')
.send({

View File

@@ -1,16 +1,13 @@
'use strict';
var assert = require('assert');
var awaitEvent = require('await-event');
var should = require('should');
var mm = require('mm');
var thunkify = require('thunkify-wrap');
var request = require('supertest');
var urllib = require('urllib');
var urlparse = require('url').parse;
var fs = require('mz/fs');
var config = require('../../config');
var common = require('../../lib/common');
var SyncModuleWorker = require('../../controllers/sync_module_worker');
var logService = require('../../services/module_log');
var packageService = require('../../services/package');
@@ -458,353 +455,4 @@ describe('test/controllers/sync_module_worker.test.js', () => {
});
});
});
describe('save backup files', function () {
const pkgName = 'backup-test';
beforeEach(() => {
mm(config, 'syncBackupFiles', true);
});
describe('package not exists', () => {
const mockPackageJson = {
name: pkgName,
version: '1.0.0',
description: 'foo',
};
beforeEach(() => {
mm(packageService, 'listModulesByName', function* () {
return [
{ name: pkgName, version: '1.0.0' },
];
});
mm(packageService, 'showPackage', function* () {
return { package: mockPackageJson };
});
});
afterEach(function* () {
yield config.nfs.remove(common.getPackageFileCDNKey(pkgName, '1.0.0'));
});
it('should upload new file', function* () {
var worker = new SyncModuleWorker({
name: pkgName,
username: 'fengmk2',
});
yield worker._saveBackupFiles();
const cdnKey = common.getPackageFileCDNKey(pkgName, '1.0.0');
const filePath = '/tmp/tnpm-1.0.0.json';
yield config.nfs.download(cdnKey, filePath);
const fileContent = yield fs.readFile(filePath, 'utf8');
const packageJson = JSON.parse(fileContent);
assert.deepStrictEqual(packageJson, mockPackageJson);
});
});
describe('new dist tag', () => {
beforeEach(() => {
mm(packageService, 'listModulesByName', function* () {
return [];
});
mm(packageService, 'listModuleTags', function* () {
return [
{ tag: 'latest', version: '1.0.0' },
];
});
});
afterEach(function* () {
yield config.nfs.remove(common.getDistTagCDNKey(pkgName, 'latest'));
});
it('should create dist-tag file', function* () {
var worker = new SyncModuleWorker({
name: pkgName,
username: 'fengmk2',
});
yield worker._saveBackupFiles();
const cdnKey = common.getDistTagCDNKey(pkgName, 'latest');
const filePath = '/tmp/tnpm-dist-tag.json';
yield config.nfs.download(cdnKey, filePath);
const fileContent = yield fs.readFile(filePath, 'utf8');
assert(fileContent === '1.0.0');
});
});
describe('remove dist tag', () => {
beforeEach(function* () {
mm(packageService, 'listModulesByName', function* () {
return [];
});
mm(packageService, 'listModuleTags', function* () {
return [];
});
const cdnKey = common.getDistTagCDNKey(pkgName, 'latest');
const filePath = '/tmp/tnpm-dist-tag.json';
yield fs.writeFile(filePath, '1.0.0');
yield config.nfs.upload(filePath, {
key: cdnKey,
});
});
it('should delete', function* () {
var worker = new SyncModuleWorker({
name: pkgName,
username: 'fengmk2',
});
yield worker._saveBackupFiles();
const cdnKey = common.getDistTagCDNKey(pkgName, 'latest');
let err;
try {
const filePath = '/tmp/tnpm-dist-tag.json';
yield config.nfs.download(cdnKey, filePath);
} catch (e) {
err = e;
}
assert(/ENOENT/.test(err));
});
});
describe('update dist tag', () => {
beforeEach(function* () {
mm(packageService, 'listModulesByName', function* () {
return [];
});
mm(packageService, 'listModuleTags', function* () {
return [
{ tag: 'latest', version: '1.0.1' },
];
});
const cdnKey = common.getDistTagCDNKey(pkgName, 'latest');
const filePath = '/tmp/tnpm-dist-tag.json';
yield fs.writeFile(filePath, '1.0.0');
yield config.nfs.upload(filePath, {
key: cdnKey,
});
});
afterEach(function* () {
yield config.nfs.remove(common.getDistTagCDNKey(pkgName, 'latest'));
});
it('should update dist-tag file', function* () {
var worker = new SyncModuleWorker({
name: pkgName,
username: 'fengmk2',
});
yield worker._saveBackupFiles();
const cdnKey = common.getDistTagCDNKey(pkgName, 'latest');
const filePath = '/tmp/tnpm-dist-tag.json';
yield config.nfs.download(cdnKey, filePath);
const fileContent = yield fs.readFile(filePath, 'utf8');
assert(fileContent === '1.0.1');
});
});
describe('package unpublished', () => {
it('should sync unpublished info', function* () {
var worker = new SyncModuleWorker({
name: ['afp'],
username: 'fengmk2'
});
worker.start();
yield awaitEvent(worker, 'end');
const cdnKey = common.getUnpublishFileKey('afp');
const filePath = '/tmp/unpublish-package.json';
yield config.nfs.download(cdnKey, filePath);
const fileContent = yield fs.readFile(filePath, 'utf8');
assert(fileContent);
});
});
});
describe('sync from backup files', function () {
const pkgName = 'sync-from-backup-files';
const publishTime100 = Date.now() - 1000 * 60;
const publishTime101 = Date.now();
afterEach(function* () {
try {
yield config.nfs.remove(common.getDistTagCDNKey(pkgName, 'latest'));
yield config.nfs.remove(common.getDistTagCDNKey(pkgName, 'beta'));
yield config.nfs.remove(common.getPackageFileCDNKey(pkgName, '1.0.1'));
yield config.nfs.remove(common.getPackageFileCDNKey(pkgName, '1.0.0'));
} catch (_) {
// ...
}
});
beforeEach(function* () {
mm(config, 'syncBackupFiles', true);
const packageFileCDNKey100 = common.getPackageFileCDNKey(pkgName, '1.0.0');
const packageFilePath = '/tmp/tnpm-package.json';
yield fs.writeFile(packageFilePath, JSON.stringify({
name: pkgName,
version: '1.0.0',
publish_time: publishTime100,
description: 'mock desc',
maintainers: [],
author: {},
repository: {},
readme: 'mock readme',
readmeFilename: 'README.md',
homepage: 'mock home page',
bugs: {},
license: 'MIT',
}));
yield config.nfs.upload(packageFilePath, {
key: packageFileCDNKey100,
});
const packageFileCDNKey101 = common.getPackageFileCDNKey(pkgName, '1.0.1');
yield fs.writeFile(packageFilePath, JSON.stringify({
name: pkgName,
version: '1.0.1',
publish_time: publishTime101,
description: 'mock desc 101',
maintainers: [],
author: {},
repository: {},
readme: 'mock readme 101',
readmeFilename: 'README.md',
homepage: 'mock home page 101',
bugs: {},
license: 'MIT',
}));
yield config.nfs.upload(packageFilePath, {
key: packageFileCDNKey101,
});
const distTagCDNKey = common.getDistTagCDNKey(pkgName, 'latest');
const distTagFilePath = '/tmp/tnpm-dist-tag.json';
yield fs.writeFile(distTagFilePath, '1.0.0');
yield config.nfs.upload(distTagFilePath, {
key: distTagCDNKey,
});
const distTagCDNKeyBeta = common.getDistTagCDNKey(pkgName, 'beta');
yield fs.writeFile(distTagFilePath, '1.0.1');
yield config.nfs.upload(distTagFilePath, {
key: distTagCDNKeyBeta,
});
});
it('should create pkg', function (done) {
var worker = new SyncModuleWorker({
name: pkgName,
username: 'fengmk2',
syncFromBackupFile: true,
});
var syncPkg;
mm(worker, '_sync', function* (name, pkg) {
syncPkg = pkg;
return [ '1.0.0' ];
})
worker.start();
worker.on('end', function () {
assert.deepStrictEqual(worker.successes, [
pkgName,
]);
assert.deepStrictEqual(syncPkg, {
name: pkgName,
'dist-tags': { beta: '1.0.1', latest: '1.0.0' },
versions: {
'1.0.0': {
name: pkgName,
version: '1.0.0',
publish_time: publishTime100,
description: 'mock desc',
maintainers: [],
author: {},
repository: {},
readme: 'mock readme',
readmeFilename: 'README.md',
homepage: 'mock home page',
bugs: {},
license: 'MIT'
},
'1.0.1': {
name: pkgName,
version: '1.0.1',
publish_time: publishTime101,
description: 'mock desc 101',
maintainers: [],
author: {},
repository: {},
readme: 'mock readme 101',
readmeFilename: 'README.md',
homepage: 'mock home page 101',
bugs: {},
license: 'MIT'
}
},
time: {
modified: new Date(publishTime101),
created: new Date(publishTime100),
'1.0.0': new Date(publishTime100),
'1.0.1': new Date(publishTime101),
},
description: 'mock desc 101',
maintainers: [],
author: {},
repository: {},
readme: 'mock readme 101',
readmeFilename: 'README.md',
homepage: 'mock home page 101',
bugs: {},
license: 'MIT'
});
done();
});
});
describe('unpublish', () => {
before(function* () {
const filePath = '/tmp/unpublish-package.json';
const cdnKey = common.getUnpublishFileKey('afp');
yield fs.writeFile(filePath, JSON.stringify({
name: 'xinglie',
time: '2017-02-21T13:10:22.892Z',
tags: { latest: '0.0.1' },
maintainers:[{
name: 'xinglie',
email: 'kooboy_li@163.com'
}],
versions:["0.0.1"]
}));
yield config.nfs.upload(filePath, {
key: cdnKey,
});
});
it('should unpublished pkg', function* () {
const worker = new SyncModuleWorker({
name: ['afp'],
username: 'fengmk2',
syncFromBackupFile: true,
});
let unpublishPkg;
mm(worker, '_unpublished', function(pkg) {
unpublishPkg = pkg;
return Promise.resolve();
});
worker.start();
yield awaitEvent(worker, 'end');
assert(unpublishPkg === 'afp');
});
});
});
});

View File

@@ -41,8 +41,8 @@ describe('test/controllers/web/package/search.test.js', function () {
.expect(200)
.expect({
keyword: '@cnpmtest/testmodule-web-search',
match: { name: '@cnpmtest/testmodule-web-search', description: 'mk2testmodule version description here' },
packages: [ { name: '@cnpmtest/testmodule-web-search', description: 'mk2testmodule version description here' } ],
match: { name: '@cnpmtest/testmodule-web-search', description: '' },
packages: [ { name: '@cnpmtest/testmodule-web-search', description: '' } ],
keywords: []
})
.expect('content-type', 'application/json; charset=utf-8', done);
@@ -52,7 +52,7 @@ describe('test/controllers/web/package/search.test.js', function () {
request(app)
.get('/browse/keyword/@cnpmtest/testmodule-web-search?type=json&callback=foo')
.expect(200)
.expect('/**/ typeof foo === \'function\' && foo({"keyword":"@cnpmtest/testmodule-web-search","match":{"name":"@cnpmtest/testmodule-web-search","description":"mk2testmodule version description here"},"packages":[{"name":"@cnpmtest/testmodule-web-search","description":"mk2testmodule version description here"}],"keywords":[]});')
.expect('/**/ typeof foo === \'function\' && foo({"keyword":"@cnpmtest/testmodule-web-search","match":{"name":"@cnpmtest/testmodule-web-search","description":""},"packages":[{"name":"@cnpmtest/testmodule-web-search","description":""}],"keywords":[]});')
.expect('content-type', 'application/javascript; charset=utf-8', done);
});
@@ -87,8 +87,8 @@ describe('test/controllers/web/package/search.test.js', function () {
.expect({
keyword: '@cnpmtest/testmodule-web-searc',
match: null,
packages: [ { name: '@cnpmtest/testmodule-web-search', description: 'mk2testmodule version description here' },
{ name: '@cnpmtest/testmodule-web-search_a', description: 'mk2testmodule version description here' }],
packages: [ { name: '@cnpmtest/testmodule-web-search', description: '' },
{ name: '@cnpmtest/testmodule-web-search_a', description: '' }],
keywords: []
})
.expect('content-type', 'application/json; charset=utf-8', done);
@@ -101,7 +101,7 @@ describe('test/controllers/web/package/search.test.js', function () {
.expect({
keyword: '@cnpmtest/testmodule-web-searc',
match: null,
packages: [ { name: '@cnpmtest/testmodule-web-search', description: 'mk2testmodule version description here' }],
packages: [ { name: '@cnpmtest/testmodule-web-search', description: '' }],
keywords: []
})
.expect('content-type', 'application/json; charset=utf-8', done);

View File

@@ -82,7 +82,6 @@ describe('controllers/web/user/show.test.js', function () {
// he.enclde('fengmk2@gmail.com') ↓
assert(res.text.includes('&#x66;&#x65;&#x6E;&#x67;&#x6D;&#x6B;&#x32;&#x40;&#x67;&#x6D;&#x61;&#x69;&#x6C;&#x2E;&#x63;&#x6F;&#x6D;'));
assert(res.headers['x-custom-web-middleware'] === 'true');
assert(res.headers['x-custom-web-app-models'] === 'true');
done()
});
});

View File

@@ -1,53 +1 @@
{
"_id": "mk2testmodule",
"name": "mk2testmodule",
"description": "mk2testmodule description here",
"dist-tags": {
"latest": "0.0.1"
},
"versions": {
"0.0.1": {
"name": "mk2testmodule",
"version": "0.0.1",
"description": "mk2testmodule version description here",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"readme": "ERROR: No README data found!",
"_id": "mk2testmodule@0.0.1",
"dist": {
"shasum": "fa475605f88bab9b1127833633ca3ae0a477224c",
"tarball": "http://127.0.0.1:7001/mk2testmodule/-/mk2testmodule-0.0.1.tgz"
},
"_from": ".",
"_npmVersion": "1.4.3",
"_npmUser": {
"name": "fengmk2",
"email": "fengmk2@gmail.com"
},
"maintainers": [
{
"name": "fengmk2",
"email": "fengmk2@gmail.com"
}
]
}
},
"readme": "ERROR: No README data found!",
"maintainers": [
{
"name": "fengmk2",
"email": "fengmk2@gmail.com"
}
],
"_attachments": {
"mk2testmodule-0.0.1.tgz": {
"content_type": "application/octet-stream",
"data": "H4sIAAAAAAAAA+2SsWrDMBCGPfspDg2ZinOyEgeylg6Zu2YR8rVRHEtGkkOg5N0jWaFdujVQAv6W4/7/dHcSGqTq5Ccthxyro7emeDCI2KxWkOKmaaaIdc4TouZQ8FqgwI3AdVMgF8ijho9e5DdGH6SLq/y1T74LfMcn4asEYEb2xLbA+q4O5ENv2/FE7CVZZ3JeW5NcrLDiWW3JK6eHcHey2Es9Zdq0dIkfKau50EcjjYpCmpDKSB0s7Nmbc9ZtwVhIBviBlP7Q1O4ZLBZAFx2As3jyOnWTYzhY9zPzpBUZPy2/e39l5bX87wedmZmZeRJuheTX2wAIAAA=",
"length": 251
}
}
}
{"_id":"mk2testmodule","name":"mk2testmodule","description":"","dist-tags":{"latest":"0.0.1"},"versions":{"0.0.1":{"name":"mk2testmodule","version":"0.0.1","description":"","main":"index.js","scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"author":"","license":"ISC","readme":"ERROR: No README data found!","_id":"mk2testmodule@0.0.1","dist":{"shasum":"fa475605f88bab9b1127833633ca3ae0a477224c","tarball":"http://127.0.0.1:7001/mk2testmodule/-/mk2testmodule-0.0.1.tgz"},"_from":".","_npmVersion":"1.4.3","_npmUser":{"name":"fengmk2","email":"fengmk2@gmail.com"},"maintainers":[{"name":"fengmk2","email":"fengmk2@gmail.com"}]}},"readme":"ERROR: No README data found!","maintainers":[{"name":"fengmk2","email":"fengmk2@gmail.com"}],"_attachments":{"mk2testmodule-0.0.1.tgz":{"content_type":"application/octet-stream","data":"H4sIAAAAAAAAA+2SsWrDMBCGPfspDg2ZinOyEgeylg6Zu2YR8rVRHEtGkkOg5N0jWaFdujVQAv6W4/7/dHcSGqTq5Ccthxyro7emeDCI2KxWkOKmaaaIdc4TouZQ8FqgwI3AdVMgF8ijho9e5DdGH6SLq/y1T74LfMcn4asEYEb2xLbA+q4O5ENv2/FE7CVZZ3JeW5NcrLDiWW3JK6eHcHey2Es9Zdq0dIkfKau50EcjjYpCmpDKSB0s7Nmbc9ZtwVhIBviBlP7Q1O4ZLBZAFx2As3jyOnWTYzhY9zPzpBUZPy2/e39l5bX87wedmZmZeRJuheTX2wAIAAA=","length":251}}}

View File

@@ -4,9 +4,6 @@ var should = require('should');
var sleep = require('co-sleep');
var Package = require('../../services/package');
var utils = require('../utils');
var common = require('../../services/common');
const config = require('../../config');
const os = require('os');
describe('test/services/package.test.js', function () {
describe('addModuleTag()', function () {
@@ -29,15 +26,6 @@ describe('test/services/package.test.js', function () {
var tag = yield Package.addModuleTag('not-exists', 'latest', '1.0.0');
should.not.exist(tag);
});
it('should return Error when tag length out of range', function* () {
const r = yield utils.createModule('test-addModuleTag-module-name', '1.0.0');
try {
yield Package.addModuleTag(r.name, Buffer.alloc(config.tagLen + 1, 'a'), r.version);
} catch (error) {
error.message.should.equal(`addModuleTag Error: length of tag(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) > 70${os.EOL}`);
}
});
});
describe('getModuleByTag()', function () {
@@ -156,7 +144,7 @@ describe('test/services/package.test.js', function () {
var alls = yield Package.listAllPublicModuleNames();
alls.length.should.above(0);
alls.forEach(function (name) {
common.isPrivatePackage(name).should.equal(false);
name.should.not.containEql('@');
});
});
});