0
Fork 0
mirror of https://github.com/verdaccio/verdaccio.git synced 2025-01-13 22:48:31 -05:00

refactor: add flow support on publish endpoint

This commit is contained in:
Juan Picado @jotadeveloper 2018-03-17 11:54:57 +01:00
parent 5a93589caa
commit 7237ab340f
No known key found for this signature in database
GPG key ID: 18AC54485952D158
8 changed files with 51 additions and 39 deletions

View file

@ -47,7 +47,7 @@ export default function(route: Router, auth: IAuth, storage: IStorageHandler, co
}); });
route.get('/:package/-/:filename', can('access'), function(req: $RequestExtend, res: $ResponseExtend) { route.get('/:package/-/:filename', can('access'), function(req: $RequestExtend, res: $ResponseExtend) {
const stream = storage.get_tarball(req.params.package, req.params.filename); const stream = storage.getTarball(req.params.package, req.params.filename);
stream.on('content-length', function(content) { stream.on('content-length', function(content) {
res.header('Content-Length', content); res.header('Content-Length', content);

View file

@ -1,23 +1,27 @@
const _ = require('lodash'); // @flow
const Path = require('path');
const createError = require('http-errors');
const {media, expect_json, allow} = require('../../middleware'); import _ from 'lodash';
const Notify = require('../../../lib/notify'); import Path from 'path';
const {DIST_TAGS, validate_metadata, isObject} = require('../../../lib/utils'); import mime from 'mime';
const mime = require('mime');
const notify = Notify.notify; import {DIST_TAGS, validate_metadata, isObject, ErrorCode} from '../../../lib/utils';
import {media, expect_json, allow} from '../../middleware';
import {notify} from '../../../lib/notify';
export default function(router, auth, storage, config) { import type {Router} from 'express';
import type {Config, Callback} from '@verdaccio/types';
import type {IAuth, $ResponseExtend, $RequestExtend, $NextFunctionVer, IStorageHandler} from '../../../../types';
export default function(router: Router, auth: IAuth, storage: IStorageHandler, config: Config) {
const can = allow(auth); const can = allow(auth);
// publishing a package // publishing a package
router.put('/:package/:_rev?/:revision?', can('publish'), media(mime.getType('json')), expect_json, function(req, res, next) { router.put('/:package/:_rev?/:revision?', can('publish'),
media(mime.getType('json')), expect_json, function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
const name = req.params.package; const name = req.params.package;
let metadata; let metadata;
const create_tarball = function(filename, data, cb) { const create_tarball = function(filename: string, data, cb: Callback) {
let stream = storage.add_tarball(name, filename); let stream = storage.addTarball(name, filename);
stream.on('error', function(err) { stream.on('error', function(err) {
cb(err); cb(err);
}); });
@ -26,6 +30,8 @@ export default function(router, auth, storage, config) {
}); });
// this is dumb and memory-consuming, but what choices do we have? // this is dumb and memory-consuming, but what choices do we have?
// flow: we need first refactor this file before decides which type use here
// $FlowFixMe
stream.end(new Buffer(data.data, 'base64')); stream.end(new Buffer(data.data, 'base64'));
stream.done(); stream.done();
}; };
@ -59,7 +65,7 @@ export default function(router, auth, storage, config) {
|| Object.keys(metadata.versions).length !== 1) { || Object.keys(metadata.versions).length !== 1) {
// npm is doing something strange again // npm is doing something strange again
// if this happens in normal circumstances, report it as a bug // if this happens in normal circumstances, report it as a bug
return next( createError[400]('unsupported registry call') ); return next(ErrorCode.get400('unsupported registry call'));
} }
if (err && err.status != 409) { if (err && err.status != 409) {
@ -94,13 +100,13 @@ export default function(router, auth, storage, config) {
if (Object.keys(req.body).length === 1 && isObject(req.body.users)) { if (Object.keys(req.body).length === 1 && isObject(req.body.users)) {
// 501 status is more meaningful, but npm doesn't show error message for 5xx // 501 status is more meaningful, but npm doesn't show error message for 5xx
return next( createError[404]('npm star|unstar calls are not implemented') ); return next(ErrorCode.get404('npm star|unstar calls are not implemented'));
} }
try { try {
metadata = validate_metadata(req.body, name); metadata = validate_metadata(req.body, name);
} catch(err) { } catch(err) {
return next( createError[422]('bad incoming package data') ); return next(ErrorCode.get422('bad incoming package data'));
} }
if (req.params._rev) { if (req.params._rev) {
@ -115,7 +121,7 @@ export default function(router, auth, storage, config) {
}); });
// unpublishing an entire package // unpublishing an entire package
router.delete('/:package/-rev/*', can('publish'), function(req, res, next) { router.delete('/:package/-rev/*', can('publish'), function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
storage.remove_package(req.params.package, function(err) { storage.remove_package(req.params.package, function(err) {
if (err) { if (err) {
return next(err); return next(err);
@ -126,7 +132,8 @@ export default function(router, auth, storage, config) {
}); });
// removing a tarball // removing a tarball
router.delete('/:package/-/:filename/-rev/:revision', can('publish'), function(req, res, next) { router.delete('/:package/-/:filename/-rev/:revision', can('publish'),
function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
storage.remove_tarball(req.params.package, req.params.filename, req.params.revision, function(err) { storage.remove_tarball(req.params.package, req.params.filename, req.params.revision, function(err) {
if (err) { if (err) {
return next(err); return next(err);
@ -137,9 +144,10 @@ export default function(router, auth, storage, config) {
}); });
// uploading package tarball // uploading package tarball
router.put('/:package/-/:filename/*', can('publish'), media('application/octet-stream'), function(req, res, next) { router.put('/:package/-/:filename/*', can('publish'), media('application/octet-stream'),
function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
const name = req.params.package; const name = req.params.package;
const stream = storage.add_tarball(name, req.params.filename); const stream = storage.addTarball(name, req.params.filename);
req.pipe(stream); req.pipe(stream);
// checking if end event came before closing // checking if end event came before closing
@ -166,7 +174,8 @@ export default function(router, auth, storage, config) {
}); });
// adding a version // adding a version
router.put('/:package/:version/-tag/:tag', can('publish'), media(mime.getType('json')), expect_json, function(req, res, next) { router.put('/:package/:version/-tag/:tag', can('publish'),
media(mime.getType('json')), expect_json, function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
let name = req.params.package; let name = req.params.package;
let version = req.params.version; let version = req.params.version;
let tag = req.params.tag; let tag = req.params.tag;

View file

@ -10,7 +10,7 @@ import UrlNode from 'url';
import _ from 'lodash'; import _ from 'lodash';
// $FlowFixMe // $FlowFixMe
import async from 'async'; import async from 'async';
import {ErrorCode, isObject, getLatestVersion, tag_version, validate_name, semverSort, DIST_TAGS} from './utils'; import {ErrorCode, isObject, getLatestVersion, tagVersion, validate_name, semverSort, DIST_TAGS} from './utils';
import { import {
generatePackageTemplate, normalizePackage, generateRevision, cleanUpReadme, generatePackageTemplate, normalizePackage, generateRevision, cleanUpReadme,
fileExist, noSuchFile, DEFAULT_REVISION, pkgFileName, fileExist, noSuchFile, DEFAULT_REVISION, pkgFileName,
@ -35,7 +35,7 @@ import type {
IUploadTarball, IUploadTarball,
IReadTarball, IReadTarball,
} from '@verdaccio/streams'; } from '@verdaccio/streams';
import type {IStorage} from '../../types'; import type {IStorage, StringValue} from '../../types';
/** /**
* Implements Storage interface (same for storage.js, local-storage.js, up-storage.js). * Implements Storage interface (same for storage.js, local-storage.js, up-storage.js).
@ -233,7 +233,7 @@ class LocalStorage implements IStorage {
addVersion(name: string, addVersion(name: string,
version: string, version: string,
metadata: Version, metadata: Version,
tag: string, tag: StringValue,
callback: Callback) { callback: Callback) {
this._updatePackage(name, (data, cb) => { this._updatePackage(name, (data, cb) => {
// keep only one readme per package // keep only one readme per package
@ -272,7 +272,7 @@ class LocalStorage implements IStorage {
} }
data.versions[version] = metadata; data.versions[version] = metadata;
tag_version(data, version, tag); tagVersion(data, version, tag);
let addFailed = this.localData.add(name); let addFailed = this.localData.add(name);
if (addFailed) { if (addFailed) {
@ -302,7 +302,7 @@ class LocalStorage implements IStorage {
return cb( this._getVersionNotFound() ); return cb( this._getVersionNotFound() );
} }
const key: string = tags[t]; const key: string = tags[t];
tag_version(data, key, t); tagVersion(data, key, t);
} }
cb(); cb();
}, callback); }, callback);

View file

@ -12,7 +12,7 @@ import LocalStorage from './local-storage';
import {ReadTarball} from '@verdaccio/streams'; import {ReadTarball} from '@verdaccio/streams';
import ProxyStorage from './up-storage'; import ProxyStorage from './up-storage';
import {ErrorCode, normalize_dist_tags, validate_metadata, isObject, DIST_TAGS} from './utils'; import {ErrorCode, normalize_dist_tags, validate_metadata, isObject, DIST_TAGS} from './utils';
import type {IStorage, IProxy, IStorageHandler, ProxyList} from '../../types'; import type {IStorage, IProxy, IStorageHandler, ProxyList, StringValue} from '../../types';
import type { import type {
Versions, Versions,
Package, Package,
@ -168,7 +168,7 @@ class Storage implements IStorageHandler {
* @param {*} tag * @param {*} tag
* @param {*} callback * @param {*} callback
*/ */
addVersion(name: string, version: string, metadata: Version, tag: string, callback: Callback) { addVersion(name: string, version: string, metadata: Version, tag: StringValue, callback: Callback) {
this.localStorage.addVersion(name, version, metadata, tag, callback); this.localStorage.addVersion(name, version, metadata, tag, callback);
} }
@ -244,7 +244,7 @@ class Storage implements IStorageHandler {
* @param {*} filename * @param {*} filename
* @return {Stream} * @return {Stream}
*/ */
add_tarball(name: string, filename: string): IUploadTarball { addTarball(name: string, filename: string): IUploadTarball {
return this.localStorage.addTarball(name, filename); return this.localStorage.addTarball(name, filename);
} }
@ -258,7 +258,7 @@ class Storage implements IStorageHandler {
* @param {*} filename * @param {*} filename
* @return {Stream} * @return {Stream}
*/ */
get_tarball(name: string, filename: string) { getTarball(name: string, filename: string) {
let readStream = new ReadTarball(); let readStream = new ReadTarball();
readStream.abort = function() {}; readStream.abort = function() {};

View file

@ -10,6 +10,7 @@ import _ from 'lodash';
import createError from 'http-errors'; import createError from 'http-errors';
import type {Package, Config} from '@verdaccio/types'; import type {Package, Config} from '@verdaccio/types';
import type {$Request} from 'express'; import type {$Request} from 'express';
import type {StringValue} from '../../types';
const Logger = require('./logger'); const Logger = require('./logger');
@ -145,8 +146,8 @@ function filter_tarball_urls(pkg: Package, req: $Request, config: Config) {
* @param {*} tag * @param {*} tag
* @return {Boolean} whether a package has been tagged * @return {Boolean} whether a package has been tagged
*/ */
function tag_version(data: Package, version: string, tag: string) { function tagVersion(data: Package, version: string, tag: StringValue) {
if (_.isEmpty(tag) === false) { if (tag) {
if (data[DIST_TAGS][tag] !== version) { if (data[DIST_TAGS][tag] !== version) {
if (semver.parse(version, true)) { if (semver.parse(version, true)) {
// valid version - store // valid version - store
@ -443,7 +444,7 @@ export {
parse_address, parse_address,
get_version, get_version,
normalize_dist_tags, normalize_dist_tags,
tag_version, tagVersion,
combineBaseUrl, combineBaseUrl,
filter_tarball_urls, filter_tarball_urls,
validate_metadata, validate_metadata,

View file

@ -39,7 +39,7 @@ describe('StorageTest', () => {
name: 'react', name: 'react',
req: request, req: request,
callback: () => { callback: () => {
const stream = storage.get_tarball('react', 'react-16.1.0.tgz'); const stream = storage.getTarball('react', 'react-16.1.0.tgz');
stream.on('content-length', function(content) { stream.on('content-length', function(content) {
if (content) { if (content) {
expect(content).toBeTruthy(); expect(content).toBeTruthy();

View file

@ -1,5 +1,5 @@
let assert = require('assert'); let assert = require('assert');
let tag_version = require('../../src/lib/utils').tag_version; let tag_version = require('../../src/lib/utils').tagVersion;
require('../../src/lib/logger').setup([]); require('../../src/lib/logger').setup([]);

View file

@ -16,6 +16,8 @@ import type {
import type {ILocalData} from '@verdaccio/local-storage'; import type {ILocalData} from '@verdaccio/local-storage';
import type {NextFunction, $Request, $Response} from 'request'; import type {NextFunction, $Request, $Response} from 'request';
export type StringValue = string | void | null;
export interface IAuth { export interface IAuth {
config: Config; config: Config;
logger: Logger; logger: Logger;
@ -77,14 +79,14 @@ export interface IStorageHandler {
logger: Logger; logger: Logger;
uplinks: ProxyList; uplinks: ProxyList;
addPackage(name: string, metadata: any, callback: Function): void; addPackage(name: string, metadata: any, callback: Function): void;
addVersion(name: string, version: string, metadata: Version, tag: string, callback: Callback): void; addVersion(name: string, version: string, metadata: Version, tag: StringValue, callback: Callback): void;
mergeTags(name: string, tagHash: MergeTags, callback: Callback): void; mergeTags(name: string, tagHash: MergeTags, callback: Callback): void;
replace_tags(name: string, tagHash: MergeTags, callback: Callback): void; replace_tags(name: string, tagHash: MergeTags, callback: Callback): void;
change_package(name: string, metadata: Package, revision: string, callback: Callback): void; change_package(name: string, metadata: Package, revision: string, callback: Callback): void;
remove_package(name: string, callback: Callback): void; remove_package(name: string, callback: Callback): void;
remove_tarball(name: string, filename: string, revision: string, callback: Callback): void; remove_tarball(name: string, filename: string, revision: string, callback: Callback): void;
add_tarball(name: string, filename: string): IUploadTarball; addTarball(name: string, filename: string): IUploadTarball;
get_tarball(name: string, filename: string): IReadTarball; getTarball(name: string, filename: string): IReadTarball;
getPackage(options: any): void; getPackage(options: any): void;
search(startkey: string, options: any): void; search(startkey: string, options: any): void;
getLocalDatabase(callback: Callback): void; getLocalDatabase(callback: Callback): void;
@ -100,7 +102,7 @@ export interface IStorage {
addPackage(name: string, info: Package, callback: Callback): void; addPackage(name: string, info: Package, callback: Callback): void;
removePackage(name: string, callback: Callback): void; removePackage(name: string, callback: Callback): void;
updateVersions(name: string, packageInfo: Package, callback: Callback): void; updateVersions(name: string, packageInfo: Package, callback: Callback): void;
addVersion(name: string, version: string, metadata: Version, tag: string, callback: Callback): void; addVersion(name: string, version: string, metadata: Version, tag: StringValue, callback: Callback): void;
mergeTags(name: string, tags: MergeTags, callback: Callback): void; mergeTags(name: string, tags: MergeTags, callback: Callback): void;
changePackage(name: string, metadata: Package, revision: string, callback: Callback): void; changePackage(name: string, metadata: Package, revision: string, callback: Callback): void;
removeTarball(name: string, filename: string, revision: string, callback: Callback): void; removeTarball(name: string, filename: string, revision: string, callback: Callback): void;