@verdaccio/store 6.0.0-6-next.18 → 6.0.0-6-next.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -0
- package/build/index.d.ts +1 -0
- package/build/index.js +13 -0
- package/build/index.js.map +1 -1
- package/build/local-storage.d.ts +22 -1
- package/build/local-storage.js +240 -4
- package/build/local-storage.js.map +1 -1
- package/build/search.d.ts +0 -43
- package/build/search.js +31 -142
- package/build/search.js.map +1 -1
- package/build/star-utils.d.ts +9 -0
- package/build/star-utils.js +50 -0
- package/build/star-utils.js.map +1 -0
- package/build/storage-utils.d.ts +3 -1
- package/build/storage-utils.js +20 -5
- package/build/storage-utils.js.map +1 -1
- package/build/storage.d.ts +23 -1
- package/build/storage.js +149 -53
- package/build/storage.js.map +1 -1
- package/build/type.d.ts +10 -1
- package/package.json +14 -18
- package/src/index.ts +1 -0
- package/src/local-storage.ts +255 -4
- package/src/search.ts +21 -124
- package/src/star-utils.ts +38 -0
- package/src/storage-utils.ts +21 -6
- package/src/storage.ts +188 -62
- package/src/type.ts +11 -1
- package/test/search.spec.ts +2 -66
- package/test/storage-utils.spec.ts +95 -1
- package/test/storage.spec.ts +7 -7
package/src/storage.ts
CHANGED
|
@@ -2,16 +2,24 @@ import assert from 'assert';
|
|
|
2
2
|
import async, { AsyncResultArrayCallback } from 'async';
|
|
3
3
|
import buildDebug from 'debug';
|
|
4
4
|
import _ from 'lodash';
|
|
5
|
-
import semver from 'semver';
|
|
6
5
|
|
|
7
6
|
import { hasProxyTo } from '@verdaccio/config';
|
|
8
|
-
import {
|
|
9
|
-
|
|
7
|
+
import {
|
|
8
|
+
API_ERROR,
|
|
9
|
+
DIST_TAGS,
|
|
10
|
+
HTTP_STATUS,
|
|
11
|
+
errorUtils,
|
|
12
|
+
pkgUtils,
|
|
13
|
+
validatioUtils,
|
|
14
|
+
} from '@verdaccio/core';
|
|
10
15
|
import { logger } from '@verdaccio/logger';
|
|
11
16
|
import { ProxyStorage } from '@verdaccio/proxy';
|
|
12
17
|
import { IProxy, ProxyList } from '@verdaccio/proxy';
|
|
13
18
|
import { ReadTarball } from '@verdaccio/streams';
|
|
14
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
convertDistRemoteToLocalTarballUrls,
|
|
21
|
+
convertDistVersionToLocalTarballsUrl,
|
|
22
|
+
} from '@verdaccio/tarball';
|
|
15
23
|
import {
|
|
16
24
|
Callback,
|
|
17
25
|
CallbackAction,
|
|
@@ -32,7 +40,8 @@ import {
|
|
|
32
40
|
import { getVersion, normalizeDistTags } from '@verdaccio/utils';
|
|
33
41
|
|
|
34
42
|
import { LocalStorage } from './local-storage';
|
|
35
|
-
import {
|
|
43
|
+
import { SearchManager } from './search';
|
|
44
|
+
// import { isPublishablePackage, validateInputs } from './star-utils';
|
|
36
45
|
import {
|
|
37
46
|
checkPackageLocal,
|
|
38
47
|
checkPackageRemote,
|
|
@@ -42,12 +51,9 @@ import {
|
|
|
42
51
|
publishPackage,
|
|
43
52
|
} from './storage-utils';
|
|
44
53
|
import { IGetPackageOptions, IGetPackageOptionsNext, IPluginFilters, ISyncUplinks } from './type';
|
|
54
|
+
// import { StarBody, Users } from './type';
|
|
45
55
|
import { setupUpLinks, updateVersionsHiddenUpLink } from './uplink-util';
|
|
46
56
|
|
|
47
|
-
if (semver.lte(process.version, 'v15.0.0')) {
|
|
48
|
-
global.AbortController = require('abortcontroller-polyfill/dist/cjs-ponyfill').AbortController;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
57
|
const debug = buildDebug('verdaccio:storage');
|
|
52
58
|
class Storage {
|
|
53
59
|
public localStorage: LocalStorage;
|
|
@@ -110,6 +116,33 @@ class Storage {
|
|
|
110
116
|
}
|
|
111
117
|
}
|
|
112
118
|
|
|
119
|
+
/**
|
|
120
|
+
* Add a {name} package to a system
|
|
121
|
+
Function checks if package with the same name is available from uplinks.
|
|
122
|
+
If it isn't, we create package locally
|
|
123
|
+
Used storages: local (write) && uplinks
|
|
124
|
+
*/
|
|
125
|
+
public async addPackageNext(name: string, metadata: Package): Promise<Package> {
|
|
126
|
+
try {
|
|
127
|
+
debug('add package for %o', name);
|
|
128
|
+
await checkPackageLocal(name, this.localStorage);
|
|
129
|
+
debug('look up remote for %o', name);
|
|
130
|
+
await checkPackageRemote(
|
|
131
|
+
name,
|
|
132
|
+
this._isAllowPublishOffline(),
|
|
133
|
+
this._syncUplinksMetadata.bind(this)
|
|
134
|
+
);
|
|
135
|
+
debug('publishing a package for %o', name);
|
|
136
|
+
// FIXME: publishPackage should return fresh metadata from backend
|
|
137
|
+
// instead return metadata
|
|
138
|
+
await publishPackage(name, metadata, this.localStorage as LocalStorage);
|
|
139
|
+
return metadata;
|
|
140
|
+
} catch (err: any) {
|
|
141
|
+
debug('error on add a package for %o with error %o', name, err);
|
|
142
|
+
throw err;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
113
146
|
private _isAllowPublishOffline(): boolean {
|
|
114
147
|
return (
|
|
115
148
|
typeof this.config.publish !== 'undefined' &&
|
|
@@ -145,6 +178,16 @@ class Storage {
|
|
|
145
178
|
this.localStorage.addVersion(name, version, metadata, tag, callback);
|
|
146
179
|
}
|
|
147
180
|
|
|
181
|
+
public async addVersionNext(
|
|
182
|
+
name: string,
|
|
183
|
+
version: string,
|
|
184
|
+
metadata: Version,
|
|
185
|
+
tag: StringValue
|
|
186
|
+
): Promise<void> {
|
|
187
|
+
debug('add the version %o for package %o', version, name);
|
|
188
|
+
return this.localStorage.addVersionNext(name, version, metadata, tag);
|
|
189
|
+
}
|
|
190
|
+
|
|
148
191
|
/**
|
|
149
192
|
* Tags a package version with a provided tag
|
|
150
193
|
Used storages: local (write)
|
|
@@ -169,6 +212,16 @@ class Storage {
|
|
|
169
212
|
this.localStorage.changePackage(name, metadata, revision, callback);
|
|
170
213
|
}
|
|
171
214
|
|
|
215
|
+
/**
|
|
216
|
+
* Change an existing package (i.e. unpublish one version)
|
|
217
|
+
Function changes a package info from local storage and all uplinks with write access./
|
|
218
|
+
Used storages: local (write)
|
|
219
|
+
*/
|
|
220
|
+
public async changePackageNext(name: string, metadata: Package, revision: string): Promise<void> {
|
|
221
|
+
debug('change existing package for package %o revision %o', name, revision);
|
|
222
|
+
this.localStorage.changePackageNext(name, metadata, revision);
|
|
223
|
+
}
|
|
224
|
+
|
|
172
225
|
/**
|
|
173
226
|
* Remove a package from a system
|
|
174
227
|
Function removes a package from local storage
|
|
@@ -177,8 +230,6 @@ class Storage {
|
|
|
177
230
|
public async removePackage(name: string): Promise<void> {
|
|
178
231
|
debug('remove packagefor package %o', name);
|
|
179
232
|
await this.localStorage.removePackage(name);
|
|
180
|
-
// update the indexer
|
|
181
|
-
SearchInstance.remove(name);
|
|
182
233
|
}
|
|
183
234
|
|
|
184
235
|
/**
|
|
@@ -346,7 +397,130 @@ class Storage {
|
|
|
346
397
|
}
|
|
347
398
|
}
|
|
348
399
|
|
|
349
|
-
public async
|
|
400
|
+
// public async starPackage(body: StarBody, options: IGetPackageOptionsNext): Promise<void> {
|
|
401
|
+
// debug('star package');
|
|
402
|
+
// const manifest = await this.getPackageNext(options);
|
|
403
|
+
// const newStarUser = body[constants.USERS];
|
|
404
|
+
// const remoteUsername: string = options.remoteUser.name as string;
|
|
405
|
+
// const localStarUsers = manifest[constants.USERS];
|
|
406
|
+
// // Check is star or unstar
|
|
407
|
+
// const isStar = Object.keys(newStarUser).includes(remoteUsername);
|
|
408
|
+
// debug('is start? %o', isStar);
|
|
409
|
+
// if (
|
|
410
|
+
// _.isNil(localStarUsers) === false &&
|
|
411
|
+
// validateInputs(localStarUsers, remoteUsername, isStar)
|
|
412
|
+
// ) {
|
|
413
|
+
// // return afterChangePackage();
|
|
414
|
+
// }
|
|
415
|
+
// const users: Users = isStar
|
|
416
|
+
// ? {
|
|
417
|
+
// ...localStarUsers,
|
|
418
|
+
// [remoteUsername]: true,
|
|
419
|
+
// }
|
|
420
|
+
// : _.reduce(
|
|
421
|
+
// localStarUsers,
|
|
422
|
+
// (users, value, key) => {
|
|
423
|
+
// if (key !== remoteUsername) {
|
|
424
|
+
// users[key] = value;
|
|
425
|
+
// }
|
|
426
|
+
// return users;
|
|
427
|
+
// },
|
|
428
|
+
// {}
|
|
429
|
+
// );
|
|
430
|
+
// debug('update package for %o', name);
|
|
431
|
+
// }
|
|
432
|
+
|
|
433
|
+
// public async publish(body: any, options: IGetPackageOptionsNext): Promise<any> {
|
|
434
|
+
// const { name } = options;
|
|
435
|
+
// debug('publishing or updating a new version for %o', name);
|
|
436
|
+
// // we check if the request is npm star
|
|
437
|
+
// if (!isPublishablePackage(body) && isObject(body.users)) {
|
|
438
|
+
// debug('starting star a package');
|
|
439
|
+
// await this.starPackage(body as StarBody, options);
|
|
440
|
+
// }
|
|
441
|
+
|
|
442
|
+
// return { ok: API_MESSAGE.PKG_CHANGED, success: true };
|
|
443
|
+
// }
|
|
444
|
+
|
|
445
|
+
public async getPackageByVersion(options: IGetPackageOptionsNext): Promise<Version> {
|
|
446
|
+
const queryVersion = options.version as string;
|
|
447
|
+
if (_.isNil(queryVersion)) {
|
|
448
|
+
throw errorUtils.getNotFound(`${API_ERROR.VERSION_NOT_EXIST}: ${queryVersion}`);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// we have version, so we need to return specific version
|
|
452
|
+
const [convertedManifest] = await this.getPackageNext(options);
|
|
453
|
+
|
|
454
|
+
const version: Version | undefined = getVersion(convertedManifest.versions, queryVersion);
|
|
455
|
+
|
|
456
|
+
debug('query by latest version %o and result %o', queryVersion, version);
|
|
457
|
+
if (typeof version !== 'undefined') {
|
|
458
|
+
debug('latest version found %o', version);
|
|
459
|
+
return convertDistVersionToLocalTarballsUrl(
|
|
460
|
+
convertedManifest.name,
|
|
461
|
+
version,
|
|
462
|
+
options.requestOptions,
|
|
463
|
+
this.config.url_prefix
|
|
464
|
+
);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// the version could be a dist-tag eg: beta, alpha, so we find the matched version
|
|
468
|
+
// on disg-tag list
|
|
469
|
+
if (_.isNil(convertedManifest[DIST_TAGS]) === false) {
|
|
470
|
+
if (_.isNil(convertedManifest[DIST_TAGS][queryVersion]) === false) {
|
|
471
|
+
// the version found as a distag
|
|
472
|
+
const matchedDisTagVersion: string = convertedManifest[DIST_TAGS][queryVersion];
|
|
473
|
+
debug('dist-tag version found %o', matchedDisTagVersion);
|
|
474
|
+
const disTagVersion: Version | undefined = getVersion(
|
|
475
|
+
convertedManifest.versions,
|
|
476
|
+
matchedDisTagVersion
|
|
477
|
+
);
|
|
478
|
+
if (typeof disTagVersion !== 'undefined') {
|
|
479
|
+
debug('dist-tag found %o', disTagVersion);
|
|
480
|
+
return convertDistVersionToLocalTarballsUrl(
|
|
481
|
+
convertedManifest.name,
|
|
482
|
+
disTagVersion,
|
|
483
|
+
options.requestOptions,
|
|
484
|
+
this.config.url_prefix
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
} else {
|
|
489
|
+
debug('dist tag not detected');
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// we didn't find the version, not found error
|
|
493
|
+
debug('package version not found %o', queryVersion);
|
|
494
|
+
throw errorUtils.getNotFound(`${API_ERROR.VERSION_NOT_EXIST}: ${queryVersion}`);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
public async getPackageManifest(options: IGetPackageOptionsNext): Promise<Package> {
|
|
498
|
+
// convert dist remotes to local bars
|
|
499
|
+
const [manifest] = await this.getPackageNext(options);
|
|
500
|
+
const convertedManifest = convertDistRemoteToLocalTarballUrls(
|
|
501
|
+
manifest,
|
|
502
|
+
options.requestOptions,
|
|
503
|
+
this.config.url_prefix
|
|
504
|
+
);
|
|
505
|
+
|
|
506
|
+
return convertedManifest;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Return a manifest or version based on the options.
|
|
511
|
+
* @param options {Object}
|
|
512
|
+
* @returns A package manifest or specific version
|
|
513
|
+
*/
|
|
514
|
+
public async getPackageByOptions(options: IGetPackageOptionsNext): Promise<Package | Version> {
|
|
515
|
+
// if no version we return the whole manifest
|
|
516
|
+
if (_.isNil(options.version) === false) {
|
|
517
|
+
return this.getPackageByVersion(options);
|
|
518
|
+
} else {
|
|
519
|
+
return this.getPackageManifest(options);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
public async getPackageNext(options: IGetPackageOptionsNext): Promise<[Package, any[]]> {
|
|
350
524
|
const { name } = options;
|
|
351
525
|
debug('get package for %o', name);
|
|
352
526
|
try {
|
|
@@ -363,59 +537,11 @@ class Storage {
|
|
|
363
537
|
// time to sync with uplinks if we have any
|
|
364
538
|
debug('sync uplinks for %o', name);
|
|
365
539
|
// @ts-expect-error
|
|
366
|
-
|
|
540
|
+
return this._syncUplinksMetadataNext(name, data, {
|
|
367
541
|
req: options.req,
|
|
368
542
|
uplinksLook: options.uplinksLook,
|
|
369
543
|
keepUpLinkData: options.keepUpLinkData,
|
|
370
544
|
});
|
|
371
|
-
debug('no. sync uplinks errors %o', errors?.length);
|
|
372
|
-
|
|
373
|
-
// TODO: we could improve performance here, if a specific version is requested
|
|
374
|
-
// we just convert that version and return it otherwise we convert
|
|
375
|
-
// the whole manifest, bonus points for contribution :)
|
|
376
|
-
// convert dist remotes to local bars
|
|
377
|
-
const convertedManifest = convertDistRemoteToLocalTarballUrls(
|
|
378
|
-
manifest,
|
|
379
|
-
options.requestOptions,
|
|
380
|
-
this.config.url_prefix
|
|
381
|
-
);
|
|
382
|
-
// if no version we return the whole manifest
|
|
383
|
-
if (_.isNil(options.version)) {
|
|
384
|
-
return convertedManifest;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
// we have version, so we need to return specific version
|
|
388
|
-
const queryVersion = options.version as string;
|
|
389
|
-
const version: Version | undefined = getVersion(convertedManifest.versions, options.version);
|
|
390
|
-
debug('query by latest version %o and result %o', options.version, version);
|
|
391
|
-
if (typeof version !== 'undefined') {
|
|
392
|
-
debug('latest version found %o', version);
|
|
393
|
-
return version;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
// the version could be a dist-tag eg: beta, alpha, so we find the matched version
|
|
397
|
-
// on disg-tag list
|
|
398
|
-
if (_.isNil(convertedManifest[DIST_TAGS]) === false) {
|
|
399
|
-
if (_.isNil(convertedManifest[DIST_TAGS][queryVersion]) === false) {
|
|
400
|
-
// the version found as a distag
|
|
401
|
-
const matchedDisTagVersion: string = convertedManifest[DIST_TAGS][queryVersion];
|
|
402
|
-
debug('dist-tag version found %o', matchedDisTagVersion);
|
|
403
|
-
const disTagVersion: Version | undefined = getVersion(
|
|
404
|
-
convertedManifest.versions,
|
|
405
|
-
matchedDisTagVersion
|
|
406
|
-
);
|
|
407
|
-
if (typeof disTagVersion !== 'undefined') {
|
|
408
|
-
debug('dist-tag found %o', disTagVersion);
|
|
409
|
-
return disTagVersion;
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
} else {
|
|
413
|
-
debug('dist tag not detected');
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
// we didn't find the version, not found error
|
|
417
|
-
debug('package version not found %o', queryVersion);
|
|
418
|
-
throw errorUtils.getNotFound(`${API_ERROR.VERSION_NOT_EXIST}: ${queryVersion}`);
|
|
419
545
|
} catch (err: any) {
|
|
420
546
|
this.logger.error(
|
|
421
547
|
{ name, err: err.message },
|
|
@@ -446,7 +572,7 @@ class Storage {
|
|
|
446
572
|
_attachments: {},
|
|
447
573
|
});
|
|
448
574
|
|
|
449
|
-
debug('no. sync uplinks errors %o', uplinkErrors?.length);
|
|
575
|
+
debug('no. sync uplinks errors %o for %s', uplinkErrors?.length, name);
|
|
450
576
|
resolve([normalizedPkg, uplinkErrors]);
|
|
451
577
|
}
|
|
452
578
|
);
|
package/src/type.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Callback, Config, IPluginStorageFilter } from '@verdaccio/types';
|
|
1
|
+
import { Callback, Config, IPluginStorageFilter, RemoteUser } from '@verdaccio/types';
|
|
2
2
|
|
|
3
3
|
// @deprecated
|
|
4
4
|
export interface IGetPackageOptions {
|
|
@@ -15,6 +15,7 @@ export type IGetPackageOptionsNext = {
|
|
|
15
15
|
name: string;
|
|
16
16
|
version?: string;
|
|
17
17
|
keepUpLinkData?: boolean;
|
|
18
|
+
remoteUser?: RemoteUser;
|
|
18
19
|
uplinksLook: boolean;
|
|
19
20
|
requestOptions: {
|
|
20
21
|
// RequestOptions from url package
|
|
@@ -30,4 +31,13 @@ export interface ISyncUplinks {
|
|
|
30
31
|
req?: Request;
|
|
31
32
|
}
|
|
32
33
|
|
|
34
|
+
export type Users = {
|
|
35
|
+
[key: string]: string;
|
|
36
|
+
};
|
|
37
|
+
export interface StarBody {
|
|
38
|
+
_id: string;
|
|
39
|
+
_rev: string;
|
|
40
|
+
users: Users;
|
|
41
|
+
}
|
|
42
|
+
|
|
33
43
|
export type IPluginFilters = IPluginStorageFilter<Config>[];
|
package/test/search.spec.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { setGlobalDispatcher } from 'undici';
|
|
2
|
+
|
|
1
3
|
import { Config } from '@verdaccio/config';
|
|
2
4
|
import { searchUtils } from '@verdaccio/core';
|
|
3
5
|
import { setup } from '@verdaccio/logger';
|
|
4
6
|
import { configExample } from '@verdaccio/mock';
|
|
5
7
|
|
|
6
8
|
import { Storage, removeDuplicates } from '../src';
|
|
7
|
-
import { SearchInstance } from '../src/search';
|
|
8
9
|
|
|
9
10
|
setup([]);
|
|
10
11
|
|
|
@@ -30,7 +31,6 @@ describe('search', () => {
|
|
|
30
31
|
test('search items', async () => {
|
|
31
32
|
const { MockAgent } = require('undici');
|
|
32
33
|
// FIXME: fetch is already part of undici
|
|
33
|
-
const { setGlobalDispatcher } = require('undici-fetch');
|
|
34
34
|
const domain = 'http://localhost:4873';
|
|
35
35
|
const url = '/-/v1/search?maintenance=1&popularity=1&quality=1&size=10&text=verdaccio';
|
|
36
36
|
const response = require('./fixtures/search.json');
|
|
@@ -52,68 +52,4 @@ describe('search', () => {
|
|
|
52
52
|
expect(results).toHaveLength(4);
|
|
53
53
|
});
|
|
54
54
|
});
|
|
55
|
-
|
|
56
|
-
describe('search index', () => {
|
|
57
|
-
const packages = [
|
|
58
|
-
{
|
|
59
|
-
name: 'test1',
|
|
60
|
-
description: 'description',
|
|
61
|
-
_npmUser: {
|
|
62
|
-
name: 'test_user',
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
name: 'test2',
|
|
67
|
-
description: 'description',
|
|
68
|
-
_npmUser: {
|
|
69
|
-
name: 'test_user',
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
name: 'test3',
|
|
74
|
-
description: 'description',
|
|
75
|
-
_npmUser: {
|
|
76
|
-
name: 'test_user',
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
];
|
|
80
|
-
|
|
81
|
-
test('search query item', async () => {
|
|
82
|
-
const config = new Config(configExample());
|
|
83
|
-
const storage = new Storage(config);
|
|
84
|
-
await storage.init(config);
|
|
85
|
-
SearchInstance.configureStorage(storage);
|
|
86
|
-
packages.map(function (item) {
|
|
87
|
-
// @ts-ignore
|
|
88
|
-
SearchInstance.add(item);
|
|
89
|
-
});
|
|
90
|
-
const result = SearchInstance.query('t');
|
|
91
|
-
expect(result).toHaveLength(3);
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
test('search remove item', async () => {
|
|
95
|
-
const config = new Config(configExample());
|
|
96
|
-
const storage = new Storage(config);
|
|
97
|
-
await storage.init(config);
|
|
98
|
-
SearchInstance.configureStorage(storage);
|
|
99
|
-
packages.map(function (item) {
|
|
100
|
-
// @ts-ignore
|
|
101
|
-
SearchInstance.add(item);
|
|
102
|
-
});
|
|
103
|
-
const item = {
|
|
104
|
-
name: 'test6',
|
|
105
|
-
description: 'description',
|
|
106
|
-
_npmUser: {
|
|
107
|
-
name: 'test_user',
|
|
108
|
-
},
|
|
109
|
-
};
|
|
110
|
-
// @ts-ignore
|
|
111
|
-
SearchInstance.add(item);
|
|
112
|
-
let result = SearchInstance.query('test6');
|
|
113
|
-
expect(result).toHaveLength(1);
|
|
114
|
-
SearchInstance.remove(item.name);
|
|
115
|
-
result = SearchInstance.query('test6');
|
|
116
|
-
expect(result).toHaveLength(0);
|
|
117
|
-
});
|
|
118
|
-
});
|
|
119
55
|
});
|
|
@@ -3,7 +3,13 @@ import assert from 'assert';
|
|
|
3
3
|
import { DIST_TAGS } from '@verdaccio/core';
|
|
4
4
|
import { Package } from '@verdaccio/types';
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
STORAGE,
|
|
8
|
+
hasInvalidPublishBody,
|
|
9
|
+
isDifferentThanOne,
|
|
10
|
+
mergeUplinkTimeIntoLocal,
|
|
11
|
+
normalizePackage,
|
|
12
|
+
} from '../src/storage-utils';
|
|
7
13
|
import { tagVersion } from '../src/storage-utils';
|
|
8
14
|
import { readFile } from './fixtures/test.utils';
|
|
9
15
|
|
|
@@ -172,4 +178,92 @@ describe('Storage Utils', () => {
|
|
|
172
178
|
});
|
|
173
179
|
});
|
|
174
180
|
});
|
|
181
|
+
|
|
182
|
+
describe('isDifferentThanOne', () => {
|
|
183
|
+
test('isDifferentThanOne is true', () => {
|
|
184
|
+
expect(isDifferentThanOne({})).toBeTruthy();
|
|
185
|
+
});
|
|
186
|
+
test('isDifferentThanOne is false', () => {
|
|
187
|
+
expect(
|
|
188
|
+
isDifferentThanOne({
|
|
189
|
+
foo: 'bar',
|
|
190
|
+
})
|
|
191
|
+
).toBeFalsy();
|
|
192
|
+
});
|
|
193
|
+
test('isDifferentThanOne with two items is true', () => {
|
|
194
|
+
expect(
|
|
195
|
+
isDifferentThanOne({
|
|
196
|
+
foo: 'bar',
|
|
197
|
+
foo1: 'bar',
|
|
198
|
+
})
|
|
199
|
+
).toBeTruthy();
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
describe('hasInvalidPublishBody', () => {
|
|
204
|
+
test('should be valid', () => {
|
|
205
|
+
expect(
|
|
206
|
+
hasInvalidPublishBody({
|
|
207
|
+
_attachments: {
|
|
208
|
+
'forbidden-place-1.0.6.tgz': {
|
|
209
|
+
content_type: 'application/octet-stream',
|
|
210
|
+
data: 'foo',
|
|
211
|
+
length: 512,
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
versions: {
|
|
215
|
+
// @ts-expect-error
|
|
216
|
+
'1.0.0': {},
|
|
217
|
+
},
|
|
218
|
+
})
|
|
219
|
+
).toBeFalsy();
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
test('should be invalid due missing versions', () => {
|
|
223
|
+
expect(
|
|
224
|
+
hasInvalidPublishBody({
|
|
225
|
+
_attachments: {},
|
|
226
|
+
versions: {},
|
|
227
|
+
})
|
|
228
|
+
).toBeTruthy();
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
test('should be invalid due missing _attachments', () => {
|
|
232
|
+
expect(
|
|
233
|
+
hasInvalidPublishBody({
|
|
234
|
+
_attachments: {},
|
|
235
|
+
versions: {},
|
|
236
|
+
})
|
|
237
|
+
).toBeTruthy();
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
test('should be invalid due invalid empty versions object', () => {
|
|
241
|
+
expect(
|
|
242
|
+
hasInvalidPublishBody({
|
|
243
|
+
_attachments: {
|
|
244
|
+
'forbidden-place-1.0.6.tgz': {
|
|
245
|
+
content_type: 'application/octet-stream',
|
|
246
|
+
data: 'foo',
|
|
247
|
+
length: 512,
|
|
248
|
+
},
|
|
249
|
+
},
|
|
250
|
+
versions: {},
|
|
251
|
+
})
|
|
252
|
+
).toBeTruthy();
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
test('should be invalid due empty _attachments object', () => {
|
|
256
|
+
expect(
|
|
257
|
+
hasInvalidPublishBody({
|
|
258
|
+
_attachments: {},
|
|
259
|
+
versions: {
|
|
260
|
+
// @ts-expect-error
|
|
261
|
+
'1.0.0': {},
|
|
262
|
+
// @ts-expect-error
|
|
263
|
+
'1.0.1': {},
|
|
264
|
+
},
|
|
265
|
+
})
|
|
266
|
+
).toBeTruthy();
|
|
267
|
+
});
|
|
268
|
+
});
|
|
175
269
|
});
|
package/test/storage.spec.ts
CHANGED
|
@@ -3,9 +3,9 @@ import * as httpMocks from 'node-mocks-http';
|
|
|
3
3
|
|
|
4
4
|
import { Config } from '@verdaccio/config';
|
|
5
5
|
import { HEADERS, errorUtils } from '@verdaccio/core';
|
|
6
|
-
import { generatePackageMetadata } from '@verdaccio/helper';
|
|
7
6
|
import { setup } from '@verdaccio/logger';
|
|
8
7
|
import { configExample, generateRamdonStorage } from '@verdaccio/mock';
|
|
8
|
+
import { generatePackageMetadata } from '@verdaccio/test-helper';
|
|
9
9
|
|
|
10
10
|
import { Storage } from '../src';
|
|
11
11
|
|
|
@@ -60,7 +60,7 @@ describe('storage', () => {
|
|
|
60
60
|
const storage = new Storage(config);
|
|
61
61
|
await storage.init(config);
|
|
62
62
|
await expect(
|
|
63
|
-
storage.
|
|
63
|
+
storage.getPackageByOptions({
|
|
64
64
|
name: 'foo',
|
|
65
65
|
uplinksLook: true,
|
|
66
66
|
req,
|
|
@@ -92,7 +92,7 @@ describe('storage', () => {
|
|
|
92
92
|
const storage = new Storage(config);
|
|
93
93
|
await storage.init(config);
|
|
94
94
|
await expect(
|
|
95
|
-
storage.
|
|
95
|
+
storage.getPackageByOptions({
|
|
96
96
|
name: 'foo',
|
|
97
97
|
version: '1.0.0',
|
|
98
98
|
uplinksLook: true,
|
|
@@ -125,7 +125,7 @@ describe('storage', () => {
|
|
|
125
125
|
const storage = new Storage(config);
|
|
126
126
|
await storage.init(config);
|
|
127
127
|
await expect(
|
|
128
|
-
storage.
|
|
128
|
+
storage.getPackageByOptions({
|
|
129
129
|
name: 'foo',
|
|
130
130
|
version: 'latest',
|
|
131
131
|
uplinksLook: true,
|
|
@@ -158,7 +158,7 @@ describe('storage', () => {
|
|
|
158
158
|
const storage = new Storage(config);
|
|
159
159
|
await storage.init(config);
|
|
160
160
|
await expect(
|
|
161
|
-
storage.
|
|
161
|
+
storage.getPackageByOptions({
|
|
162
162
|
name: 'foo',
|
|
163
163
|
version: '1.0.0-does-not-exist',
|
|
164
164
|
uplinksLook: true,
|
|
@@ -193,7 +193,7 @@ describe('storage', () => {
|
|
|
193
193
|
const storage = new Storage(config);
|
|
194
194
|
await storage.init(config);
|
|
195
195
|
await expect(
|
|
196
|
-
storage.
|
|
196
|
+
storage.getPackageByOptions({
|
|
197
197
|
name: 'foo2',
|
|
198
198
|
uplinksLook: true,
|
|
199
199
|
req,
|
|
@@ -228,7 +228,7 @@ describe('storage', () => {
|
|
|
228
228
|
const storage = new Storage(config);
|
|
229
229
|
await storage.init(config);
|
|
230
230
|
await expect(
|
|
231
|
-
storage.
|
|
231
|
+
storage.getPackageByOptions({
|
|
232
232
|
name: 'foo2',
|
|
233
233
|
uplinksLook: true,
|
|
234
234
|
req,
|