2019-01-28 22:54:47 -05:00
|
|
|
import fs from 'fs';
|
2022-01-09 14:51:50 -05:00
|
|
|
import path from 'path';
|
|
|
|
import rimraf from 'rimraf';
|
2021-03-14 02:42:46 -05:00
|
|
|
import { Writable } from 'stream';
|
2022-01-09 14:51:50 -05:00
|
|
|
|
|
|
|
import { Config } from '@verdaccio/types';
|
|
|
|
|
2019-05-19 16:07:17 -05:00
|
|
|
import AppConfig from '../../../../src/lib/config';
|
2022-01-09 14:51:50 -05:00
|
|
|
import { API_ERROR, HTTP_STATUS } from '../../../../src/lib/constants';
|
2021-03-14 02:42:46 -05:00
|
|
|
import { setup } from '../../../../src/lib/logger';
|
2022-01-09 14:51:50 -05:00
|
|
|
import Storage from '../../../../src/lib/storage';
|
2021-03-14 02:42:46 -05:00
|
|
|
import { DOMAIN_SERVERS } from '../../../functional/config.functional';
|
2022-11-22 12:35:47 -05:00
|
|
|
import { IStorageHandler } from '../../../types';
|
2022-01-09 14:51:50 -05:00
|
|
|
import { mockServer } from '../../__helper/mock';
|
|
|
|
import configExample from '../../partials/config';
|
2018-02-19 13:29:14 -05:00
|
|
|
|
2019-02-24 17:20:25 -05:00
|
|
|
setup([]);
|
2018-02-19 13:29:14 -05:00
|
|
|
|
2019-05-19 16:07:17 -05:00
|
|
|
const storagePath = path.join(__dirname, '../../partials/store/test-storage-store.spec');
|
2019-07-16 01:40:01 -05:00
|
|
|
const mockServerPort = 55548;
|
2021-03-14 02:42:46 -05:00
|
|
|
const generateStorage = async function (port = mockServerPort) {
|
|
|
|
const storageConfig = configExample(
|
|
|
|
{
|
|
|
|
self_path: __dirname,
|
|
|
|
storage: storagePath,
|
|
|
|
uplinks: {
|
|
|
|
npmjs: {
|
2021-12-22 18:14:53 -05:00
|
|
|
url: `http://${DOMAIN_SERVERS}:${port}`,
|
|
|
|
},
|
|
|
|
},
|
2021-03-14 02:42:46 -05:00
|
|
|
},
|
|
|
|
'store.spec.yaml'
|
|
|
|
);
|
2019-02-24 17:20:25 -05:00
|
|
|
|
2018-06-24 15:39:09 -05:00
|
|
|
const config: Config = new AppConfig(storageConfig);
|
2018-04-21 11:36:06 -05:00
|
|
|
const store: IStorageHandler = new Storage(config);
|
2019-07-16 01:40:01 -05:00
|
|
|
await store.init(config, []);
|
2018-02-19 13:29:14 -05:00
|
|
|
|
2018-06-24 15:39:09 -05:00
|
|
|
return store;
|
2021-03-14 02:42:46 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
const generateSameUplinkStorage = async function (port = mockServerPort) {
|
|
|
|
const storageConfig = configExample(
|
|
|
|
{
|
|
|
|
self_path: __dirname,
|
|
|
|
storage: storagePath,
|
|
|
|
packages: {
|
|
|
|
jquery: {
|
|
|
|
access: ['$all'],
|
|
|
|
publish: ['$all'],
|
2021-12-22 18:14:53 -05:00
|
|
|
proxy: ['cached'],
|
2021-03-14 02:42:46 -05:00
|
|
|
},
|
|
|
|
'@jquery/*': {
|
|
|
|
access: ['$all'],
|
|
|
|
publish: ['$all'],
|
2021-12-22 18:14:53 -05:00
|
|
|
proxy: ['notcached'],
|
|
|
|
},
|
2020-01-11 02:39:58 -05:00
|
|
|
},
|
2021-03-14 02:42:46 -05:00
|
|
|
uplinks: {
|
|
|
|
cached: {
|
|
|
|
url: `http://${DOMAIN_SERVERS}:${port}`,
|
2021-12-22 18:14:53 -05:00
|
|
|
cache: true,
|
2021-03-14 02:42:46 -05:00
|
|
|
},
|
|
|
|
notcached: {
|
|
|
|
url: `http://${DOMAIN_SERVERS}:${port}`,
|
2021-12-22 18:14:53 -05:00
|
|
|
cache: false,
|
|
|
|
},
|
|
|
|
},
|
2020-01-11 02:39:58 -05:00
|
|
|
},
|
2021-03-14 02:42:46 -05:00
|
|
|
'store.spec.yaml'
|
|
|
|
);
|
2020-01-11 02:39:58 -05:00
|
|
|
|
|
|
|
const config: Config = new AppConfig(storageConfig);
|
|
|
|
const store: IStorageHandler = new Storage(config);
|
|
|
|
await store.init(config, []);
|
|
|
|
|
|
|
|
return store;
|
2021-03-14 02:42:46 -05:00
|
|
|
};
|
2020-01-11 02:39:58 -05:00
|
|
|
|
2021-03-14 02:42:46 -05:00
|
|
|
const createNullStream = () =>
|
|
|
|
new Writable({
|
|
|
|
write: function (chunk, encoding, next) {
|
|
|
|
next();
|
2021-12-22 18:14:53 -05:00
|
|
|
},
|
2021-03-14 02:42:46 -05:00
|
|
|
});
|
2020-01-11 02:39:58 -05:00
|
|
|
|
2018-02-19 13:29:14 -05:00
|
|
|
describe('StorageTest', () => {
|
2018-06-24 15:39:09 -05:00
|
|
|
let mockRegistry;
|
2018-02-19 13:29:14 -05:00
|
|
|
|
2021-03-14 02:42:46 -05:00
|
|
|
beforeAll((done) => {
|
2019-01-28 22:54:47 -05:00
|
|
|
rimraf(storagePath, async () => {
|
|
|
|
mockRegistry = await mockServer(mockServerPort).init();
|
2021-03-14 02:42:46 -05:00
|
|
|
done();
|
|
|
|
});
|
2018-06-24 15:39:09 -05:00
|
|
|
});
|
2018-02-19 13:29:14 -05:00
|
|
|
|
2021-03-14 02:42:46 -05:00
|
|
|
afterAll(function (done) {
|
2018-06-24 15:39:09 -05:00
|
|
|
mockRegistry[0].stop();
|
|
|
|
done();
|
|
|
|
});
|
2018-02-19 13:29:14 -05:00
|
|
|
|
2018-06-24 15:39:09 -05:00
|
|
|
test('should be defined', async () => {
|
|
|
|
const storage: IStorageHandler = await generateStorage();
|
2018-02-19 13:29:14 -05:00
|
|
|
|
|
|
|
expect(storage).toBeDefined();
|
2018-06-24 15:39:09 -05:00
|
|
|
});
|
2018-02-19 13:29:14 -05:00
|
|
|
|
2020-01-11 02:39:58 -05:00
|
|
|
describe('test getTarball', () => {
|
|
|
|
test('should select right uplink given package.proxy for upstream tarballs', async (done) => {
|
|
|
|
const storage: IStorageHandler = await generateSameUplinkStorage();
|
|
|
|
const notcachedSpy = jest.spyOn(storage.uplinks.notcached, 'fetchTarball');
|
|
|
|
const cachedSpy = jest.spyOn(storage.uplinks.cached, 'fetchTarball');
|
|
|
|
|
|
|
|
await new Promise((res, rej) => {
|
|
|
|
const reader = storage.getTarball('jquery', 'jquery-1.5.1.tgz');
|
|
|
|
reader.on('end', () => {
|
|
|
|
expect(notcachedSpy).toHaveBeenCalledTimes(0);
|
|
|
|
expect(cachedSpy).toHaveBeenCalledTimes(1);
|
2023-01-18 16:49:28 -05:00
|
|
|
expect(cachedSpy).toHaveBeenCalledWith(
|
|
|
|
'http://localhost:55548/jquery/-/jquery-1.5.1.tgz'
|
|
|
|
);
|
2020-01-11 02:39:58 -05:00
|
|
|
res();
|
|
|
|
});
|
|
|
|
reader.on('error', (err) => {
|
|
|
|
rej(err);
|
|
|
|
});
|
|
|
|
reader.pipe(createNullStream());
|
|
|
|
});
|
|
|
|
|
|
|
|
// Reset counters.
|
|
|
|
cachedSpy.mockClear();
|
|
|
|
notcachedSpy.mockClear();
|
|
|
|
|
|
|
|
await new Promise((res, rej) => {
|
|
|
|
const reader = storage.getTarball('@jquery/jquery', 'jquery-1.5.1.tgz');
|
|
|
|
reader.on('end', () => {
|
|
|
|
expect(cachedSpy).toHaveBeenCalledTimes(0);
|
|
|
|
expect(notcachedSpy).toHaveBeenCalledTimes(1);
|
2023-01-18 16:49:28 -05:00
|
|
|
expect(notcachedSpy).toHaveBeenCalledWith(
|
|
|
|
'http://localhost:55548/@jquery%2fjquery/-/jquery-1.5.1.tgz'
|
|
|
|
);
|
2020-01-11 02:39:58 -05:00
|
|
|
res();
|
|
|
|
});
|
|
|
|
reader.on('error', (err) => {
|
|
|
|
rej(err);
|
|
|
|
});
|
|
|
|
reader.pipe(createNullStream());
|
|
|
|
});
|
|
|
|
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2018-06-27 01:52:52 -05:00
|
|
|
describe('test _syncUplinksMetadata', () => {
|
|
|
|
test('should fetch from uplink jquery metadata from registry', async (done) => {
|
|
|
|
const storage: IStorageHandler = await generateStorage();
|
2018-02-19 13:29:14 -05:00
|
|
|
|
2019-08-16 14:20:18 -05:00
|
|
|
// @ts-ignore
|
2019-09-26 11:22:14 -05:00
|
|
|
storage._syncUplinksMetadata('jquery', null, {}, (err, metadata) => {
|
2018-06-27 01:52:52 -05:00
|
|
|
expect(err).toBeNull();
|
|
|
|
expect(metadata).toBeDefined();
|
|
|
|
expect(metadata).toBeInstanceOf(Object);
|
|
|
|
done();
|
|
|
|
});
|
2018-06-24 15:39:09 -05:00
|
|
|
});
|
2018-02-19 13:29:14 -05:00
|
|
|
|
2018-06-27 01:52:52 -05:00
|
|
|
test('should fails on fetch from uplink non existing from registry', async (done) => {
|
|
|
|
const storage: IStorageHandler = await generateStorage();
|
|
|
|
|
2019-08-16 14:20:18 -05:00
|
|
|
// @ts-ignore
|
2018-06-27 01:52:52 -05:00
|
|
|
storage._syncUplinksMetadata('@verdaccio/404', null, {}, (err, metadata, errors) => {
|
|
|
|
expect(err).not.toBeNull();
|
|
|
|
expect(errors).toBeInstanceOf(Array);
|
|
|
|
expect(errors[0][0].statusCode).toBe(HTTP_STATUS.NOT_FOUND);
|
|
|
|
expect(errors[0][0].message).toMatch(API_ERROR.NOT_PACKAGE_UPLINK);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should fails on fetch from uplink corrupted pkg from registry', async (done) => {
|
|
|
|
const storage: IStorageHandler = await generateStorage();
|
2018-02-19 13:29:14 -05:00
|
|
|
|
2019-08-16 14:20:18 -05:00
|
|
|
// @ts-ignore
|
2018-06-27 01:52:52 -05:00
|
|
|
storage._syncUplinksMetadata('corrupted-package', null, {}, (err, metadata, errors) => {
|
|
|
|
expect(err).not.toBeNull();
|
|
|
|
expect(errors).toBeInstanceOf(Array);
|
|
|
|
expect(errors[0][0].statusCode).toBe(HTTP_STATUS.INTERNAL_ERROR);
|
|
|
|
expect(errors[0][0].message).toMatch(API_ERROR.BAD_STATUS_CODE);
|
|
|
|
done();
|
|
|
|
});
|
2018-06-24 15:39:09 -05:00
|
|
|
});
|
2019-01-28 22:54:47 -05:00
|
|
|
|
|
|
|
test('should not touch if the package exists and has no uplinks', async (done) => {
|
2021-03-14 02:42:46 -05:00
|
|
|
const storage: IStorageHandler = (await generateStorage()) as IStorageHandler;
|
2019-05-19 16:07:17 -05:00
|
|
|
const metadataSource = path.join(__dirname, '../../partials/metadata');
|
2019-01-29 22:21:36 -05:00
|
|
|
const metadataPath = path.join(storagePath, 'npm_test/package.json');
|
2019-07-16 01:40:01 -05:00
|
|
|
|
2019-01-29 22:21:36 -05:00
|
|
|
fs.mkdirSync(path.join(storagePath, 'npm_test'));
|
2019-01-29 01:03:04 -05:00
|
|
|
fs.writeFileSync(metadataPath, fs.readFileSync(metadataSource));
|
2019-01-29 22:21:36 -05:00
|
|
|
const metadata = JSON.parse(fs.readFileSync(metadataPath).toString());
|
2019-08-16 14:20:18 -05:00
|
|
|
// @ts-ignore
|
2019-01-29 22:21:36 -05:00
|
|
|
storage.localStorage.updateVersions = jest.fn(storage.localStorage.updateVersions);
|
2019-02-24 17:20:25 -05:00
|
|
|
expect(metadata).toBeDefined();
|
2019-01-28 22:54:47 -05:00
|
|
|
storage._syncUplinksMetadata('npm_test', metadata, {}, (err) => {
|
2019-01-29 22:21:36 -05:00
|
|
|
expect(err).toBeNull();
|
2019-08-16 14:20:18 -05:00
|
|
|
// @ts-ignore
|
2019-01-29 22:21:36 -05:00
|
|
|
expect(storage.localStorage.updateVersions).not.toHaveBeenCalled();
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2018-02-19 13:29:14 -05:00
|
|
|
});
|
|
|
|
});
|