@verdaccio/store 6.0.0-6-next.21 → 6.0.0-6-next.24
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 +92 -0
- package/build/index.d.ts +5 -4
- package/build/index.js +31 -15
- package/build/index.js.map +1 -1
- package/build/lib/TransFormResults.d.ts +15 -0
- package/build/lib/TransFormResults.js +61 -0
- package/build/lib/TransFormResults.js.map +1 -0
- package/build/lib/search-utils.d.ts +4 -0
- package/build/lib/search-utils.js +59 -0
- package/build/lib/search-utils.js.map +1 -0
- package/build/lib/star-utils.d.ts +14 -0
- package/build/{star-utils.js → lib/star-utils.js} +16 -2
- package/build/lib/star-utils.js.map +1 -0
- package/build/lib/storage-utils.d.ts +82 -0
- package/build/{storage-utils.js → lib/storage-utils.js} +173 -60
- package/build/lib/storage-utils.js.map +1 -0
- package/build/lib/uplink-util.d.ts +10 -0
- package/build/lib/uplink-util.js +49 -0
- package/build/lib/uplink-util.js.map +1 -0
- package/build/lib/versions-utils.d.ts +28 -0
- package/build/lib/versions-utils.js +104 -0
- package/build/lib/versions-utils.js.map +1 -0
- package/build/local-storage.d.ts +3 -165
- package/build/local-storage.js +6 -1166
- package/build/local-storage.js.map +1 -1
- package/build/storage.d.ts +242 -86
- package/build/storage.js +1681 -548
- package/build/storage.js.map +1 -1
- package/build/type.d.ts +42 -19
- package/build/type.js.map +1 -1
- package/jest.config.js +8 -2
- package/package.json +71 -71
- package/src/index.ts +5 -4
- package/src/lib/TransFormResults.ts +42 -0
- package/src/lib/search-utils.ts +50 -0
- package/src/{star-utils.ts → lib/star-utils.ts} +16 -5
- package/src/lib/storage-utils.ts +362 -0
- package/src/lib/uplink-util.ts +41 -0
- package/src/lib/versions-utils.ts +87 -0
- package/src/local-storage.ts +7 -1217
- package/src/storage.ts +1683 -635
- package/src/type.ts +47 -21
- package/test/fixtures/config/getTarballNext-getupstream.yaml +17 -0
- package/test/fixtures/config/syncDoubleUplinksMetadata.yaml +25 -0
- package/test/fixtures/config/syncNoUplinksMetadata.yaml +17 -0
- package/test/fixtures/config/syncSingleUplinksMetadata.yaml +21 -0
- package/test/fixtures/config/updateManifest-1.yaml +16 -0
- package/test/fixtures/manifests/foo-npmjs.json +253 -0
- package/test/fixtures/manifests/foo-verdaccio.json +253 -0
- package/test/fixtures/tarball.tgz +0 -0
- package/test/helpers.ts +22 -0
- package/test/local-store.__disabled__.ts +553 -0
- package/test/search.spec.ts +4 -5
- package/test/star.spec.ts +31 -0
- package/test/storage-utils.spec.ts +129 -42
- package/test/storage.spec.ts +943 -33
- package/test/versions.spec.ts +109 -0
- package/tsconfig.json +6 -3
- package/build/search.d.ts +0 -35
- package/build/search.js +0 -198
- package/build/search.js.map +0 -1
- package/build/star-utils.d.ts +0 -9
- package/build/star-utils.js.map +0 -1
- package/build/storage-utils.d.ts +0 -39
- package/build/storage-utils.js.map +0 -1
- package/build/uplink-util.d.ts +0 -7
- package/build/uplink-util.js +0 -38
- package/build/uplink-util.js.map +0 -1
- package/src/search.ts +0 -175
- package/src/storage-utils.ts +0 -263
- package/src/uplink-util.ts +0 -32
- package/test/local-storage.spec.ts +0 -583
package/package.json
CHANGED
|
@@ -1,72 +1,72 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
2
|
+
"name": "@verdaccio/store",
|
|
3
|
+
"version": "6.0.0-6-next.24",
|
|
4
|
+
"description": "loaders logic",
|
|
5
|
+
"main": "./build/index.js",
|
|
6
|
+
"types": "build/index.d.ts",
|
|
7
|
+
"author": {
|
|
8
|
+
"name": "Juan Picado",
|
|
9
|
+
"email": "juanpicado19@gmail.com"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "https",
|
|
13
|
+
"url": "https://github.com/verdaccio/verdaccio"
|
|
14
|
+
},
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"homepage": "https://verdaccio.org",
|
|
17
|
+
"keywords": [
|
|
18
|
+
"private",
|
|
19
|
+
"package",
|
|
20
|
+
"repository",
|
|
21
|
+
"registry",
|
|
22
|
+
"enterprise",
|
|
23
|
+
"modules",
|
|
24
|
+
"proxy",
|
|
25
|
+
"server",
|
|
26
|
+
"verdaccio"
|
|
27
|
+
],
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=16",
|
|
30
|
+
"npm": ">=6"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@verdaccio/config": "6.0.0-6-next.15",
|
|
34
|
+
"@verdaccio/core": "6.0.0-6-next.6",
|
|
35
|
+
"@verdaccio/hooks": "6.0.0-6-next.14",
|
|
36
|
+
"@verdaccio/loaders": "6.0.0-6-next.13",
|
|
37
|
+
"@verdaccio/local-storage": "11.0.0-6-next.14",
|
|
38
|
+
"@verdaccio/logger": "6.0.0-6-next.12",
|
|
39
|
+
"@verdaccio/proxy": "6.0.0-6-next.22",
|
|
40
|
+
"@verdaccio/url": "11.0.0-6-next.10",
|
|
41
|
+
"@verdaccio/utils": "6.0.0-6-next.12",
|
|
42
|
+
"@verdaccio/tarball": "11.0.0-6-next.13",
|
|
43
|
+
"JSONStream": "1.3.5",
|
|
44
|
+
"debug": "4.3.4",
|
|
45
|
+
"lodash": "4.17.21",
|
|
46
|
+
"merge2": "1.4.1",
|
|
47
|
+
"semver": "7.3.7"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/node": "16.11.51",
|
|
51
|
+
"@verdaccio/types": "11.0.0-6-next.14",
|
|
52
|
+
"@verdaccio/test-helper": "1.1.0-6-next.2",
|
|
53
|
+
"undici": "4.16.0",
|
|
54
|
+
"nock": "13.2.9",
|
|
55
|
+
"node-mocks-http": "1.11.0",
|
|
56
|
+
"mockdate": "3.0.5"
|
|
57
|
+
},
|
|
58
|
+
"funding": {
|
|
59
|
+
"type": "opencollective",
|
|
60
|
+
"url": "https://opencollective.com/verdaccio"
|
|
61
|
+
},
|
|
62
|
+
"scripts": {
|
|
63
|
+
"clean": "rimraf ./build",
|
|
64
|
+
"test": "jest",
|
|
65
|
+
"type-check": "tsc --noEmit -p tsconfig.build.json",
|
|
66
|
+
"build:types": "tsc --emitDeclarationOnly -p tsconfig.build.json",
|
|
67
|
+
"build:js": "babel src/ --out-dir build/ --copy-files --extensions \".ts,.tsx\" --source-maps",
|
|
68
|
+
"watch": "pnpm build:js -- --watch",
|
|
69
|
+
"build": "pnpm run build:js && pnpm run build:types"
|
|
70
|
+
},
|
|
71
|
+
"readme": "# @verdaccio/store\n\n[](https://opencollective.com/verdaccio)\n[](https://stackshare.io/verdaccio)\n[](https://github.com/verdaccio/verdaccio/blob/master/LICENSE)\n[](https://crowdin.com/project/verdaccio)\n[](https://www.tickgit.com/browse?repo=github.com/verdaccio/verdaccio)\n\n[](https://twitter.com/verdaccio_npm)\n[](https://github.com/verdaccio/verdaccio/stargazers)\n\n## Donations\n\nVerdaccio is run by **volunteers**; nobody is working full-time on it. If you find this project to be useful and would like to support its development, consider making a donation - **your logo might end up in this readme.** 😉\n\n**[Donate](https://opencollective.com/verdaccio)** 💵👍🏻 starting from _\\$1/month_ or just one single contribution.\n\n## Report a vulnerability\n\nIf you want to report a security vulnerability, please follow the steps which we have defined for you in our [security policy](https://github.com/verdaccio/verdaccio/security/policy).\n\n## Open Collective Sponsors\n\nSupport this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/verdaccio#sponsor)]\n\n[](https://opencollective.com/verdaccio/sponsor/0/website)\n[](https://opencollective.com/verdaccio/sponsor/1/website)\n[](https://opencollective.com/verdaccio/sponsor/2/website)\n[](https://opencollective.com/verdaccio/sponsor/3/website)\n[](https://opencollective.com/verdaccio/sponsor/4/website)\n[](https://opencollective.com/verdaccio/sponsor/5/website)\n[](https://opencollective.com/verdaccio/sponsor/6/website)\n[](https://opencollective.com/verdaccio/sponsor/7/website)\n[](https://opencollective.com/verdaccio/sponsor/8/website)\n[](https://opencollective.com/verdaccio/sponsor/9/website)\n\n## Open Collective Backers\n\nThank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/verdaccio#backer)]\n\n[](https://opencollective.com/verdaccio#backers)\n\n## Special Thanks\n\nThanks to the following companies to help us to achieve our goals providing free open source licenses.\n\n[](https://www.jetbrains.com/)\n[](https://crowdin.com/)\n[](https://balsamiq.com/)\n\n## Contributors\n\nThis project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].\n\n[](../../graphs/contributors)\n\n### FAQ / Contact / Troubleshoot\n\nIf you have any issue you can try the following options, do no desist to ask or check our issues database, perhaps someone has asked already what you are looking for.\n\n- [Blog](https://verdaccio.org/blog/)\n- [Donations](https://opencollective.com/verdaccio)\n- [Reporting an issue](https://github.com/verdaccio/verdaccio/blob/master/CONTRIBUTING.md#reporting-a-bug)\n- [Running discussions](https://github.com/verdaccio/verdaccio/issues?q=is%3Aissue+is%3Aopen+label%3Adiscuss)\n- [Chat](http://chat.verdaccio.org/)\n- [Logos](https://verdaccio.org/docs/en/logo)\n- [Docker Examples](https://github.com/verdaccio/docker-examples)\n- [FAQ](https://github.com/verdaccio/verdaccio/issues?utf8=%E2%9C%93&q=is%3Aissue%20label%3Aquestion%20)\n\n### License\n\nVerdaccio is [MIT licensed](https://github.com/verdaccio/verdaccio/blob/master/LICENSE)\n\nThe Verdaccio documentation and logos (excluding /thanks, e.g., .md, .png, .sketch) files within the /assets folder) is\n[Creative Commons licensed](https://github.com/verdaccio/verdaccio/blob/master/LICENSE-docs).\n"
|
|
72
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export
|
|
2
|
-
export * from './storage-utils';
|
|
3
|
-
export * from './
|
|
4
|
-
export * from './
|
|
1
|
+
export { Storage } from './storage';
|
|
2
|
+
export * from './lib/storage-utils';
|
|
3
|
+
export * from './lib/search-utils';
|
|
4
|
+
export * from './lib/versions-utils';
|
|
5
|
+
export * from './lib/star-utils';
|
|
5
6
|
export * from './type';
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import buildDebug from 'debug';
|
|
2
|
+
import _ from 'lodash';
|
|
3
|
+
import { Transform } from 'stream';
|
|
4
|
+
|
|
5
|
+
import { searchUtils } from '@verdaccio/core';
|
|
6
|
+
|
|
7
|
+
const debug = buildDebug('verdaccio:storage:search:transform');
|
|
8
|
+
|
|
9
|
+
export class TransFormResults extends Transform {
|
|
10
|
+
public constructor(options) {
|
|
11
|
+
super(options);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Transform either array of packages or a single package into a stream of packages.
|
|
16
|
+
* From uplinks the chunks are array but from local packages are objects.
|
|
17
|
+
* @param {string} chunk
|
|
18
|
+
* @param {string} encoding
|
|
19
|
+
* @param {function} done
|
|
20
|
+
* @returns {void}
|
|
21
|
+
* @override
|
|
22
|
+
*/
|
|
23
|
+
public _transform(chunk, _encoding, callback) {
|
|
24
|
+
if (_.isArray(chunk)) {
|
|
25
|
+
// from remotes we should expect chunks as arrays
|
|
26
|
+
(chunk as searchUtils.SearchItem[])
|
|
27
|
+
.filter((pkgItem) => {
|
|
28
|
+
debug(`streaming remote pkg name ${pkgItem?.package?.name}`);
|
|
29
|
+
return true;
|
|
30
|
+
})
|
|
31
|
+
.forEach((pkgItem) => {
|
|
32
|
+
this.push({ ...pkgItem, verdaccioPkgCached: false, verdaccioPrivate: false });
|
|
33
|
+
});
|
|
34
|
+
return callback();
|
|
35
|
+
} else {
|
|
36
|
+
// local we expect objects
|
|
37
|
+
debug(`streaming local pkg name ${chunk?.package?.name}`);
|
|
38
|
+
this.push(chunk);
|
|
39
|
+
return callback();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { orderBy } from 'lodash';
|
|
2
|
+
|
|
3
|
+
import { pkgUtils, searchUtils } from '@verdaccio/core';
|
|
4
|
+
import { Manifest, Version } from '@verdaccio/types';
|
|
5
|
+
|
|
6
|
+
export function removeDuplicates(results: searchUtils.SearchPackageItem[]) {
|
|
7
|
+
const pkgNames: any[] = [];
|
|
8
|
+
const orderByResults = orderBy(results, ['verdaccioPrivate', 'asc']);
|
|
9
|
+
return orderByResults.filter((pkg) => {
|
|
10
|
+
if (pkgNames.includes(pkg?.package?.name)) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
pkgNames.push(pkg?.package?.name);
|
|
14
|
+
return true;
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function mapManifestToSearchPackageBody(
|
|
19
|
+
pkg: Manifest,
|
|
20
|
+
searchItem: searchUtils.SearchItem
|
|
21
|
+
): searchUtils.SearchPackageBody {
|
|
22
|
+
const latest = pkgUtils.getLatest(pkg);
|
|
23
|
+
const version: Version = pkg.versions[latest];
|
|
24
|
+
const result: searchUtils.SearchPackageBody = {
|
|
25
|
+
name: version.name,
|
|
26
|
+
scope: '',
|
|
27
|
+
description: version.description,
|
|
28
|
+
version: latest,
|
|
29
|
+
keywords: version.keywords,
|
|
30
|
+
date: pkg.time[latest],
|
|
31
|
+
// FIXME: type
|
|
32
|
+
author: version.author as any,
|
|
33
|
+
// FIXME: not possible fill this out from a private package
|
|
34
|
+
publisher: {},
|
|
35
|
+
// FIXME: type
|
|
36
|
+
maintainers: version.maintainers as any,
|
|
37
|
+
links: {
|
|
38
|
+
npm: '',
|
|
39
|
+
homepage: version.homepage,
|
|
40
|
+
repository: version.repository,
|
|
41
|
+
bugs: version.bugs,
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
if (typeof searchItem.package.scoped === 'string') {
|
|
46
|
+
result.scope = searchItem.package.scoped;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
@@ -1,21 +1,28 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { validatioUtils } from '@verdaccio/core';
|
|
4
|
+
import { Manifest } from '@verdaccio/types';
|
|
4
5
|
|
|
5
|
-
import { Users } from '
|
|
6
|
+
import { Users } from '../type';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Check whether the package metadta has enough data to be published
|
|
9
10
|
* @param pkg metadata
|
|
10
11
|
*/
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Check whether the package metadta has enough data to be published
|
|
15
|
+
* @param pkg metadata
|
|
16
|
+
*/
|
|
17
|
+
export function isPublishablePackage(pkg: Manifest): boolean {
|
|
18
|
+
// TODO: we can do better, no need get keys
|
|
13
19
|
const keys: string[] = Object.keys(pkg);
|
|
14
20
|
|
|
15
|
-
return
|
|
21
|
+
return keys.includes('versions');
|
|
16
22
|
}
|
|
17
23
|
|
|
18
|
-
|
|
24
|
+
// @deprecated don't think this is used anymore (REMOVE)
|
|
25
|
+
export function isRelatedToDeprecation(pkgInfo: Manifest): boolean {
|
|
19
26
|
const { versions } = pkgInfo;
|
|
20
27
|
for (const version in versions) {
|
|
21
28
|
if (Object.prototype.hasOwnProperty.call(versions[version], 'deprecated')) {
|
|
@@ -36,3 +43,7 @@ export function validateInputs(localUsers: Users, username: string, isStar: bool
|
|
|
36
43
|
}
|
|
37
44
|
return false;
|
|
38
45
|
}
|
|
46
|
+
|
|
47
|
+
export function isStarManifest(manifest: Manifest): boolean {
|
|
48
|
+
return isPublishablePackage(manifest) === false && validatioUtils.isObject(manifest.users);
|
|
49
|
+
}
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
2
|
+
import semver from 'semver';
|
|
3
|
+
|
|
4
|
+
import { errorUtils, pkgUtils, validatioUtils } from '@verdaccio/core';
|
|
5
|
+
import { API_ERROR, DIST_TAGS, HTTP_STATUS, USERS } from '@verdaccio/core';
|
|
6
|
+
import { AttachMents, Manifest, Version, Versions } from '@verdaccio/types';
|
|
7
|
+
import { generateRandomHexString, isNil, isObject } from '@verdaccio/utils';
|
|
8
|
+
|
|
9
|
+
import { sortVersionsAndFilterInvalid } from './versions-utils';
|
|
10
|
+
|
|
11
|
+
export const STORAGE = {
|
|
12
|
+
PACKAGE_FILE_NAME: 'package.json',
|
|
13
|
+
FILE_EXIST_ERROR: 'EEXISTS',
|
|
14
|
+
NO_SUCH_FILE_ERROR: 'ENOENT',
|
|
15
|
+
DEFAULT_REVISION: '0-0000000000000000',
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Create a new package in the storage, return a boilerplate package
|
|
20
|
+
* @param name package name
|
|
21
|
+
* @returns {Manifest}
|
|
22
|
+
*/
|
|
23
|
+
export function generatePackageTemplate(name: string): Manifest {
|
|
24
|
+
return {
|
|
25
|
+
// standard things
|
|
26
|
+
name,
|
|
27
|
+
versions: {},
|
|
28
|
+
time: {},
|
|
29
|
+
[USERS]: {},
|
|
30
|
+
[DIST_TAGS]: {},
|
|
31
|
+
_uplinks: {},
|
|
32
|
+
_distfiles: {},
|
|
33
|
+
_attachments: {},
|
|
34
|
+
_rev: '',
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Normalize package properties, tags, revision id.
|
|
40
|
+
* @param {Object} pkg package reference.
|
|
41
|
+
*/
|
|
42
|
+
export function normalizePackage(pkg: Manifest): Manifest {
|
|
43
|
+
const pkgProperties = ['versions', 'dist-tags', '_distfiles', '_attachments', '_uplinks', 'time'];
|
|
44
|
+
|
|
45
|
+
pkgProperties.forEach((key): void => {
|
|
46
|
+
const pkgProp = pkg[key];
|
|
47
|
+
|
|
48
|
+
if (isNil(pkgProp) || validatioUtils.isObject(pkgProp) === false) {
|
|
49
|
+
pkg[key] = {};
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
if (typeof pkg?._rev !== 'string') {
|
|
54
|
+
pkg._rev = STORAGE.DEFAULT_REVISION;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (typeof pkg?._id !== 'string') {
|
|
58
|
+
pkg._id = pkg.name;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// normalize dist-tags
|
|
62
|
+
return normalizeDistTags(pkg);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function generateRevision(rev: string): string {
|
|
66
|
+
const _rev = rev.split('-');
|
|
67
|
+
|
|
68
|
+
return (+_rev[0] || 0) + 1 + '-' + generateRandomHexString();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function getLatestReadme(pkg: Manifest): string {
|
|
72
|
+
const versions = pkg['versions'] || {};
|
|
73
|
+
const distTags = pkg[DIST_TAGS] || {};
|
|
74
|
+
// FIXME: here is a bit tricky add the types
|
|
75
|
+
const latestVersion: Version | any = distTags['latest'] ? versions[distTags['latest']] || {} : {};
|
|
76
|
+
let readme = _.trim(pkg.readme || latestVersion.readme || '');
|
|
77
|
+
if (readme) {
|
|
78
|
+
return readme;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// In case of empty readme - trying to get ANY readme in the following order:
|
|
82
|
+
// 'next','beta','alpha','test','dev','canary'
|
|
83
|
+
const readmeDistTagsPriority = ['next', 'beta', 'alpha', 'test', 'dev', 'canary'];
|
|
84
|
+
readmeDistTagsPriority.forEach(function (tag): string | void {
|
|
85
|
+
if (readme) {
|
|
86
|
+
return readme;
|
|
87
|
+
}
|
|
88
|
+
const version: Version | any = distTags[tag] ? versions[distTags[tag]] || {} : {};
|
|
89
|
+
readme = _.trim(version.readme || readme);
|
|
90
|
+
});
|
|
91
|
+
return readme;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// FIXME: type any due this
|
|
95
|
+
export function cleanUpReadme(version: any): Version {
|
|
96
|
+
if (isNil(version) === false) {
|
|
97
|
+
delete version.readme;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return version;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export const WHITELIST = [
|
|
104
|
+
'_rev',
|
|
105
|
+
'name',
|
|
106
|
+
'versions',
|
|
107
|
+
'dist-tags',
|
|
108
|
+
'readme',
|
|
109
|
+
'time',
|
|
110
|
+
'_id',
|
|
111
|
+
'users',
|
|
112
|
+
];
|
|
113
|
+
|
|
114
|
+
export function cleanUpLinksRef(result: Manifest, keepUpLinkData?: boolean): Manifest {
|
|
115
|
+
const propertyToKeep = [...WHITELIST];
|
|
116
|
+
if (keepUpLinkData === true) {
|
|
117
|
+
propertyToKeep.push('_uplinks');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
for (const i in result) {
|
|
121
|
+
if (propertyToKeep.indexOf(i) === -1) {
|
|
122
|
+
// Remove sections like '_uplinks' from response
|
|
123
|
+
delete result[i];
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return result;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// TODO: move to abstract storage
|
|
131
|
+
// @deprecated use abstract.storage.ts:checkPackageRemote
|
|
132
|
+
export function checkPackageRemote(
|
|
133
|
+
name: string,
|
|
134
|
+
isAllowPublishOffline: boolean,
|
|
135
|
+
syncMetadata: Function
|
|
136
|
+
): Promise<any> {
|
|
137
|
+
return new Promise<void>((resolve, reject): void => {
|
|
138
|
+
syncMetadata(name, null, {}, (err, packageJsonLocal, upLinksErrors): void => {
|
|
139
|
+
// something weird
|
|
140
|
+
if (err && err.status !== HTTP_STATUS.NOT_FOUND) {
|
|
141
|
+
return reject(err);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// checking package exist already
|
|
145
|
+
if (isNil(packageJsonLocal) === false) {
|
|
146
|
+
return reject(errorUtils.getConflict(API_ERROR.PACKAGE_EXIST));
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
for (let errorItem = 0; errorItem < upLinksErrors.length; errorItem++) {
|
|
150
|
+
// checking error
|
|
151
|
+
// if uplink fails with a status other than 404, we report failure
|
|
152
|
+
if (isNil(upLinksErrors[errorItem][0]) === false) {
|
|
153
|
+
if (upLinksErrors[errorItem][0].status !== HTTP_STATUS.NOT_FOUND) {
|
|
154
|
+
if (isAllowPublishOffline) {
|
|
155
|
+
return resolve();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return reject(errorUtils.getServiceUnavailable(API_ERROR.UPLINK_OFFLINE_PUBLISH));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return resolve();
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// @deprecated use export function mergeUplinkTimeIntoLocalNext
|
|
169
|
+
export function mergeUplinkTimeIntoLocal(localMetadata: Manifest, remoteMetadata: Manifest): any {
|
|
170
|
+
if ('time' in remoteMetadata) {
|
|
171
|
+
return Object.assign({}, localMetadata.time, remoteMetadata.time);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return localMetadata.time;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export function mergeUplinkTimeIntoLocalNext(
|
|
178
|
+
cacheManifest: Manifest,
|
|
179
|
+
remoteManifest: Manifest
|
|
180
|
+
): Manifest {
|
|
181
|
+
if ('time' in remoteManifest) {
|
|
182
|
+
// remote override cache time conflicts
|
|
183
|
+
return { ...cacheManifest, time: { ...cacheManifest.time, ...remoteManifest.time } };
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return cacheManifest;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export function updateUpLinkMetadata(uplinkId, manifest: Manifest, etag: string) {
|
|
190
|
+
const _uplinks = {
|
|
191
|
+
...manifest._uplinks,
|
|
192
|
+
[uplinkId]: {
|
|
193
|
+
etag,
|
|
194
|
+
fetched: Date.now(),
|
|
195
|
+
},
|
|
196
|
+
};
|
|
197
|
+
return {
|
|
198
|
+
...manifest,
|
|
199
|
+
_uplinks,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export function prepareSearchPackage(data: Manifest): any {
|
|
204
|
+
const latest = pkgUtils.getLatest(data);
|
|
205
|
+
|
|
206
|
+
if (latest && data.versions[latest]) {
|
|
207
|
+
const version: Version = data.versions[latest];
|
|
208
|
+
const versions: any = { [latest]: 'latest' };
|
|
209
|
+
const pkg: any = {
|
|
210
|
+
name: version.name,
|
|
211
|
+
description: version.description,
|
|
212
|
+
[DIST_TAGS]: { latest },
|
|
213
|
+
maintainers: version.maintainers || [version.author].filter(Boolean),
|
|
214
|
+
author: version.author,
|
|
215
|
+
repository: version.repository,
|
|
216
|
+
readmeFilename: version.readmeFilename || '',
|
|
217
|
+
homepage: version.homepage,
|
|
218
|
+
keywords: version.keywords,
|
|
219
|
+
bugs: version.bugs,
|
|
220
|
+
license: version.license,
|
|
221
|
+
// time: {
|
|
222
|
+
// modified: time,
|
|
223
|
+
// },
|
|
224
|
+
versions,
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
return pkg;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export function isDifferentThanOne(versions: Versions | AttachMents): boolean {
|
|
232
|
+
return Object.keys(versions).length !== 1;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// @deprecated use validationUtils.validatePublishNewPackage
|
|
236
|
+
export function hasInvalidPublishBody(manifest: Pick<Manifest, '_attachments' | 'versions'>) {
|
|
237
|
+
if (!manifest) {
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const { _attachments, versions } = manifest;
|
|
242
|
+
const res =
|
|
243
|
+
isObject(_attachments) === false ||
|
|
244
|
+
isDifferentThanOne(_attachments) ||
|
|
245
|
+
isObject(versions) === false ||
|
|
246
|
+
isDifferentThanOne(versions);
|
|
247
|
+
return res;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Function gets a local info and an info from uplinks and tries to merge it
|
|
252
|
+
exported for unit tests only.
|
|
253
|
+
* @param {*} local
|
|
254
|
+
* @param {*} remoteManifest
|
|
255
|
+
* @param {*} config configuration file
|
|
256
|
+
*/
|
|
257
|
+
export function mergeVersions(cacheManifest: Manifest, remoteManifest: Manifest): Manifest {
|
|
258
|
+
let _cacheManifest = { ...cacheManifest };
|
|
259
|
+
const { versions, time } = remoteManifest;
|
|
260
|
+
// copy new versions to a cache
|
|
261
|
+
// NOTE: if a certain version was updated, we can't refresh it reliably
|
|
262
|
+
for (const i in versions) {
|
|
263
|
+
if (typeof cacheManifest.versions[i] === 'undefined') {
|
|
264
|
+
_cacheManifest.versions[i] = versions[i];
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
for (const i in time) {
|
|
269
|
+
if (typeof cacheManifest.time[i] === 'undefined') {
|
|
270
|
+
_cacheManifest.time[i] = time[i];
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
for (const distTag in remoteManifest[DIST_TAGS]) {
|
|
275
|
+
if (_cacheManifest[DIST_TAGS][distTag] !== remoteManifest[DIST_TAGS][distTag]) {
|
|
276
|
+
if (
|
|
277
|
+
!_cacheManifest[DIST_TAGS][distTag] ||
|
|
278
|
+
semver.lte(_cacheManifest[DIST_TAGS][distTag], remoteManifest[DIST_TAGS][distTag])
|
|
279
|
+
) {
|
|
280
|
+
_cacheManifest[DIST_TAGS][distTag] = remoteManifest[DIST_TAGS][distTag];
|
|
281
|
+
}
|
|
282
|
+
if (
|
|
283
|
+
distTag === 'latest' &&
|
|
284
|
+
_cacheManifest[DIST_TAGS][distTag] === remoteManifest[DIST_TAGS][distTag]
|
|
285
|
+
) {
|
|
286
|
+
// NOTE: this override the latest publish readme from local cache with
|
|
287
|
+
// the remote one
|
|
288
|
+
cacheManifest = { ..._cacheManifest, readme: remoteManifest.readme };
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return cacheManifest;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Normalize dist-tags.
|
|
298
|
+
*
|
|
299
|
+
* There is a legacy behaviour where the dist-tags could be an array, in such
|
|
300
|
+
* case, the array is orderded and the highest version becames the
|
|
301
|
+
* latest.
|
|
302
|
+
*
|
|
303
|
+
* The dist-tag tags must be plain strigs, if the latest is empty (for whatever reason) is
|
|
304
|
+
* normalized to be the highest version available.
|
|
305
|
+
*
|
|
306
|
+
* This function cleans up every invalid version on dist-tags, but does not remove
|
|
307
|
+
* invalid versions from the manifest.
|
|
308
|
+
*
|
|
309
|
+
* @param {*} data
|
|
310
|
+
*/
|
|
311
|
+
export function normalizeDistTags(manifest: Manifest): Manifest {
|
|
312
|
+
let sorted;
|
|
313
|
+
// handle missing latest dist-tag
|
|
314
|
+
if (!manifest[DIST_TAGS].latest) {
|
|
315
|
+
// if there is no latest tag, set the highest known version based on semver sort
|
|
316
|
+
sorted = sortVersionsAndFilterInvalid(Object.keys(manifest.versions));
|
|
317
|
+
if (sorted?.length) {
|
|
318
|
+
// get the highest published version
|
|
319
|
+
manifest[DIST_TAGS].latest = sorted.pop();
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
for (const tag in manifest[DIST_TAGS]) {
|
|
324
|
+
// deprecated (will be removed un future majors)
|
|
325
|
+
// this should not happen, tags should be plain strings, legacy fallback
|
|
326
|
+
if (_.isArray(manifest[DIST_TAGS][tag])) {
|
|
327
|
+
if (manifest[DIST_TAGS][tag].length) {
|
|
328
|
+
// sort array
|
|
329
|
+
// FIXME: this is clearly wrong, we need to research why this is like this.
|
|
330
|
+
// @ts-ignore
|
|
331
|
+
sorted = sortVersionsAndFilterInvalid(manifest[DIST_TAGS][tag]);
|
|
332
|
+
if (sorted.length) {
|
|
333
|
+
// use highest version based on semver sort
|
|
334
|
+
manifest[DIST_TAGS][tag] = sorted.pop();
|
|
335
|
+
}
|
|
336
|
+
} else {
|
|
337
|
+
delete manifest[DIST_TAGS][tag];
|
|
338
|
+
}
|
|
339
|
+
} else if (_.isString(manifest[DIST_TAGS][tag])) {
|
|
340
|
+
if (!semver.parse(manifest[DIST_TAGS][tag], true)) {
|
|
341
|
+
// if the version is invalid, delete the dist-tag entry
|
|
342
|
+
delete manifest[DIST_TAGS][tag];
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
return manifest;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
export function hasDeprecatedVersions(pkgInfo: Manifest): boolean {
|
|
351
|
+
const { versions } = pkgInfo;
|
|
352
|
+
for (const version in versions) {
|
|
353
|
+
if (Object.prototype.hasOwnProperty.call(versions[version], 'deprecated')) {
|
|
354
|
+
return true;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
return false;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
export function isDeprecatedManifest(manifest: Manifest): boolean {
|
|
361
|
+
return hasDeprecatedVersions(manifest) && Object.keys(manifest._attachments).length === 0;
|
|
362
|
+
}
|