mirror of
https://github.com/verdaccio/verdaccio.git
synced 2024-12-23 22:27:34 -05:00
459b6fa72b
* Refactor local-storage async refactor local storage search stream Remove async from local-storage, refactor search with streams refactor search with undici fetch finish search refactor stream multiple request to single stream refactor storage types remove async dependency #1225 add score and refactor metadata remove old search async fix missing stream local data clean up clean up refactor folder search format fix some test fix issue on publish filter preview update ci delete package folder refactor refactor get packages methods fix tests fix lock file add changeset fix test windows disable some test update package json versions * fix merge * fix e2e cli * restore e2e * Update process.ts * Update process.ts * add improvement * format * Update utils.ts * test * test * Update search.spec.ts * Update search.spec.ts * Update search.spec.ts * test * Update ci.yml * clean up * fix tests * Update tags.ts * Update index.spec.ts * document changeset * format
444 lines
13 KiB
TypeScript
444 lines
13 KiB
TypeScript
import { PackageAccess } from '@verdaccio/types';
|
|
|
|
import S3PackageManager from '../src/s3PackageManager';
|
|
import { S3Config } from '../src/config';
|
|
|
|
import logger from './__mocks__/Logger';
|
|
import pkg from './__fixtures__/pkg';
|
|
|
|
const mockHeadObject = jest.fn();
|
|
const mockPutObject = jest.fn();
|
|
const mockDeleteObject = jest.fn();
|
|
const mockListObject = jest.fn();
|
|
const mockDeleteObjects = jest.fn();
|
|
const mockGetObject = jest.fn();
|
|
|
|
jest.mock('aws-sdk', () => ({
|
|
S3: jest.fn().mockImplementation(() => ({
|
|
headObject: mockHeadObject,
|
|
putObject: mockPutObject,
|
|
deleteObject: mockDeleteObject,
|
|
listObjectsV2: mockListObject,
|
|
deleteObjects: mockDeleteObjects,
|
|
getObject: mockGetObject,
|
|
})),
|
|
}));
|
|
|
|
// TODO: fix by https://github.com/verdaccio/verdaccio/pull/2218
|
|
describe.skip('S3PackageManager with mocked s3', function () {
|
|
beforeEach(() => {
|
|
mockHeadObject.mockClear();
|
|
mockPutObject.mockClear();
|
|
mockDeleteObject.mockClear();
|
|
mockDeleteObjects.mockClear();
|
|
mockListObject.mockClear();
|
|
mockGetObject.mockClear();
|
|
});
|
|
test('existing packages on s3 are not recreated', (done) => {
|
|
expect.assertions(1);
|
|
const config: S3Config = {
|
|
bucket: 'test-bucket',
|
|
keyPrefix: 'keyPrefix/',
|
|
getMatchedPackagesSpec: jest.fn(() => null) as PackageAccess,
|
|
} as S3Config;
|
|
|
|
mockHeadObject.mockImplementation((params, callback) => {
|
|
callback();
|
|
});
|
|
|
|
const testPackageManager = new S3PackageManager(config, 'test-package', logger);
|
|
|
|
testPackageManager.createPackage('test-0.0.0.tgz', pkg, (err) => {
|
|
expect(err.message).toEqual('file already exists');
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('new package is created on s3', (done) => {
|
|
expect.assertions(2);
|
|
|
|
const config: S3Config = {
|
|
bucket: 'test-bucket',
|
|
keyPrefix: 'keyPrefix/',
|
|
getMatchedPackagesSpec: jest.fn(() => null) as PackageAccess,
|
|
} as S3Config;
|
|
|
|
mockHeadObject.mockImplementation((params, callback) => {
|
|
callback({ code: 'NoSuchKey' }, 'some data');
|
|
});
|
|
|
|
mockPutObject.mockImplementation((params, callback) => {
|
|
callback();
|
|
});
|
|
|
|
const testPackageManager = new S3PackageManager(config, 'test-package', logger);
|
|
|
|
testPackageManager.createPackage('test-0.0.0.tgz', pkg, (err) => {
|
|
expect(err).toBeUndefined();
|
|
expect(mockPutObject).toHaveBeenCalled();
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('new package is uploaded to keyprefix if custom storage is not specified', (done) => {
|
|
expect.assertions(1);
|
|
const config: S3Config = {
|
|
bucket: 'test-bucket',
|
|
keyPrefix: 'testKeyPrefix/',
|
|
getMatchedPackagesSpec: jest.fn(() => null) as PackageAccess,
|
|
} as S3Config;
|
|
|
|
mockHeadObject.mockImplementation((params, callback) => {
|
|
callback({ code: 'NoSuchKey' }, 'some data');
|
|
});
|
|
|
|
mockPutObject.mockImplementation((params, callback) => {
|
|
callback();
|
|
});
|
|
|
|
const testPackageManager = new S3PackageManager(config, 'test-package', logger);
|
|
|
|
testPackageManager.createPackage('test-0.0.0.tgz', pkg, () => {
|
|
expect(mockPutObject).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
Bucket: 'test-bucket',
|
|
Key: 'testKeyPrefix/test-package/package.json',
|
|
}),
|
|
expect.any(Function)
|
|
);
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('new package is uploaded to custom storage prefix', (done) => {
|
|
expect.assertions(2);
|
|
const config: S3Config = {
|
|
bucket: 'test-bucket',
|
|
keyPrefix: 'testKeyPrefix/',
|
|
getMatchedPackagesSpec: jest.fn(() => ({
|
|
storage: 'customFolder',
|
|
})) as PackageAccess,
|
|
} as S3Config;
|
|
|
|
mockHeadObject.mockImplementation((params, callback) => {
|
|
callback({ code: 'NoSuchKey' }, 'some data');
|
|
});
|
|
|
|
mockPutObject.mockImplementation((params, callback) => {
|
|
callback();
|
|
});
|
|
|
|
const testPackageManager = new S3PackageManager(config, '@company/test-package', logger);
|
|
|
|
testPackageManager.createPackage('test-0.0.0.tgz', pkg, () => {
|
|
expect(mockHeadObject).toHaveBeenCalledWith(
|
|
{
|
|
Bucket: 'test-bucket',
|
|
Key: 'testKeyPrefix/customFolder/@company/test-package/package.json',
|
|
},
|
|
expect.any(Function)
|
|
);
|
|
expect(mockPutObject).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
Bucket: 'test-bucket',
|
|
Key: 'testKeyPrefix/customFolder/@company/test-package/package.json',
|
|
}),
|
|
expect.any(Function)
|
|
);
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('delete package with custom folder from s3 bucket', (done) => {
|
|
expect.assertions(1);
|
|
const config: S3Config = {
|
|
bucket: 'test-bucket',
|
|
keyPrefix: 'testKeyPrefix/',
|
|
getMatchedPackagesSpec: jest.fn(() => ({
|
|
storage: 'customFolder',
|
|
})) as PackageAccess,
|
|
} as S3Config;
|
|
|
|
mockDeleteObject.mockImplementation((params, callback) => {
|
|
callback();
|
|
});
|
|
|
|
const testPackageManager = new S3PackageManager(config, '@company/test-package', logger);
|
|
|
|
testPackageManager.deletePackage('test-0.0.0.tgz', () => {
|
|
expect(mockDeleteObject).toHaveBeenCalledWith(
|
|
{
|
|
Bucket: 'test-bucket',
|
|
Key: 'testKeyPrefix/customFolder/@company/test-package/test-0.0.0.tgz',
|
|
},
|
|
expect.any(Function)
|
|
);
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('delete package from s3 bucket', (done) => {
|
|
expect.assertions(1);
|
|
const config: S3Config = {
|
|
bucket: 'test-bucket',
|
|
keyPrefix: 'testKeyPrefix/',
|
|
getMatchedPackagesSpec: jest.fn(() => ({})) as PackageAccess,
|
|
} as S3Config;
|
|
|
|
mockDeleteObject.mockImplementation((params, callback) => {
|
|
callback();
|
|
});
|
|
|
|
const testPackageManager = new S3PackageManager(config, '@company/test-package', logger);
|
|
|
|
testPackageManager.deletePackage('test-0.0.0.tgz', () => {
|
|
expect(mockDeleteObject).toHaveBeenCalledWith(
|
|
{
|
|
Bucket: 'test-bucket',
|
|
Key: 'testKeyPrefix/@company/test-package/test-0.0.0.tgz',
|
|
},
|
|
expect.any(Function)
|
|
);
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('remove packages from s3 bucket', (done) => {
|
|
expect.assertions(2);
|
|
const config: S3Config = {
|
|
bucket: 'test-bucket',
|
|
keyPrefix: 'testKeyPrefix/',
|
|
getMatchedPackagesSpec: jest.fn(() => ({})) as PackageAccess,
|
|
} as S3Config;
|
|
|
|
mockListObject.mockImplementation((params, callback) => {
|
|
callback(null, { KeyCount: 1 });
|
|
});
|
|
|
|
mockDeleteObjects.mockImplementation((params, callback) => {
|
|
callback();
|
|
});
|
|
|
|
const testPackageManager = new S3PackageManager(config, '@company/test-package', logger);
|
|
|
|
testPackageManager.removePackage(() => {
|
|
expect(mockDeleteObjects).toHaveBeenCalledWith(
|
|
{
|
|
Bucket: 'test-bucket',
|
|
Delete: { Objects: [] },
|
|
},
|
|
expect.any(Function)
|
|
);
|
|
expect(mockListObject).toHaveBeenCalledWith(
|
|
{
|
|
Bucket: 'test-bucket',
|
|
Prefix: 'testKeyPrefix/@company/test-package/',
|
|
},
|
|
expect.any(Function)
|
|
);
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('remove packages with custom storage from s3 bucket', (done) => {
|
|
expect.assertions(2);
|
|
const config: S3Config = {
|
|
bucket: 'test-bucket',
|
|
keyPrefix: 'testKeyPrefix/',
|
|
getMatchedPackagesSpec: jest.fn(() => ({
|
|
storage: 'customFolder',
|
|
})) as PackageAccess,
|
|
} as S3Config;
|
|
|
|
mockListObject.mockImplementation((params, callback) => {
|
|
callback(null, { KeyCount: 1 });
|
|
});
|
|
|
|
mockDeleteObjects.mockImplementation((params, callback) => {
|
|
callback();
|
|
});
|
|
|
|
const testPackageManager = new S3PackageManager(config, '@company/test-package', logger);
|
|
|
|
testPackageManager.removePackage(() => {
|
|
expect(mockDeleteObjects).toHaveBeenCalledWith(
|
|
{
|
|
Bucket: 'test-bucket',
|
|
Delete: { Objects: [] },
|
|
},
|
|
expect.any(Function)
|
|
);
|
|
expect(mockListObject).toHaveBeenCalledWith(
|
|
{
|
|
Bucket: 'test-bucket',
|
|
Prefix: 'testKeyPrefix/customFolder/@company/test-package/',
|
|
},
|
|
expect.any(Function)
|
|
);
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('read packages with custom storage from s3 bucket', (done) => {
|
|
expect.assertions(1);
|
|
const config: S3Config = {
|
|
bucket: 'test-bucket',
|
|
keyPrefix: 'testKeyPrefix/',
|
|
getMatchedPackagesSpec: jest.fn(() => ({
|
|
storage: 'customStorage',
|
|
})) as PackageAccess,
|
|
} as S3Config;
|
|
|
|
mockGetObject.mockImplementation((params, callback) => {
|
|
callback(null, { Body: JSON.stringify({ some: 'data' }) });
|
|
});
|
|
|
|
const testPackageManager = new S3PackageManager(config, '@company/test-package', logger);
|
|
|
|
testPackageManager.readPackage('some package', () => {
|
|
expect(mockGetObject).toHaveBeenCalledWith(
|
|
{
|
|
Bucket: 'test-bucket',
|
|
Key: 'testKeyPrefix/customStorage/@company/test-package/package.json',
|
|
},
|
|
expect.any(Function)
|
|
);
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('read packages from s3 bucket', (done) => {
|
|
expect.assertions(1);
|
|
const config: S3Config = {
|
|
bucket: 'test-bucket',
|
|
keyPrefix: 'testKeyPrefix/',
|
|
getMatchedPackagesSpec: jest.fn(() => null) as PackageAccess,
|
|
} as S3Config;
|
|
|
|
mockGetObject.mockImplementation((params, callback) => {
|
|
callback(null, { Body: JSON.stringify({ some: 'data' }) });
|
|
});
|
|
|
|
const testPackageManager = new S3PackageManager(config, '@company/test-package', logger);
|
|
|
|
testPackageManager.readPackage('some package', () => {
|
|
expect(mockGetObject).toHaveBeenCalledWith(
|
|
{
|
|
Bucket: 'test-bucket',
|
|
Key: 'testKeyPrefix/@company/test-package/package.json',
|
|
},
|
|
expect.any(Function)
|
|
);
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('read tarballs from s3 bucket', () => {
|
|
expect.assertions(1);
|
|
const config: S3Config = {
|
|
bucket: 'test-bucket',
|
|
keyPrefix: 'testKeyPrefix/',
|
|
getMatchedPackagesSpec: jest.fn(() => null) as PackageAccess,
|
|
} as S3Config;
|
|
|
|
mockGetObject.mockImplementation(() => {
|
|
return {
|
|
on: jest.fn(() => ({
|
|
createReadStream: jest.fn(() => ({
|
|
on: jest.fn(),
|
|
pipe: jest.fn(),
|
|
})),
|
|
})),
|
|
};
|
|
});
|
|
|
|
const testPackageManager = new S3PackageManager(config, '@company/test-package', logger);
|
|
|
|
testPackageManager.readTarball('tarballfile.gz');
|
|
|
|
expect(mockGetObject).toHaveBeenCalledWith({
|
|
Bucket: 'test-bucket',
|
|
Key: 'testKeyPrefix/@company/test-package/tarballfile.gz',
|
|
});
|
|
});
|
|
|
|
test('read tarballs for a custom folder from s3 bucket', () => {
|
|
expect.assertions(1);
|
|
const config: S3Config = {
|
|
bucket: 'test-bucket',
|
|
keyPrefix: 'testKeyPrefix/',
|
|
getMatchedPackagesSpec: jest.fn(() => ({
|
|
storage: 'customStorage',
|
|
})) as PackageAccess,
|
|
} as S3Config;
|
|
|
|
mockGetObject.mockImplementation(() => {
|
|
return {
|
|
on: jest.fn(() => ({
|
|
createReadStream: jest.fn(() => ({
|
|
on: jest.fn(),
|
|
pipe: jest.fn(),
|
|
})),
|
|
})),
|
|
};
|
|
});
|
|
|
|
const testPackageManager = new S3PackageManager(config, '@company/test-package', logger);
|
|
|
|
testPackageManager.readTarball('tarballfile.gz');
|
|
|
|
expect(mockGetObject).toHaveBeenCalledWith({
|
|
Bucket: 'test-bucket',
|
|
Key: 'testKeyPrefix/customStorage/@company/test-package/tarballfile.gz',
|
|
});
|
|
});
|
|
|
|
test('write tarballs from s3 bucket', () => {
|
|
expect.assertions(1);
|
|
|
|
const config: S3Config = {
|
|
bucket: 'test-bucket',
|
|
keyPrefix: 'testKeyPrefix/',
|
|
getMatchedPackagesSpec: jest.fn(() => null) as PackageAccess,
|
|
} as S3Config;
|
|
|
|
mockHeadObject.mockImplementation(() => {});
|
|
|
|
const testPackageManager = new S3PackageManager(config, '@company/test-package', logger);
|
|
|
|
testPackageManager.writeTarball('tarballfile.gz');
|
|
|
|
expect(mockHeadObject).toHaveBeenCalledWith(
|
|
{
|
|
Bucket: 'test-bucket',
|
|
Key: 'testKeyPrefix/@company/test-package/tarballfile.gz',
|
|
},
|
|
expect.any(Function)
|
|
);
|
|
});
|
|
|
|
test('write tarballs with custom storage from s3 bucket', () => {
|
|
expect.assertions(1);
|
|
const config: S3Config = {
|
|
bucket: 'test-bucket',
|
|
keyPrefix: 'testKeyPrefix/',
|
|
getMatchedPackagesSpec: jest.fn(() => ({
|
|
storage: 'customStorage',
|
|
})) as PackageAccess,
|
|
} as S3Config;
|
|
|
|
const testPackageManager = new S3PackageManager(config, '@company/test-package', logger);
|
|
|
|
mockHeadObject.mockImplementation(() => {});
|
|
|
|
testPackageManager.writeTarball('tarballfile.gz');
|
|
|
|
expect(mockHeadObject).toHaveBeenCalledWith(
|
|
{
|
|
Bucket: 'test-bucket',
|
|
Key: 'testKeyPrefix/customStorage/@company/test-package/tarballfile.gz',
|
|
},
|
|
expect.any(Function)
|
|
);
|
|
});
|
|
});
|