@verdaccio/core 8.2.2 → 8.3.0
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/build/author-utils.d.ts +20 -0
- package/build/author-utils.js +98 -0
- package/build/author-utils.js.map +1 -0
- package/build/author-utils.mjs +87 -0
- package/build/author-utils.mjs.map +1 -0
- package/build/index.d.ts +2 -1
- package/build/index.js +7 -0
- package/build/index.mjs +2 -1
- package/build/pkg-utils.d.ts +5 -0
- package/build/pkg-utils.js +9 -0
- package/build/pkg-utils.js.map +1 -1
- package/build/pkg-utils.mjs +9 -1
- package/build/pkg-utils.mjs.map +1 -1
- package/build/validation-utils.js +3 -2
- package/build/validation-utils.js.map +1 -1
- package/build/validation-utils.mjs +3 -2
- package/build/validation-utils.mjs.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Author, Manifest } from '@verdaccio/types';
|
|
2
|
+
export type AuthorAvatar = Author & {
|
|
3
|
+
avatar?: string;
|
|
4
|
+
};
|
|
5
|
+
export type AuthorFormat = Author | string | null | void;
|
|
6
|
+
export declare const GENERIC_AVATAR: string;
|
|
7
|
+
/**
|
|
8
|
+
* Formats author field for the web UI.
|
|
9
|
+
* @see https://docs.npmjs.com/files/package.json#author
|
|
10
|
+
*/
|
|
11
|
+
export declare function formatAuthor(author: AuthorFormat): any;
|
|
12
|
+
/**
|
|
13
|
+
* Generate a gravatar url from an email address.
|
|
14
|
+
*/
|
|
15
|
+
export declare function generateGravatarUrl(email?: string | void, online?: boolean): string;
|
|
16
|
+
export declare function normalizeContributors(contributors: Author[]): Author[];
|
|
17
|
+
/**
|
|
18
|
+
* Add gravatar avatars to the author, contributors and maintainers of a manifest.
|
|
19
|
+
*/
|
|
20
|
+
export declare function addGravatarSupport(pkgInfo: Manifest, online?: boolean): AuthorAvatar;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
const require_runtime = require("./_virtual/_rolldown/runtime.js");
|
|
2
|
+
const require_constants = require("./constants.js");
|
|
3
|
+
const require_crypto_utils = require("./crypto-utils.js");
|
|
4
|
+
let lodash = require("lodash");
|
|
5
|
+
lodash = require_runtime.__toESM(lodash);
|
|
6
|
+
//#region src/author-utils.ts
|
|
7
|
+
var author_utils_exports = /* @__PURE__ */ require_runtime.__exportAll({
|
|
8
|
+
GENERIC_AVATAR: () => GENERIC_AVATAR,
|
|
9
|
+
addGravatarSupport: () => addGravatarSupport,
|
|
10
|
+
formatAuthor: () => formatAuthor,
|
|
11
|
+
generateGravatarUrl: () => generateGravatarUrl,
|
|
12
|
+
normalizeContributors: () => normalizeContributors
|
|
13
|
+
});
|
|
14
|
+
var AVATAR_PROVIDER = "https://www.gravatar.com/avatar/";
|
|
15
|
+
var GENERIC_AVATAR = "data:image/svg+xml;utf8," + encodeURIComponent("<svg height=\"100\" viewBox=\"-27 24 100 100\" width=\"100\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><defs><circle cx=\"23\" cy=\"74\" id=\"a\" r=\"50\"/></defs><use fill=\"#F5EEE5\" overflow=\"visible\" xlink:href=\"#a\"/><clipPath id=\"b\"><use overflow=\"visible\" xlink:href=\"#a\"/></clipPath><g clip-path=\"url(#b)\"><defs><path d=\"M36 95.9c0 4 4.7 5.2 7.1 5.8 7.6 2 22.8 5.9 22.8 5.9 3.2 1.1 5.7 3.5 7.1 6.6v9.8H-27v-9.8c1.3-3.1 3.9-5.5 7.1-6.6 0 0 15.2-3.9 22.8-5.9 2.4-.6 7.1-1.8 7.1-5.8V85h26v10.9z\" id=\"c\"/></defs><use fill=\"#E6C19C\" overflow=\"visible\" xlink:href=\"#c\"/><clipPath id=\"d\"><use overflow=\"visible\" xlink:href=\"#c\"/></clipPath><path clip-path=\"url(#d)\" d=\"M23.2 35h.2c3.3 0 8.2.2 11.4 2 3.3 1.9 7.3 5.6 8.5 12.1 2.4 13.7-2.1 35.4-6.3 42.4-4 6.7-9.8 9.2-13.5 9.4H23h-.1c-3.7-.2-9.5-2.7-13.5-9.4-4.2-7-8.7-28.7-6.3-42.4 1.2-6.5 5.2-10.2 8.5-12.1 3.2-1.8 8.1-2 11.4-2h.2z\" fill=\"#D4B08C\"/></g><path d=\"M22.6 40c19.1 0 20.7 13.8 20.8 15.1 1.1 11.9-3 28.1-6.8 33.7-4 5.9-9.8 8.1-13.5 8.3h-.5c-3.8-.3-9.6-2.5-13.6-8.4-3.8-5.6-7.9-21.8-6.8-33.8C2.3 53.7 3.5 40 22.6 40z\" fill=\"#F2CEA5\"/></svg>");
|
|
16
|
+
/**
|
|
17
|
+
* Formats author field for the web UI.
|
|
18
|
+
* @see https://docs.npmjs.com/files/package.json#author
|
|
19
|
+
*/
|
|
20
|
+
function formatAuthor(author) {
|
|
21
|
+
let authorDetails = {
|
|
22
|
+
name: require_constants.DEFAULT_USER,
|
|
23
|
+
email: "",
|
|
24
|
+
url: ""
|
|
25
|
+
};
|
|
26
|
+
if (lodash.default.isNil(author)) return authorDetails;
|
|
27
|
+
if (lodash.default.isString(author)) authorDetails = {
|
|
28
|
+
...authorDetails,
|
|
29
|
+
name: author
|
|
30
|
+
};
|
|
31
|
+
if (lodash.default.isObject(author)) authorDetails = {
|
|
32
|
+
...authorDetails,
|
|
33
|
+
...author
|
|
34
|
+
};
|
|
35
|
+
return authorDetails;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Generate a gravatar url from an email address.
|
|
39
|
+
*/
|
|
40
|
+
function generateGravatarUrl(email = "", online = true) {
|
|
41
|
+
if (online && lodash.default.isString(email) && lodash.default.size(email) > 0) {
|
|
42
|
+
email = email.trim().toLocaleLowerCase();
|
|
43
|
+
return `${AVATAR_PROVIDER}${require_crypto_utils.stringToMD5(email)}`;
|
|
44
|
+
}
|
|
45
|
+
return GENERIC_AVATAR;
|
|
46
|
+
}
|
|
47
|
+
function normalizeContributors(contributors) {
|
|
48
|
+
if (lodash.default.isNil(contributors)) return [];
|
|
49
|
+
else if (contributors && lodash.default.isArray(contributors) === false) return [contributors];
|
|
50
|
+
else if (lodash.default.isString(contributors)) return [{ name: contributors }];
|
|
51
|
+
return contributors;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Add gravatar avatars to the author, contributors and maintainers of a manifest.
|
|
55
|
+
*/
|
|
56
|
+
function addGravatarSupport(pkgInfo, online = true) {
|
|
57
|
+
const pkgInfoCopy = { ...pkgInfo };
|
|
58
|
+
const author = lodash.default.get(pkgInfo, "latest.author", null);
|
|
59
|
+
const contributors = normalizeContributors(lodash.default.get(pkgInfo, "latest.contributors", []));
|
|
60
|
+
const maintainers = lodash.default.get(pkgInfo, "latest.maintainers", []);
|
|
61
|
+
if (author && lodash.default.isObject(author)) {
|
|
62
|
+
const { email } = author;
|
|
63
|
+
pkgInfoCopy.latest.author.avatar = generateGravatarUrl(email, online);
|
|
64
|
+
}
|
|
65
|
+
if (author && lodash.default.isString(author)) pkgInfoCopy.latest.author = {
|
|
66
|
+
avatar: GENERIC_AVATAR,
|
|
67
|
+
email: "",
|
|
68
|
+
author
|
|
69
|
+
};
|
|
70
|
+
if (lodash.default.isEmpty(contributors) === false) pkgInfoCopy.latest.contributors = contributors.map((contributor) => {
|
|
71
|
+
if (lodash.default.isObject(contributor)) contributor.avatar = generateGravatarUrl(contributor.email, online);
|
|
72
|
+
else if (lodash.default.isString(contributor)) contributor = {
|
|
73
|
+
avatar: GENERIC_AVATAR,
|
|
74
|
+
email: contributor,
|
|
75
|
+
name: contributor
|
|
76
|
+
};
|
|
77
|
+
return contributor;
|
|
78
|
+
});
|
|
79
|
+
if (lodash.default.isEmpty(maintainers) === false) pkgInfoCopy.latest.maintainers = maintainers.map((maintainer) => {
|
|
80
|
+
maintainer.avatar = generateGravatarUrl(maintainer.email, online);
|
|
81
|
+
return maintainer;
|
|
82
|
+
});
|
|
83
|
+
return pkgInfoCopy;
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
exports.GENERIC_AVATAR = GENERIC_AVATAR;
|
|
87
|
+
exports.addGravatarSupport = addGravatarSupport;
|
|
88
|
+
Object.defineProperty(exports, "author_utils_exports", {
|
|
89
|
+
enumerable: true,
|
|
90
|
+
get: function() {
|
|
91
|
+
return author_utils_exports;
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
exports.formatAuthor = formatAuthor;
|
|
95
|
+
exports.generateGravatarUrl = generateGravatarUrl;
|
|
96
|
+
exports.normalizeContributors = normalizeContributors;
|
|
97
|
+
|
|
98
|
+
//# sourceMappingURL=author-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"author-utils.js","names":[],"sources":["../src/author-utils.ts"],"sourcesContent":["import _ from 'lodash';\n\nimport type { Author, Manifest } from '@verdaccio/types';\n\nimport { DEFAULT_USER } from './constants';\nimport { stringToMD5 } from './crypto-utils';\n\nexport type AuthorAvatar = Author & { avatar?: string };\n\nexport type AuthorFormat = Author | string | null | void;\n\nconst AVATAR_PROVIDER = 'https://www.gravatar.com/avatar/';\n\nexport const GENERIC_AVATAR =\n 'data:image/svg+xml;utf8,' +\n encodeURIComponent(\n '<svg height=\"100\" viewBox=\"-27 24 100 100\" width=\"100\" xmlns=\"http://www.w3.org/' +\n '2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><defs><circle cx=\"23\" cy=\"7' +\n '4\" id=\"a\" r=\"50\"/></defs><use fill=\"#F5EEE5\" overflow=\"visible\" xlink:href=\"#a\"/' +\n '><clipPath id=\"b\"><use overflow=\"visible\" xlink:href=\"#a\"/></clipPath><g clip-pa' +\n 'th=\"url(#b)\"><defs><path d=\"M36 95.9c0 4 4.7 5.2 7.1 5.8 7.6 2 22.8 5.9 22.8 5.9' +\n ' 3.2 1.1 5.7 3.5 7.1 6.6v9.8H-27v-9.8c1.3-3.1 3.9-5.5 7.1-6.6 0 0 15.2-3.9 22.8-' +\n '5.9 2.4-.6 7.1-1.8 7.1-5.8V85h26v10.9z\" id=\"c\"/></defs><use fill=\"#E6C19C\" overf' +\n 'low=\"visible\" xlink:href=\"#c\"/><clipPath id=\"d\"><use overflow=\"visible\" xlink:hr' +\n 'ef=\"#c\"/></clipPath><path clip-path=\"url(#d)\" d=\"M23.2 35h.2c3.3 0 8.2.2 11.4 2 ' +\n '3.3 1.9 7.3 5.6 8.5 12.1 2.4 13.7-2.1 35.4-6.3 42.4-4 6.7-9.8 9.2-13.5 9.4H23h-.' +\n '1c-3.7-.2-9.5-2.7-13.5-9.4-4.2-7-8.7-28.7-6.3-42.4 1.2-6.5 5.2-10.2 8.5-12.1 3.2' +\n '-1.8 8.1-2 11.4-2h.2z\" fill=\"#D4B08C\"/></g><path d=\"M22.6 40c19.1 0 20.7 13.8 20' +\n '.8 15.1 1.1 11.9-3 28.1-6.8 33.7-4 5.9-9.8 8.1-13.5 8.3h-.5c-3.8-.3-9.6-2.5-13.6' +\n '-8.4-3.8-5.6-7.9-21.8-6.8-33.8C2.3 53.7 3.5 40 22.6 40z\" fill=\"#F2CEA5\"/></svg>'\n );\n\n/**\n * Formats author field for the web UI.\n * @see https://docs.npmjs.com/files/package.json#author\n */\nexport function formatAuthor(author: AuthorFormat): any {\n let authorDetails = {\n name: DEFAULT_USER,\n email: '',\n url: '',\n };\n\n if (_.isNil(author)) {\n return authorDetails;\n }\n\n if (_.isString(author)) {\n authorDetails = {\n ...authorDetails,\n name: author as string,\n };\n }\n\n if (_.isObject(author)) {\n authorDetails = {\n ...authorDetails,\n ...(author as Author),\n };\n }\n\n return authorDetails;\n}\n\n/**\n * Generate a gravatar url from an email address.\n */\nexport function generateGravatarUrl(email: string | void = '', online: boolean = true): string {\n if (online && _.isString(email) && _.size(email) > 0) {\n email = email.trim().toLocaleLowerCase();\n const emailMD5 = stringToMD5(email);\n return `${AVATAR_PROVIDER}${emailMD5}`;\n }\n return GENERIC_AVATAR;\n}\n\nexport function normalizeContributors(contributors: Author[]): Author[] {\n if (_.isNil(contributors)) {\n return [];\n } else if (contributors && _.isArray(contributors) === false) {\n return [contributors];\n } else if (_.isString(contributors)) {\n return [\n {\n name: contributors,\n },\n ];\n }\n\n return contributors;\n}\n\n/**\n * Add gravatar avatars to the author, contributors and maintainers of a manifest.\n */\nexport function addGravatarSupport(pkgInfo: Manifest, online = true): AuthorAvatar {\n const pkgInfoCopy = { ...pkgInfo } as any;\n const author: any = _.get(pkgInfo, 'latest.author', null) as any;\n const contributors: AuthorAvatar[] = normalizeContributors(\n _.get(pkgInfo, 'latest.contributors', [])\n );\n const maintainers = _.get(pkgInfo, 'latest.maintainers', []);\n\n // for author.\n if (author && _.isObject(author)) {\n const { email } = author as Author;\n pkgInfoCopy.latest.author.avatar = generateGravatarUrl(email, online);\n }\n\n if (author && _.isString(author)) {\n pkgInfoCopy.latest.author = {\n avatar: GENERIC_AVATAR,\n email: '',\n author,\n };\n }\n\n // for contributors\n if (_.isEmpty(contributors) === false) {\n pkgInfoCopy.latest.contributors = contributors.map((contributor): AuthorAvatar => {\n if (_.isObject(contributor)) {\n contributor.avatar = generateGravatarUrl(contributor.email, online);\n } else if (_.isString(contributor)) {\n contributor = {\n avatar: GENERIC_AVATAR,\n email: contributor,\n name: contributor,\n };\n }\n\n return contributor;\n });\n }\n\n // for maintainers\n if (_.isEmpty(maintainers) === false) {\n pkgInfoCopy.latest.maintainers = maintainers.map((maintainer): void => {\n // @ts-ignore\n maintainer.avatar = generateGravatarUrl(maintainer.email, online);\n return maintainer;\n });\n }\n\n return pkgInfoCopy;\n}\n"],"mappings":";;;;;;;;;;;;;AAWA,IAAM,kBAAkB;AAExB,IAAa,iBACX,6BACA,mBACE,2pCAcF;;;;;AAMF,SAAgB,aAAa,QAA2B;CACtD,IAAI,gBAAgB;EAClB,MAAM,kBAAA;EACN,OAAO;EACP,KAAK;CACP;CAEA,IAAI,OAAA,QAAE,MAAM,MAAM,GAChB,OAAO;CAGT,IAAI,OAAA,QAAE,SAAS,MAAM,GACnB,gBAAgB;EACd,GAAG;EACH,MAAM;CACR;CAGF,IAAI,OAAA,QAAE,SAAS,MAAM,GACnB,gBAAgB;EACd,GAAG;EACH,GAAI;CACN;CAGF,OAAO;AACT;;;;AAKA,SAAgB,oBAAoB,QAAuB,IAAI,SAAkB,MAAc;CAC7F,IAAI,UAAU,OAAA,QAAE,SAAS,KAAK,KAAK,OAAA,QAAE,KAAK,KAAK,IAAI,GAAG;EACpD,QAAQ,MAAM,KAAK,CAAC,CAAC,kBAAkB;EAEvC,OAAO,GAAG,kBADO,qBAAA,YAAY,KACD;CAC9B;CACA,OAAO;AACT;AAEA,SAAgB,sBAAsB,cAAkC;CACtE,IAAI,OAAA,QAAE,MAAM,YAAY,GACtB,OAAO,CAAC;MACH,IAAI,gBAAgB,OAAA,QAAE,QAAQ,YAAY,MAAM,OACrD,OAAO,CAAC,YAAY;MACf,IAAI,OAAA,QAAE,SAAS,YAAY,GAChC,OAAO,CACL,EACE,MAAM,aACR,CACF;CAGF,OAAO;AACT;;;;AAKA,SAAgB,mBAAmB,SAAmB,SAAS,MAAoB;CACjF,MAAM,cAAc,EAAE,GAAG,QAAQ;CACjC,MAAM,SAAc,OAAA,QAAE,IAAI,SAAS,iBAAiB,IAAI;CACxD,MAAM,eAA+B,sBACnC,OAAA,QAAE,IAAI,SAAS,uBAAuB,CAAC,CAAC,CAC1C;CACA,MAAM,cAAc,OAAA,QAAE,IAAI,SAAS,sBAAsB,CAAC,CAAC;CAG3D,IAAI,UAAU,OAAA,QAAE,SAAS,MAAM,GAAG;EAChC,MAAM,EAAE,UAAU;EAClB,YAAY,OAAO,OAAO,SAAS,oBAAoB,OAAO,MAAM;CACtE;CAEA,IAAI,UAAU,OAAA,QAAE,SAAS,MAAM,GAC7B,YAAY,OAAO,SAAS;EAC1B,QAAQ;EACR,OAAO;EACP;CACF;CAIF,IAAI,OAAA,QAAE,QAAQ,YAAY,MAAM,OAC9B,YAAY,OAAO,eAAe,aAAa,KAAK,gBAA8B;EAChF,IAAI,OAAA,QAAE,SAAS,WAAW,GACxB,YAAY,SAAS,oBAAoB,YAAY,OAAO,MAAM;OAC7D,IAAI,OAAA,QAAE,SAAS,WAAW,GAC/B,cAAc;GACZ,QAAQ;GACR,OAAO;GACP,MAAM;EACR;EAGF,OAAO;CACT,CAAC;CAIH,IAAI,OAAA,QAAE,QAAQ,WAAW,MAAM,OAC7B,YAAY,OAAO,cAAc,YAAY,KAAK,eAAqB;EAErE,WAAW,SAAS,oBAAoB,WAAW,OAAO,MAAM;EAChE,OAAO;CACT,CAAC;CAGH,OAAO;AACT"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { __exportAll } from "./_virtual/_rolldown/runtime.mjs";
|
|
2
|
+
import { DEFAULT_USER } from "./constants.mjs";
|
|
3
|
+
import { stringToMD5 } from "./crypto-utils.mjs";
|
|
4
|
+
import _ from "lodash";
|
|
5
|
+
//#region src/author-utils.ts
|
|
6
|
+
var author_utils_exports = /* @__PURE__ */ __exportAll({
|
|
7
|
+
GENERIC_AVATAR: () => GENERIC_AVATAR,
|
|
8
|
+
addGravatarSupport: () => addGravatarSupport,
|
|
9
|
+
formatAuthor: () => formatAuthor,
|
|
10
|
+
generateGravatarUrl: () => generateGravatarUrl,
|
|
11
|
+
normalizeContributors: () => normalizeContributors
|
|
12
|
+
});
|
|
13
|
+
var AVATAR_PROVIDER = "https://www.gravatar.com/avatar/";
|
|
14
|
+
var GENERIC_AVATAR = "data:image/svg+xml;utf8," + encodeURIComponent("<svg height=\"100\" viewBox=\"-27 24 100 100\" width=\"100\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><defs><circle cx=\"23\" cy=\"74\" id=\"a\" r=\"50\"/></defs><use fill=\"#F5EEE5\" overflow=\"visible\" xlink:href=\"#a\"/><clipPath id=\"b\"><use overflow=\"visible\" xlink:href=\"#a\"/></clipPath><g clip-path=\"url(#b)\"><defs><path d=\"M36 95.9c0 4 4.7 5.2 7.1 5.8 7.6 2 22.8 5.9 22.8 5.9 3.2 1.1 5.7 3.5 7.1 6.6v9.8H-27v-9.8c1.3-3.1 3.9-5.5 7.1-6.6 0 0 15.2-3.9 22.8-5.9 2.4-.6 7.1-1.8 7.1-5.8V85h26v10.9z\" id=\"c\"/></defs><use fill=\"#E6C19C\" overflow=\"visible\" xlink:href=\"#c\"/><clipPath id=\"d\"><use overflow=\"visible\" xlink:href=\"#c\"/></clipPath><path clip-path=\"url(#d)\" d=\"M23.2 35h.2c3.3 0 8.2.2 11.4 2 3.3 1.9 7.3 5.6 8.5 12.1 2.4 13.7-2.1 35.4-6.3 42.4-4 6.7-9.8 9.2-13.5 9.4H23h-.1c-3.7-.2-9.5-2.7-13.5-9.4-4.2-7-8.7-28.7-6.3-42.4 1.2-6.5 5.2-10.2 8.5-12.1 3.2-1.8 8.1-2 11.4-2h.2z\" fill=\"#D4B08C\"/></g><path d=\"M22.6 40c19.1 0 20.7 13.8 20.8 15.1 1.1 11.9-3 28.1-6.8 33.7-4 5.9-9.8 8.1-13.5 8.3h-.5c-3.8-.3-9.6-2.5-13.6-8.4-3.8-5.6-7.9-21.8-6.8-33.8C2.3 53.7 3.5 40 22.6 40z\" fill=\"#F2CEA5\"/></svg>");
|
|
15
|
+
/**
|
|
16
|
+
* Formats author field for the web UI.
|
|
17
|
+
* @see https://docs.npmjs.com/files/package.json#author
|
|
18
|
+
*/
|
|
19
|
+
function formatAuthor(author) {
|
|
20
|
+
let authorDetails = {
|
|
21
|
+
name: DEFAULT_USER,
|
|
22
|
+
email: "",
|
|
23
|
+
url: ""
|
|
24
|
+
};
|
|
25
|
+
if (_.isNil(author)) return authorDetails;
|
|
26
|
+
if (_.isString(author)) authorDetails = {
|
|
27
|
+
...authorDetails,
|
|
28
|
+
name: author
|
|
29
|
+
};
|
|
30
|
+
if (_.isObject(author)) authorDetails = {
|
|
31
|
+
...authorDetails,
|
|
32
|
+
...author
|
|
33
|
+
};
|
|
34
|
+
return authorDetails;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Generate a gravatar url from an email address.
|
|
38
|
+
*/
|
|
39
|
+
function generateGravatarUrl(email = "", online = true) {
|
|
40
|
+
if (online && _.isString(email) && _.size(email) > 0) {
|
|
41
|
+
email = email.trim().toLocaleLowerCase();
|
|
42
|
+
return `${AVATAR_PROVIDER}${stringToMD5(email)}`;
|
|
43
|
+
}
|
|
44
|
+
return GENERIC_AVATAR;
|
|
45
|
+
}
|
|
46
|
+
function normalizeContributors(contributors) {
|
|
47
|
+
if (_.isNil(contributors)) return [];
|
|
48
|
+
else if (contributors && _.isArray(contributors) === false) return [contributors];
|
|
49
|
+
else if (_.isString(contributors)) return [{ name: contributors }];
|
|
50
|
+
return contributors;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Add gravatar avatars to the author, contributors and maintainers of a manifest.
|
|
54
|
+
*/
|
|
55
|
+
function addGravatarSupport(pkgInfo, online = true) {
|
|
56
|
+
const pkgInfoCopy = { ...pkgInfo };
|
|
57
|
+
const author = _.get(pkgInfo, "latest.author", null);
|
|
58
|
+
const contributors = normalizeContributors(_.get(pkgInfo, "latest.contributors", []));
|
|
59
|
+
const maintainers = _.get(pkgInfo, "latest.maintainers", []);
|
|
60
|
+
if (author && _.isObject(author)) {
|
|
61
|
+
const { email } = author;
|
|
62
|
+
pkgInfoCopy.latest.author.avatar = generateGravatarUrl(email, online);
|
|
63
|
+
}
|
|
64
|
+
if (author && _.isString(author)) pkgInfoCopy.latest.author = {
|
|
65
|
+
avatar: GENERIC_AVATAR,
|
|
66
|
+
email: "",
|
|
67
|
+
author
|
|
68
|
+
};
|
|
69
|
+
if (_.isEmpty(contributors) === false) pkgInfoCopy.latest.contributors = contributors.map((contributor) => {
|
|
70
|
+
if (_.isObject(contributor)) contributor.avatar = generateGravatarUrl(contributor.email, online);
|
|
71
|
+
else if (_.isString(contributor)) contributor = {
|
|
72
|
+
avatar: GENERIC_AVATAR,
|
|
73
|
+
email: contributor,
|
|
74
|
+
name: contributor
|
|
75
|
+
};
|
|
76
|
+
return contributor;
|
|
77
|
+
});
|
|
78
|
+
if (_.isEmpty(maintainers) === false) pkgInfoCopy.latest.maintainers = maintainers.map((maintainer) => {
|
|
79
|
+
maintainer.avatar = generateGravatarUrl(maintainer.email, online);
|
|
80
|
+
return maintainer;
|
|
81
|
+
});
|
|
82
|
+
return pkgInfoCopy;
|
|
83
|
+
}
|
|
84
|
+
//#endregion
|
|
85
|
+
export { GENERIC_AVATAR, addGravatarSupport, author_utils_exports, formatAuthor, generateGravatarUrl, normalizeContributors };
|
|
86
|
+
|
|
87
|
+
//# sourceMappingURL=author-utils.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"author-utils.mjs","names":[],"sources":["../src/author-utils.ts"],"sourcesContent":["import _ from 'lodash';\n\nimport type { Author, Manifest } from '@verdaccio/types';\n\nimport { DEFAULT_USER } from './constants';\nimport { stringToMD5 } from './crypto-utils';\n\nexport type AuthorAvatar = Author & { avatar?: string };\n\nexport type AuthorFormat = Author | string | null | void;\n\nconst AVATAR_PROVIDER = 'https://www.gravatar.com/avatar/';\n\nexport const GENERIC_AVATAR =\n 'data:image/svg+xml;utf8,' +\n encodeURIComponent(\n '<svg height=\"100\" viewBox=\"-27 24 100 100\" width=\"100\" xmlns=\"http://www.w3.org/' +\n '2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><defs><circle cx=\"23\" cy=\"7' +\n '4\" id=\"a\" r=\"50\"/></defs><use fill=\"#F5EEE5\" overflow=\"visible\" xlink:href=\"#a\"/' +\n '><clipPath id=\"b\"><use overflow=\"visible\" xlink:href=\"#a\"/></clipPath><g clip-pa' +\n 'th=\"url(#b)\"><defs><path d=\"M36 95.9c0 4 4.7 5.2 7.1 5.8 7.6 2 22.8 5.9 22.8 5.9' +\n ' 3.2 1.1 5.7 3.5 7.1 6.6v9.8H-27v-9.8c1.3-3.1 3.9-5.5 7.1-6.6 0 0 15.2-3.9 22.8-' +\n '5.9 2.4-.6 7.1-1.8 7.1-5.8V85h26v10.9z\" id=\"c\"/></defs><use fill=\"#E6C19C\" overf' +\n 'low=\"visible\" xlink:href=\"#c\"/><clipPath id=\"d\"><use overflow=\"visible\" xlink:hr' +\n 'ef=\"#c\"/></clipPath><path clip-path=\"url(#d)\" d=\"M23.2 35h.2c3.3 0 8.2.2 11.4 2 ' +\n '3.3 1.9 7.3 5.6 8.5 12.1 2.4 13.7-2.1 35.4-6.3 42.4-4 6.7-9.8 9.2-13.5 9.4H23h-.' +\n '1c-3.7-.2-9.5-2.7-13.5-9.4-4.2-7-8.7-28.7-6.3-42.4 1.2-6.5 5.2-10.2 8.5-12.1 3.2' +\n '-1.8 8.1-2 11.4-2h.2z\" fill=\"#D4B08C\"/></g><path d=\"M22.6 40c19.1 0 20.7 13.8 20' +\n '.8 15.1 1.1 11.9-3 28.1-6.8 33.7-4 5.9-9.8 8.1-13.5 8.3h-.5c-3.8-.3-9.6-2.5-13.6' +\n '-8.4-3.8-5.6-7.9-21.8-6.8-33.8C2.3 53.7 3.5 40 22.6 40z\" fill=\"#F2CEA5\"/></svg>'\n );\n\n/**\n * Formats author field for the web UI.\n * @see https://docs.npmjs.com/files/package.json#author\n */\nexport function formatAuthor(author: AuthorFormat): any {\n let authorDetails = {\n name: DEFAULT_USER,\n email: '',\n url: '',\n };\n\n if (_.isNil(author)) {\n return authorDetails;\n }\n\n if (_.isString(author)) {\n authorDetails = {\n ...authorDetails,\n name: author as string,\n };\n }\n\n if (_.isObject(author)) {\n authorDetails = {\n ...authorDetails,\n ...(author as Author),\n };\n }\n\n return authorDetails;\n}\n\n/**\n * Generate a gravatar url from an email address.\n */\nexport function generateGravatarUrl(email: string | void = '', online: boolean = true): string {\n if (online && _.isString(email) && _.size(email) > 0) {\n email = email.trim().toLocaleLowerCase();\n const emailMD5 = stringToMD5(email);\n return `${AVATAR_PROVIDER}${emailMD5}`;\n }\n return GENERIC_AVATAR;\n}\n\nexport function normalizeContributors(contributors: Author[]): Author[] {\n if (_.isNil(contributors)) {\n return [];\n } else if (contributors && _.isArray(contributors) === false) {\n return [contributors];\n } else if (_.isString(contributors)) {\n return [\n {\n name: contributors,\n },\n ];\n }\n\n return contributors;\n}\n\n/**\n * Add gravatar avatars to the author, contributors and maintainers of a manifest.\n */\nexport function addGravatarSupport(pkgInfo: Manifest, online = true): AuthorAvatar {\n const pkgInfoCopy = { ...pkgInfo } as any;\n const author: any = _.get(pkgInfo, 'latest.author', null) as any;\n const contributors: AuthorAvatar[] = normalizeContributors(\n _.get(pkgInfo, 'latest.contributors', [])\n );\n const maintainers = _.get(pkgInfo, 'latest.maintainers', []);\n\n // for author.\n if (author && _.isObject(author)) {\n const { email } = author as Author;\n pkgInfoCopy.latest.author.avatar = generateGravatarUrl(email, online);\n }\n\n if (author && _.isString(author)) {\n pkgInfoCopy.latest.author = {\n avatar: GENERIC_AVATAR,\n email: '',\n author,\n };\n }\n\n // for contributors\n if (_.isEmpty(contributors) === false) {\n pkgInfoCopy.latest.contributors = contributors.map((contributor): AuthorAvatar => {\n if (_.isObject(contributor)) {\n contributor.avatar = generateGravatarUrl(contributor.email, online);\n } else if (_.isString(contributor)) {\n contributor = {\n avatar: GENERIC_AVATAR,\n email: contributor,\n name: contributor,\n };\n }\n\n return contributor;\n });\n }\n\n // for maintainers\n if (_.isEmpty(maintainers) === false) {\n pkgInfoCopy.latest.maintainers = maintainers.map((maintainer): void => {\n // @ts-ignore\n maintainer.avatar = generateGravatarUrl(maintainer.email, online);\n return maintainer;\n });\n }\n\n return pkgInfoCopy;\n}\n"],"mappings":";;;;;;;;;;;;AAWA,IAAM,kBAAkB;AAExB,IAAa,iBACX,6BACA,mBACE,2pCAcF;;;;;AAMF,SAAgB,aAAa,QAA2B;CACtD,IAAI,gBAAgB;EAClB,MAAM;EACN,OAAO;EACP,KAAK;CACP;CAEA,IAAI,EAAE,MAAM,MAAM,GAChB,OAAO;CAGT,IAAI,EAAE,SAAS,MAAM,GACnB,gBAAgB;EACd,GAAG;EACH,MAAM;CACR;CAGF,IAAI,EAAE,SAAS,MAAM,GACnB,gBAAgB;EACd,GAAG;EACH,GAAI;CACN;CAGF,OAAO;AACT;;;;AAKA,SAAgB,oBAAoB,QAAuB,IAAI,SAAkB,MAAc;CAC7F,IAAI,UAAU,EAAE,SAAS,KAAK,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG;EACpD,QAAQ,MAAM,KAAK,CAAC,CAAC,kBAAkB;EAEvC,OAAO,GAAG,kBADO,YAAY,KACD;CAC9B;CACA,OAAO;AACT;AAEA,SAAgB,sBAAsB,cAAkC;CACtE,IAAI,EAAE,MAAM,YAAY,GACtB,OAAO,CAAC;MACH,IAAI,gBAAgB,EAAE,QAAQ,YAAY,MAAM,OACrD,OAAO,CAAC,YAAY;MACf,IAAI,EAAE,SAAS,YAAY,GAChC,OAAO,CACL,EACE,MAAM,aACR,CACF;CAGF,OAAO;AACT;;;;AAKA,SAAgB,mBAAmB,SAAmB,SAAS,MAAoB;CACjF,MAAM,cAAc,EAAE,GAAG,QAAQ;CACjC,MAAM,SAAc,EAAE,IAAI,SAAS,iBAAiB,IAAI;CACxD,MAAM,eAA+B,sBACnC,EAAE,IAAI,SAAS,uBAAuB,CAAC,CAAC,CAC1C;CACA,MAAM,cAAc,EAAE,IAAI,SAAS,sBAAsB,CAAC,CAAC;CAG3D,IAAI,UAAU,EAAE,SAAS,MAAM,GAAG;EAChC,MAAM,EAAE,UAAU;EAClB,YAAY,OAAO,OAAO,SAAS,oBAAoB,OAAO,MAAM;CACtE;CAEA,IAAI,UAAU,EAAE,SAAS,MAAM,GAC7B,YAAY,OAAO,SAAS;EAC1B,QAAQ;EACR,OAAO;EACP;CACF;CAIF,IAAI,EAAE,QAAQ,YAAY,MAAM,OAC9B,YAAY,OAAO,eAAe,aAAa,KAAK,gBAA8B;EAChF,IAAI,EAAE,SAAS,WAAW,GACxB,YAAY,SAAS,oBAAoB,YAAY,OAAO,MAAM;OAC7D,IAAI,EAAE,SAAS,WAAW,GAC/B,cAAc;GACZ,QAAQ;GACR,OAAO;GACP,MAAM;EACR;EAGF,OAAO;CACT,CAAC;CAIH,IAAI,EAAE,QAAQ,WAAW,MAAM,OAC7B,YAAY,OAAO,cAAc,YAAY,KAAK,eAAqB;EAErE,WAAW,SAAS,oBAAoB,WAAW,OAAO,MAAM;EAChE,OAAO;CACT,CAAC;CAGH,OAAO;AACT"}
|
package/build/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as authUtils from './auth-utils';
|
|
2
|
+
import * as authorUtils from './author-utils';
|
|
2
3
|
import * as constants from './constants';
|
|
3
4
|
import * as cryptoUtils from './crypto-utils';
|
|
4
5
|
import * as errorUtils from './error-utils';
|
|
@@ -15,4 +16,4 @@ import * as warningUtils from './warning-utils';
|
|
|
15
16
|
export type { VerdaccioError } from './error-utils';
|
|
16
17
|
export { API_ERROR, SUPPORT_ERRORS, APP_ERROR } from './error-utils';
|
|
17
18
|
export { TOKEN_BASIC, TOKEN_BEARER, HTTP_STATUS, API_MESSAGE, HEADERS, DIST_TAGS, CHARACTER_ENCODING, HEADER_TYPE, LATEST, DEFAULT_PASSWORD_VALIDATION, DEFAULT_USER, ANONYMOUS_USER, USERS, MAINTAINERS, PLUGIN_CATEGORY, PLUGIN_PREFIX, PLUGIN_UI_PREFIX, HtpasswdHashAlgorithm, DEFAULT_DOMAIN, DEFAULT_PORT, DEFAULT_PROTOCOL, } from './constants';
|
|
18
|
-
export { authUtils, cryptoUtils, fileUtils, ipUtils, pkgUtils, searchUtils, streamUtils, errorUtils, validationUtils, stringUtils, constants, pluginUtils, warningUtils, tarballUtils, };
|
|
19
|
+
export { authUtils, authorUtils, cryptoUtils, fileUtils, ipUtils, pkgUtils, searchUtils, streamUtils, errorUtils, validationUtils, stringUtils, constants, pluginUtils, warningUtils, tarballUtils, };
|
package/build/index.js
CHANGED
|
@@ -5,6 +5,7 @@ Object.defineProperties(exports, {
|
|
|
5
5
|
const require_auth_utils = require("./auth-utils.js");
|
|
6
6
|
const require_constants = require("./constants.js");
|
|
7
7
|
const require_crypto_utils = require("./crypto-utils.js");
|
|
8
|
+
const require_author_utils = require("./author-utils.js");
|
|
8
9
|
const require_error_utils = require("./error-utils.js");
|
|
9
10
|
const require_file_utils = require("./file-utils.js");
|
|
10
11
|
const require_ip_utils = require("./ip-utils.js");
|
|
@@ -46,6 +47,12 @@ Object.defineProperty(exports, "authUtils", {
|
|
|
46
47
|
return require_auth_utils.auth_utils_exports;
|
|
47
48
|
}
|
|
48
49
|
});
|
|
50
|
+
Object.defineProperty(exports, "authorUtils", {
|
|
51
|
+
enumerable: true,
|
|
52
|
+
get: function() {
|
|
53
|
+
return require_author_utils.author_utils_exports;
|
|
54
|
+
}
|
|
55
|
+
});
|
|
49
56
|
Object.defineProperty(exports, "constants", {
|
|
50
57
|
enumerable: true,
|
|
51
58
|
get: function() {
|
package/build/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { auth_utils_exports } from "./auth-utils.mjs";
|
|
2
2
|
import { ANONYMOUS_USER, API_MESSAGE, CHARACTER_ENCODING, DEFAULT_DOMAIN, DEFAULT_PASSWORD_VALIDATION, DEFAULT_PORT, DEFAULT_PROTOCOL, DEFAULT_USER, DIST_TAGS, HEADERS, HEADER_TYPE, HTTP_STATUS, HtpasswdHashAlgorithm, LATEST, MAINTAINERS, PLUGIN_CATEGORY, PLUGIN_PREFIX, PLUGIN_UI_PREFIX, TOKEN_BASIC, TOKEN_BEARER, USERS, constants_exports } from "./constants.mjs";
|
|
3
3
|
import { crypto_utils_exports } from "./crypto-utils.mjs";
|
|
4
|
+
import { author_utils_exports } from "./author-utils.mjs";
|
|
4
5
|
import { API_ERROR, APP_ERROR, SUPPORT_ERRORS, error_utils_exports } from "./error-utils.mjs";
|
|
5
6
|
import { file_utils_exports } from "./file-utils.mjs";
|
|
6
7
|
import { ip_utils_exports } from "./ip-utils.mjs";
|
|
@@ -12,4 +13,4 @@ import { string_utils_exports } from "./string-utils.mjs";
|
|
|
12
13
|
import { tarball_utils_exports } from "./tarball-utils.mjs";
|
|
13
14
|
import { validation_utils_exports } from "./validation-utils.mjs";
|
|
14
15
|
import { warning_utils_exports } from "./warning-utils.mjs";
|
|
15
|
-
export { ANONYMOUS_USER, API_ERROR, API_MESSAGE, APP_ERROR, CHARACTER_ENCODING, DEFAULT_DOMAIN, DEFAULT_PASSWORD_VALIDATION, DEFAULT_PORT, DEFAULT_PROTOCOL, DEFAULT_USER, DIST_TAGS, HEADERS, HEADER_TYPE, HTTP_STATUS, HtpasswdHashAlgorithm, LATEST, MAINTAINERS, PLUGIN_CATEGORY, PLUGIN_PREFIX, PLUGIN_UI_PREFIX, SUPPORT_ERRORS, TOKEN_BASIC, TOKEN_BEARER, USERS, auth_utils_exports as authUtils, constants_exports as constants, crypto_utils_exports as cryptoUtils, error_utils_exports as errorUtils, file_utils_exports as fileUtils, ip_utils_exports as ipUtils, pkg_utils_exports as pkgUtils, plugin_utils_exports as pluginUtils, search_utils_exports as searchUtils, stream_utils_exports as streamUtils, string_utils_exports as stringUtils, tarball_utils_exports as tarballUtils, validation_utils_exports as validationUtils, warning_utils_exports as warningUtils };
|
|
16
|
+
export { ANONYMOUS_USER, API_ERROR, API_MESSAGE, APP_ERROR, CHARACTER_ENCODING, DEFAULT_DOMAIN, DEFAULT_PASSWORD_VALIDATION, DEFAULT_PORT, DEFAULT_PROTOCOL, DEFAULT_USER, DIST_TAGS, HEADERS, HEADER_TYPE, HTTP_STATUS, HtpasswdHashAlgorithm, LATEST, MAINTAINERS, PLUGIN_CATEGORY, PLUGIN_PREFIX, PLUGIN_UI_PREFIX, SUPPORT_ERRORS, TOKEN_BASIC, TOKEN_BEARER, USERS, auth_utils_exports as authUtils, author_utils_exports as authorUtils, constants_exports as constants, crypto_utils_exports as cryptoUtils, error_utils_exports as errorUtils, file_utils_exports as fileUtils, ip_utils_exports as ipUtils, pkg_utils_exports as pkgUtils, plugin_utils_exports as pluginUtils, search_utils_exports as searchUtils, stream_utils_exports as streamUtils, string_utils_exports as stringUtils, tarball_utils_exports as tarballUtils, validation_utils_exports as validationUtils, warning_utils_exports as warningUtils };
|
package/build/pkg-utils.d.ts
CHANGED
|
@@ -10,6 +10,11 @@ export declare function semverSort(listVersions: string[]): string[];
|
|
|
10
10
|
* @returns The sanitized version string.
|
|
11
11
|
*/
|
|
12
12
|
export declare function semverSanitize(version: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Get the version tagged as latest in the dist-tags of a package.
|
|
15
|
+
* @param package metadata
|
|
16
|
+
**/
|
|
17
|
+
export declare function getLatestVersion(pkgInfo: Manifest): string;
|
|
13
18
|
/**
|
|
14
19
|
* Get the latest publihsed version of a package.
|
|
15
20
|
* @param package metadata
|
package/build/pkg-utils.js
CHANGED
|
@@ -9,6 +9,7 @@ semver = require_runtime.__toESM(semver);
|
|
|
9
9
|
//#region src/pkg-utils.ts
|
|
10
10
|
var pkg_utils_exports = /* @__PURE__ */ require_runtime.__exportAll({
|
|
11
11
|
getLatest: () => getLatest,
|
|
12
|
+
getLatestVersion: () => getLatestVersion,
|
|
12
13
|
getPackageJson: () => getPackageJson,
|
|
13
14
|
mergeVersions: () => mergeVersions,
|
|
14
15
|
semverSanitize: () => semverSanitize,
|
|
@@ -33,6 +34,13 @@ function semverSanitize(version) {
|
|
|
33
34
|
return semver.default.valid(version) || semver.default.coerce(version, { includePrerelease: true })?.version || "";
|
|
34
35
|
}
|
|
35
36
|
/**
|
|
37
|
+
* Get the version tagged as latest in the dist-tags of a package.
|
|
38
|
+
* @param package metadata
|
|
39
|
+
**/
|
|
40
|
+
function getLatestVersion(pkgInfo) {
|
|
41
|
+
return pkgInfo[require_constants.DIST_TAGS].latest;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
36
44
|
* Get the latest publihsed version of a package.
|
|
37
45
|
* @param package metadata
|
|
38
46
|
**/
|
|
@@ -68,6 +76,7 @@ function getPackageJson(packagePath, relativePath) {
|
|
|
68
76
|
}
|
|
69
77
|
//#endregion
|
|
70
78
|
exports.getLatest = getLatest;
|
|
79
|
+
exports.getLatestVersion = getLatestVersion;
|
|
71
80
|
exports.getPackageJson = getPackageJson;
|
|
72
81
|
exports.mergeVersions = mergeVersions;
|
|
73
82
|
Object.defineProperty(exports, "pkg_utils_exports", {
|
package/build/pkg-utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pkg-utils.js","names":[],"sources":["../src/pkg-utils.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport semver from 'semver';\n\nimport type { Manifest } from '@verdaccio/types';\n\nimport { DIST_TAGS } from './constants';\n\n/**\n * Function filters out bad semver versions and sorts the array.\n * @return {Array} sorted Array\n */\nexport function semverSort(listVersions: string[]): string[] {\n return listVersions\n .filter(function (x): boolean {\n if (!semver.parse(x, true)) {\n return false;\n }\n return true;\n })\n .sort(semver.compareLoose)\n .map(String);\n}\n\n/**\n * Sanitize a version string to a valid semver version.\n * @param version - The version string to sanitize.\n * @returns The sanitized version string.\n */\nexport function semverSanitize(version: string): string {\n return (\n semver.valid(version) || semver.coerce(version, { includePrerelease: true })?.version || ''\n );\n}\n\n/**\n * Get the latest publihsed version of a package.\n * @param package metadata\n **/\nexport function getLatest(pkg: Manifest): string {\n const listVersions: string[] = Object.keys(pkg.versions);\n if (listVersions.length < 1) {\n throw Error('cannot get lastest version of none');\n }\n\n const versions: string[] = semverSort(listVersions);\n const latest: string | undefined = pkg[DIST_TAGS]?.latest ? pkg[DIST_TAGS].latest : versions[0];\n\n return latest;\n}\n\n/**\n * Function gets a local info and an info from uplinks and tries to merge it\n exported for unit tests only.\n * @param {*} local\n * @param {*} upstream\n * @param {*} config sds\n * @deprecated use @verdaccio/storage mergeVersions method\n */\n// @deprecated\nexport function mergeVersions(local: Manifest, upstream: Manifest) {\n // copy new versions to a cache\n // NOTE: if a certain version was updated, we can't refresh it reliably\n for (const i in upstream.versions) {\n if (typeof local.versions[i] === 'undefined') {\n local.versions[i] = upstream.versions[i];\n }\n }\n\n for (const i in upstream[DIST_TAGS]) {\n if (local[DIST_TAGS][i] !== upstream[DIST_TAGS][i]) {\n if (!local[DIST_TAGS][i] || semver.lte(local[DIST_TAGS][i], upstream[DIST_TAGS][i])) {\n local[DIST_TAGS][i] = upstream[DIST_TAGS][i];\n }\n if (i === 'latest' && local[DIST_TAGS][i] === upstream[DIST_TAGS][i]) {\n // if remote has more fresh package, we should borrow its readme\n local.readme = upstream.readme;\n }\n }\n }\n}\n\n/**\n * Get package informations from package.json\n * @param packagePath - The path to the package.json file.\n * @returns The package.json content\n */\nexport function getPackageJson(packagePath: string, relativePath: string): Record<string, unknown> {\n const packageJsonPath = path.join(packagePath, relativePath, 'package.json');\n return JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"pkg-utils.js","names":[],"sources":["../src/pkg-utils.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport semver from 'semver';\n\nimport type { Manifest } from '@verdaccio/types';\n\nimport { DIST_TAGS } from './constants';\n\n/**\n * Function filters out bad semver versions and sorts the array.\n * @return {Array} sorted Array\n */\nexport function semverSort(listVersions: string[]): string[] {\n return listVersions\n .filter(function (x): boolean {\n if (!semver.parse(x, true)) {\n return false;\n }\n return true;\n })\n .sort(semver.compareLoose)\n .map(String);\n}\n\n/**\n * Sanitize a version string to a valid semver version.\n * @param version - The version string to sanitize.\n * @returns The sanitized version string.\n */\nexport function semverSanitize(version: string): string {\n return (\n semver.valid(version) || semver.coerce(version, { includePrerelease: true })?.version || ''\n );\n}\n\n/**\n * Get the version tagged as latest in the dist-tags of a package.\n * @param package metadata\n **/\nexport function getLatestVersion(pkgInfo: Manifest): string {\n return pkgInfo[DIST_TAGS].latest;\n}\n\n/**\n * Get the latest publihsed version of a package.\n * @param package metadata\n **/\nexport function getLatest(pkg: Manifest): string {\n const listVersions: string[] = Object.keys(pkg.versions);\n if (listVersions.length < 1) {\n throw Error('cannot get lastest version of none');\n }\n\n const versions: string[] = semverSort(listVersions);\n const latest: string | undefined = pkg[DIST_TAGS]?.latest ? pkg[DIST_TAGS].latest : versions[0];\n\n return latest;\n}\n\n/**\n * Function gets a local info and an info from uplinks and tries to merge it\n exported for unit tests only.\n * @param {*} local\n * @param {*} upstream\n * @param {*} config sds\n * @deprecated use @verdaccio/storage mergeVersions method\n */\n// @deprecated\nexport function mergeVersions(local: Manifest, upstream: Manifest) {\n // copy new versions to a cache\n // NOTE: if a certain version was updated, we can't refresh it reliably\n for (const i in upstream.versions) {\n if (typeof local.versions[i] === 'undefined') {\n local.versions[i] = upstream.versions[i];\n }\n }\n\n for (const i in upstream[DIST_TAGS]) {\n if (local[DIST_TAGS][i] !== upstream[DIST_TAGS][i]) {\n if (!local[DIST_TAGS][i] || semver.lte(local[DIST_TAGS][i], upstream[DIST_TAGS][i])) {\n local[DIST_TAGS][i] = upstream[DIST_TAGS][i];\n }\n if (i === 'latest' && local[DIST_TAGS][i] === upstream[DIST_TAGS][i]) {\n // if remote has more fresh package, we should borrow its readme\n local.readme = upstream.readme;\n }\n }\n }\n}\n\n/**\n * Get package informations from package.json\n * @param packagePath - The path to the package.json file.\n * @returns The package.json content\n */\nexport function getPackageJson(packagePath: string, relativePath: string): Record<string, unknown> {\n const packageJsonPath = path.join(packagePath, relativePath, 'package.json');\n return JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAYA,SAAgB,WAAW,cAAkC;CAC3D,OAAO,aACJ,OAAO,SAAU,GAAY;EAC5B,IAAI,CAAC,OAAA,QAAO,MAAM,GAAG,IAAI,GACvB,OAAO;EAET,OAAO;CACT,CAAC,CAAC,CACD,KAAK,OAAA,QAAO,YAAY,CAAC,CACzB,IAAI,MAAM;AACf;;;;;;AAOA,SAAgB,eAAe,SAAyB;CACtD,OACE,OAAA,QAAO,MAAM,OAAO,KAAK,OAAA,QAAO,OAAO,SAAS,EAAE,mBAAmB,KAAK,CAAC,CAAC,EAAE,WAAW;AAE7F;;;;;AAMA,SAAgB,iBAAiB,SAA2B;CAC1D,OAAO,QAAQ,kBAAA,UAAU,CAAC;AAC5B;;;;;AAMA,SAAgB,UAAU,KAAuB;CAC/C,MAAM,eAAyB,OAAO,KAAK,IAAI,QAAQ;CACvD,IAAI,aAAa,SAAS,GACxB,MAAM,MAAM,oCAAoC;CAGlD,MAAM,WAAqB,WAAW,YAAY;CAGlD,OAFmC,IAAA,YAAc,EAAE,SAAS,IAAI,kBAAA,UAAU,CAAC,SAAS,SAAS;AAG/F;;;;;;;;;AAWA,SAAgB,cAAc,OAAiB,UAAoB;CAGjE,KAAK,MAAM,KAAK,SAAS,UACvB,IAAI,OAAO,MAAM,SAAS,OAAO,aAC/B,MAAM,SAAS,KAAK,SAAS,SAAS;CAI1C,KAAK,MAAM,KAAK,SAAS,kBAAA,YACvB,IAAI,MAAA,YAAgB,CAAC,OAAO,SAAA,YAAmB,CAAC,IAAI;EAClD,IAAI,CAAC,MAAA,YAAgB,CAAC,MAAM,OAAA,QAAO,IAAI,MAAA,YAAgB,CAAC,IAAI,SAAA,YAAmB,CAAC,EAAE,GAChF,MAAM,kBAAA,UAAU,CAAC,KAAK,SAAS,kBAAA,UAAU,CAAC;EAE5C,IAAI,MAAM,YAAY,MAAA,YAAgB,CAAC,OAAO,SAAA,YAAmB,CAAC,IAEhE,MAAM,SAAS,SAAS;CAE5B;AAEJ;;;;;;AAOA,SAAgB,eAAe,aAAqB,cAA+C;CACjG,MAAM,kBAAkB,UAAA,QAAK,KAAK,aAAa,cAAc,cAAc;CAC3E,OAAO,KAAK,MAAM,QAAA,QAAG,aAAa,iBAAiB,MAAM,CAAC;AAC5D"}
|
package/build/pkg-utils.mjs
CHANGED
|
@@ -6,6 +6,7 @@ import semver from "semver";
|
|
|
6
6
|
//#region src/pkg-utils.ts
|
|
7
7
|
var pkg_utils_exports = /* @__PURE__ */ __exportAll({
|
|
8
8
|
getLatest: () => getLatest,
|
|
9
|
+
getLatestVersion: () => getLatestVersion,
|
|
9
10
|
getPackageJson: () => getPackageJson,
|
|
10
11
|
mergeVersions: () => mergeVersions,
|
|
11
12
|
semverSanitize: () => semverSanitize,
|
|
@@ -30,6 +31,13 @@ function semverSanitize(version) {
|
|
|
30
31
|
return semver.valid(version) || semver.coerce(version, { includePrerelease: true })?.version || "";
|
|
31
32
|
}
|
|
32
33
|
/**
|
|
34
|
+
* Get the version tagged as latest in the dist-tags of a package.
|
|
35
|
+
* @param package metadata
|
|
36
|
+
**/
|
|
37
|
+
function getLatestVersion(pkgInfo) {
|
|
38
|
+
return pkgInfo[DIST_TAGS].latest;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
33
41
|
* Get the latest publihsed version of a package.
|
|
34
42
|
* @param package metadata
|
|
35
43
|
**/
|
|
@@ -64,6 +72,6 @@ function getPackageJson(packagePath, relativePath) {
|
|
|
64
72
|
return JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
65
73
|
}
|
|
66
74
|
//#endregion
|
|
67
|
-
export { getLatest, getPackageJson, mergeVersions, pkg_utils_exports, semverSanitize, semverSort };
|
|
75
|
+
export { getLatest, getLatestVersion, getPackageJson, mergeVersions, pkg_utils_exports, semverSanitize, semverSort };
|
|
68
76
|
|
|
69
77
|
//# sourceMappingURL=pkg-utils.mjs.map
|
package/build/pkg-utils.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pkg-utils.mjs","names":[],"sources":["../src/pkg-utils.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport semver from 'semver';\n\nimport type { Manifest } from '@verdaccio/types';\n\nimport { DIST_TAGS } from './constants';\n\n/**\n * Function filters out bad semver versions and sorts the array.\n * @return {Array} sorted Array\n */\nexport function semverSort(listVersions: string[]): string[] {\n return listVersions\n .filter(function (x): boolean {\n if (!semver.parse(x, true)) {\n return false;\n }\n return true;\n })\n .sort(semver.compareLoose)\n .map(String);\n}\n\n/**\n * Sanitize a version string to a valid semver version.\n * @param version - The version string to sanitize.\n * @returns The sanitized version string.\n */\nexport function semverSanitize(version: string): string {\n return (\n semver.valid(version) || semver.coerce(version, { includePrerelease: true })?.version || ''\n );\n}\n\n/**\n * Get the latest publihsed version of a package.\n * @param package metadata\n **/\nexport function getLatest(pkg: Manifest): string {\n const listVersions: string[] = Object.keys(pkg.versions);\n if (listVersions.length < 1) {\n throw Error('cannot get lastest version of none');\n }\n\n const versions: string[] = semverSort(listVersions);\n const latest: string | undefined = pkg[DIST_TAGS]?.latest ? pkg[DIST_TAGS].latest : versions[0];\n\n return latest;\n}\n\n/**\n * Function gets a local info and an info from uplinks and tries to merge it\n exported for unit tests only.\n * @param {*} local\n * @param {*} upstream\n * @param {*} config sds\n * @deprecated use @verdaccio/storage mergeVersions method\n */\n// @deprecated\nexport function mergeVersions(local: Manifest, upstream: Manifest) {\n // copy new versions to a cache\n // NOTE: if a certain version was updated, we can't refresh it reliably\n for (const i in upstream.versions) {\n if (typeof local.versions[i] === 'undefined') {\n local.versions[i] = upstream.versions[i];\n }\n }\n\n for (const i in upstream[DIST_TAGS]) {\n if (local[DIST_TAGS][i] !== upstream[DIST_TAGS][i]) {\n if (!local[DIST_TAGS][i] || semver.lte(local[DIST_TAGS][i], upstream[DIST_TAGS][i])) {\n local[DIST_TAGS][i] = upstream[DIST_TAGS][i];\n }\n if (i === 'latest' && local[DIST_TAGS][i] === upstream[DIST_TAGS][i]) {\n // if remote has more fresh package, we should borrow its readme\n local.readme = upstream.readme;\n }\n }\n }\n}\n\n/**\n * Get package informations from package.json\n * @param packagePath - The path to the package.json file.\n * @returns The package.json content\n */\nexport function getPackageJson(packagePath: string, relativePath: string): Record<string, unknown> {\n const packageJsonPath = path.join(packagePath, relativePath, 'package.json');\n return JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"pkg-utils.mjs","names":[],"sources":["../src/pkg-utils.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport semver from 'semver';\n\nimport type { Manifest } from '@verdaccio/types';\n\nimport { DIST_TAGS } from './constants';\n\n/**\n * Function filters out bad semver versions and sorts the array.\n * @return {Array} sorted Array\n */\nexport function semverSort(listVersions: string[]): string[] {\n return listVersions\n .filter(function (x): boolean {\n if (!semver.parse(x, true)) {\n return false;\n }\n return true;\n })\n .sort(semver.compareLoose)\n .map(String);\n}\n\n/**\n * Sanitize a version string to a valid semver version.\n * @param version - The version string to sanitize.\n * @returns The sanitized version string.\n */\nexport function semverSanitize(version: string): string {\n return (\n semver.valid(version) || semver.coerce(version, { includePrerelease: true })?.version || ''\n );\n}\n\n/**\n * Get the version tagged as latest in the dist-tags of a package.\n * @param package metadata\n **/\nexport function getLatestVersion(pkgInfo: Manifest): string {\n return pkgInfo[DIST_TAGS].latest;\n}\n\n/**\n * Get the latest publihsed version of a package.\n * @param package metadata\n **/\nexport function getLatest(pkg: Manifest): string {\n const listVersions: string[] = Object.keys(pkg.versions);\n if (listVersions.length < 1) {\n throw Error('cannot get lastest version of none');\n }\n\n const versions: string[] = semverSort(listVersions);\n const latest: string | undefined = pkg[DIST_TAGS]?.latest ? pkg[DIST_TAGS].latest : versions[0];\n\n return latest;\n}\n\n/**\n * Function gets a local info and an info from uplinks and tries to merge it\n exported for unit tests only.\n * @param {*} local\n * @param {*} upstream\n * @param {*} config sds\n * @deprecated use @verdaccio/storage mergeVersions method\n */\n// @deprecated\nexport function mergeVersions(local: Manifest, upstream: Manifest) {\n // copy new versions to a cache\n // NOTE: if a certain version was updated, we can't refresh it reliably\n for (const i in upstream.versions) {\n if (typeof local.versions[i] === 'undefined') {\n local.versions[i] = upstream.versions[i];\n }\n }\n\n for (const i in upstream[DIST_TAGS]) {\n if (local[DIST_TAGS][i] !== upstream[DIST_TAGS][i]) {\n if (!local[DIST_TAGS][i] || semver.lte(local[DIST_TAGS][i], upstream[DIST_TAGS][i])) {\n local[DIST_TAGS][i] = upstream[DIST_TAGS][i];\n }\n if (i === 'latest' && local[DIST_TAGS][i] === upstream[DIST_TAGS][i]) {\n // if remote has more fresh package, we should borrow its readme\n local.readme = upstream.readme;\n }\n }\n }\n}\n\n/**\n * Get package informations from package.json\n * @param packagePath - The path to the package.json file.\n * @returns The package.json content\n */\nexport function getPackageJson(packagePath: string, relativePath: string): Record<string, unknown> {\n const packageJsonPath = path.join(packagePath, relativePath, 'package.json');\n return JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAYA,SAAgB,WAAW,cAAkC;CAC3D,OAAO,aACJ,OAAO,SAAU,GAAY;EAC5B,IAAI,CAAC,OAAO,MAAM,GAAG,IAAI,GACvB,OAAO;EAET,OAAO;CACT,CAAC,CAAC,CACD,KAAK,OAAO,YAAY,CAAC,CACzB,IAAI,MAAM;AACf;;;;;;AAOA,SAAgB,eAAe,SAAyB;CACtD,OACE,OAAO,MAAM,OAAO,KAAK,OAAO,OAAO,SAAS,EAAE,mBAAmB,KAAK,CAAC,CAAC,EAAE,WAAW;AAE7F;;;;;AAMA,SAAgB,iBAAiB,SAA2B;CAC1D,OAAO,QAAQ,UAAU,CAAC;AAC5B;;;;;AAMA,SAAgB,UAAU,KAAuB;CAC/C,MAAM,eAAyB,OAAO,KAAK,IAAI,QAAQ;CACvD,IAAI,aAAa,SAAS,GACxB,MAAM,MAAM,oCAAoC;CAGlD,MAAM,WAAqB,WAAW,YAAY;CAGlD,OAFmC,IAAA,YAAc,EAAE,SAAS,IAAI,UAAU,CAAC,SAAS,SAAS;AAG/F;;;;;;;;;AAWA,SAAgB,cAAc,OAAiB,UAAoB;CAGjE,KAAK,MAAM,KAAK,SAAS,UACvB,IAAI,OAAO,MAAM,SAAS,OAAO,aAC/B,MAAM,SAAS,KAAK,SAAS,SAAS;CAI1C,KAAK,MAAM,KAAK,SAAS,YACvB,IAAI,MAAA,YAAgB,CAAC,OAAO,SAAA,YAAmB,CAAC,IAAI;EAClD,IAAI,CAAC,MAAA,YAAgB,CAAC,MAAM,OAAO,IAAI,MAAA,YAAgB,CAAC,IAAI,SAAA,YAAmB,CAAC,EAAE,GAChF,MAAM,UAAU,CAAC,KAAK,SAAS,UAAU,CAAC;EAE5C,IAAI,MAAM,YAAY,MAAA,YAAgB,CAAC,OAAO,SAAA,YAAmB,CAAC,IAEhE,MAAM,SAAS,SAAS;CAE5B;AAEJ;;;;;;AAOA,SAAgB,eAAe,aAAqB,cAA+C;CACjG,MAAM,kBAAkB,KAAK,KAAK,aAAa,cAAc,cAAc;CAC3E,OAAO,KAAK,MAAM,GAAG,aAAa,iBAAiB,MAAM,CAAC;AAC5D"}
|
|
@@ -52,9 +52,10 @@ function validateName(name) {
|
|
|
52
52
|
* @return {Boolean} whether the package is valid or not
|
|
53
53
|
*/
|
|
54
54
|
function validatePackage(name) {
|
|
55
|
-
const nameList = name.split("/"
|
|
55
|
+
const nameList = name.split("/");
|
|
56
56
|
if (nameList.length === 1) return validateName(nameList[0]);
|
|
57
|
-
return nameList[0][0] === "@" && validateName(nameList[0].slice(1)) && validateName(nameList[1]);
|
|
57
|
+
else if (nameList.length === 2) return nameList[0][0] === "@" && validateName(nameList[0].slice(1)) && validateName(nameList[1]);
|
|
58
|
+
return false;
|
|
58
59
|
}
|
|
59
60
|
/**
|
|
60
61
|
* Validate the package metadata, add additional properties whether are missing within
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation-utils.js","names":[],"sources":["../src/validation-utils.ts"],"sourcesContent":["import assert from 'node:assert';\n\nimport type { Manifest } from '@verdaccio/types';\n\nimport { DEFAULT_PASSWORD_VALIDATION, DIST_TAGS, MAINTAINERS } from './constants';\n\nexport { validatePublishSingleVersion } from './schemes/publish-manifest';\nexport { validateUnPublishSingleVersion } from './schemes/unpublish-manifest';\n\nexport function isPackageNameScoped(name: string): boolean {\n return name.startsWith('@');\n}\n\n/**\n * From normalize-package-data/lib/fixer.js\n * @param {*} name the package name\n * @return {Boolean} whether is valid or not\n */\nexport function validateName(name: string): boolean {\n if (typeof name !== 'string') {\n return false;\n }\n\n let normalizedName: string = name.toLowerCase();\n\n const isScoped: boolean = isPackageNameScoped(name);\n const scopedName = name.split('/', 2)[1];\n\n if (isScoped && typeof scopedName !== 'undefined') {\n normalizedName = scopedName.toLowerCase();\n }\n\n /**\n * Some context about the first regex\n * - npm used to have a different tarball naming system.\n * eg: http://registry.npmjs.com/thirty-two\n * https://registry.npmjs.org/thirty-two/-/thirty-two@0.0.1.tgz\n * The file name thirty-two@0.0.1.tgz, the version and the pkg name was separated by an at (@)\n * while nowadays the naming system is based in dashes\n * https://registry.npmjs.org/verdaccio/-/verdaccio-1.4.0.tgz\n *\n * more info here: https://github.com/rlidwka/sinopia/issues/75\n */\n return !(\n !normalizedName.match(/^[-a-zA-Z0-9_.!~*'()@]+$/) ||\n normalizedName.startsWith('.') || // \".bin\", etc.\n ['node_modules', '__proto__', 'favicon.ico'].includes(normalizedName)\n );\n}\n\n/**\n * Validate a package.\n * @return {Boolean} whether the package is valid or not\n */\nexport function validatePackage(name: string): boolean {\n const nameList = name.split('/'
|
|
1
|
+
{"version":3,"file":"validation-utils.js","names":[],"sources":["../src/validation-utils.ts"],"sourcesContent":["import assert from 'node:assert';\n\nimport type { Manifest } from '@verdaccio/types';\n\nimport { DEFAULT_PASSWORD_VALIDATION, DIST_TAGS, MAINTAINERS } from './constants';\n\nexport { validatePublishSingleVersion } from './schemes/publish-manifest';\nexport { validateUnPublishSingleVersion } from './schemes/unpublish-manifest';\n\nexport function isPackageNameScoped(name: string): boolean {\n return name.startsWith('@');\n}\n\n/**\n * From normalize-package-data/lib/fixer.js\n * @param {*} name the package name\n * @return {Boolean} whether is valid or not\n */\nexport function validateName(name: string): boolean {\n if (typeof name !== 'string') {\n return false;\n }\n\n let normalizedName: string = name.toLowerCase();\n\n const isScoped: boolean = isPackageNameScoped(name);\n const scopedName = name.split('/', 2)[1];\n\n if (isScoped && typeof scopedName !== 'undefined') {\n normalizedName = scopedName.toLowerCase();\n }\n\n /**\n * Some context about the first regex\n * - npm used to have a different tarball naming system.\n * eg: http://registry.npmjs.com/thirty-two\n * https://registry.npmjs.org/thirty-two/-/thirty-two@0.0.1.tgz\n * The file name thirty-two@0.0.1.tgz, the version and the pkg name was separated by an at (@)\n * while nowadays the naming system is based in dashes\n * https://registry.npmjs.org/verdaccio/-/verdaccio-1.4.0.tgz\n *\n * more info here: https://github.com/rlidwka/sinopia/issues/75\n */\n return !(\n !normalizedName.match(/^[-a-zA-Z0-9_.!~*'()@]+$/) ||\n normalizedName.startsWith('.') || // \".bin\", etc.\n ['node_modules', '__proto__', 'favicon.ico'].includes(normalizedName)\n );\n}\n\n/**\n * Validate a package.\n * @return {Boolean} whether the package is valid or not\n */\nexport function validatePackage(name: string): boolean {\n // Split on every separator (no limit) so trailing or interior slashes are not\n // silently dropped, keeping a single canonical form per package name.\n const nameList = name.split('/');\n if (nameList.length === 1) {\n // normal package\n return validateName(nameList[0]);\n } else if (nameList.length === 2) {\n // scoped package\n return (\n nameList[0][0] === '@' && validateName(nameList[0].slice(1)) && validateName(nameList[1])\n );\n }\n // anything with 3+ segments is never a valid package name\n return false;\n}\n\n/**\n * Validate the package metadata, add additional properties whether are missing within\n * the metadata properties.\n * @param {*} manifest\n * @param {*} name\n * @return {Object} the object with additional properties as dist-tags ad versions\n */\nexport function normalizeMetadata(manifest: Manifest, name: string): Manifest {\n assert.strictEqual(manifest.name, name);\n const _manifest = { ...manifest };\n\n if (!isObject(manifest[DIST_TAGS])) {\n _manifest[DIST_TAGS] = {};\n }\n\n if (!Array.isArray(manifest[MAINTAINERS])) {\n _manifest[MAINTAINERS] = [];\n }\n\n // This may not be needed\n if (!isObject(manifest['versions'])) {\n _manifest['versions'] = {};\n }\n\n if (!isObject(manifest['time'])) {\n _manifest['time'] = {};\n }\n\n return _manifest;\n}\n\n/**\n * Check whether an element is an Object\n * @param {*} obj the element\n * @return {Boolean}\n */\nexport function isObject(obj: any): boolean {\n // if (obj === null || typeof obj === 'undefined' || typeof obj === 'string') {\n // return false;\n // }\n\n // return (\n // (typeof obj === 'object' || typeof obj.prototype === 'undefined') &&\n // Array.isArray(obj) === false\n // );\n return Object.prototype.toString.call(obj) === '[object Object]';\n}\n\nexport function validatePassword(\n password: string,\n validation: RegExp = DEFAULT_PASSWORD_VALIDATION\n): boolean {\n return typeof password === 'string' && validation instanceof RegExp\n ? password.match(validation) !== null\n : false;\n}\n\nexport function validateUserName(userName: any, expectedName: string): boolean {\n return (\n typeof userName === 'string' &&\n userName.split(':')[0] === 'org.couchdb.user' &&\n userName.split(':')[1] === expectedName\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AASA,SAAgB,oBAAoB,MAAuB;CACzD,OAAO,KAAK,WAAW,GAAG;AAC5B;;;;;;AAOA,SAAgB,aAAa,MAAuB;CAClD,IAAI,OAAO,SAAS,UAClB,OAAO;CAGT,IAAI,iBAAyB,KAAK,YAAY;CAE9C,MAAM,WAAoB,oBAAoB,IAAI;CAClD,MAAM,aAAa,KAAK,MAAM,KAAK,CAAC,CAAC,CAAC;CAEtC,IAAI,YAAY,OAAO,eAAe,aACpC,iBAAiB,WAAW,YAAY;;;;;;;;;;;;CAc1C,OAAO,EACL,CAAC,eAAe,MAAM,0BAA0B,KAChD,eAAe,WAAW,GAAG,KAC7B;EAAC;EAAgB;EAAa;CAAa,CAAC,CAAC,SAAS,cAAc;AAExE;;;;;AAMA,SAAgB,gBAAgB,MAAuB;CAGrD,MAAM,WAAW,KAAK,MAAM,GAAG;CAC/B,IAAI,SAAS,WAAW,GAEtB,OAAO,aAAa,SAAS,EAAE;MAC1B,IAAI,SAAS,WAAW,GAE7B,OACE,SAAS,EAAE,CAAC,OAAO,OAAO,aAAa,SAAS,EAAE,CAAC,MAAM,CAAC,CAAC,KAAK,aAAa,SAAS,EAAE;CAI5F,OAAO;AACT;;;;;;;;AASA,SAAgB,kBAAkB,UAAoB,MAAwB;CAC5E,YAAA,QAAO,YAAY,SAAS,MAAM,IAAI;CACtC,MAAM,YAAY,EAAE,GAAG,SAAS;CAEhC,IAAI,CAAC,SAAS,SAAA,YAAmB,GAC/B,UAAU,kBAAA,aAAa,CAAC;CAG1B,IAAI,CAAC,MAAM,QAAQ,SAAA,cAAqB,GACtC,UAAU,kBAAA,eAAe,CAAC;CAI5B,IAAI,CAAC,SAAS,SAAS,WAAW,GAChC,UAAU,cAAc,CAAC;CAG3B,IAAI,CAAC,SAAS,SAAS,OAAO,GAC5B,UAAU,UAAU,CAAC;CAGvB,OAAO;AACT;;;;;;AAOA,SAAgB,SAAS,KAAmB;CAS1C,OAAO,OAAO,UAAU,SAAS,KAAK,GAAG,MAAM;AACjD;AAEA,SAAgB,iBACd,UACA,aAAqB,kBAAA,6BACZ;CACT,OAAO,OAAO,aAAa,YAAY,sBAAsB,SACzD,SAAS,MAAM,UAAU,MAAM,OAC/B;AACN;AAEA,SAAgB,iBAAiB,UAAe,cAA+B;CAC7E,OACE,OAAO,aAAa,YACpB,SAAS,MAAM,GAAG,CAAC,CAAC,OAAO,sBAC3B,SAAS,MAAM,GAAG,CAAC,CAAC,OAAO;AAE/B"}
|
|
@@ -51,9 +51,10 @@ function validateName(name) {
|
|
|
51
51
|
* @return {Boolean} whether the package is valid or not
|
|
52
52
|
*/
|
|
53
53
|
function validatePackage(name) {
|
|
54
|
-
const nameList = name.split("/"
|
|
54
|
+
const nameList = name.split("/");
|
|
55
55
|
if (nameList.length === 1) return validateName(nameList[0]);
|
|
56
|
-
return nameList[0][0] === "@" && validateName(nameList[0].slice(1)) && validateName(nameList[1]);
|
|
56
|
+
else if (nameList.length === 2) return nameList[0][0] === "@" && validateName(nameList[0].slice(1)) && validateName(nameList[1]);
|
|
57
|
+
return false;
|
|
57
58
|
}
|
|
58
59
|
/**
|
|
59
60
|
* Validate the package metadata, add additional properties whether are missing within
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation-utils.mjs","names":[],"sources":["../src/validation-utils.ts"],"sourcesContent":["import assert from 'node:assert';\n\nimport type { Manifest } from '@verdaccio/types';\n\nimport { DEFAULT_PASSWORD_VALIDATION, DIST_TAGS, MAINTAINERS } from './constants';\n\nexport { validatePublishSingleVersion } from './schemes/publish-manifest';\nexport { validateUnPublishSingleVersion } from './schemes/unpublish-manifest';\n\nexport function isPackageNameScoped(name: string): boolean {\n return name.startsWith('@');\n}\n\n/**\n * From normalize-package-data/lib/fixer.js\n * @param {*} name the package name\n * @return {Boolean} whether is valid or not\n */\nexport function validateName(name: string): boolean {\n if (typeof name !== 'string') {\n return false;\n }\n\n let normalizedName: string = name.toLowerCase();\n\n const isScoped: boolean = isPackageNameScoped(name);\n const scopedName = name.split('/', 2)[1];\n\n if (isScoped && typeof scopedName !== 'undefined') {\n normalizedName = scopedName.toLowerCase();\n }\n\n /**\n * Some context about the first regex\n * - npm used to have a different tarball naming system.\n * eg: http://registry.npmjs.com/thirty-two\n * https://registry.npmjs.org/thirty-two/-/thirty-two@0.0.1.tgz\n * The file name thirty-two@0.0.1.tgz, the version and the pkg name was separated by an at (@)\n * while nowadays the naming system is based in dashes\n * https://registry.npmjs.org/verdaccio/-/verdaccio-1.4.0.tgz\n *\n * more info here: https://github.com/rlidwka/sinopia/issues/75\n */\n return !(\n !normalizedName.match(/^[-a-zA-Z0-9_.!~*'()@]+$/) ||\n normalizedName.startsWith('.') || // \".bin\", etc.\n ['node_modules', '__proto__', 'favicon.ico'].includes(normalizedName)\n );\n}\n\n/**\n * Validate a package.\n * @return {Boolean} whether the package is valid or not\n */\nexport function validatePackage(name: string): boolean {\n const nameList = name.split('/'
|
|
1
|
+
{"version":3,"file":"validation-utils.mjs","names":[],"sources":["../src/validation-utils.ts"],"sourcesContent":["import assert from 'node:assert';\n\nimport type { Manifest } from '@verdaccio/types';\n\nimport { DEFAULT_PASSWORD_VALIDATION, DIST_TAGS, MAINTAINERS } from './constants';\n\nexport { validatePublishSingleVersion } from './schemes/publish-manifest';\nexport { validateUnPublishSingleVersion } from './schemes/unpublish-manifest';\n\nexport function isPackageNameScoped(name: string): boolean {\n return name.startsWith('@');\n}\n\n/**\n * From normalize-package-data/lib/fixer.js\n * @param {*} name the package name\n * @return {Boolean} whether is valid or not\n */\nexport function validateName(name: string): boolean {\n if (typeof name !== 'string') {\n return false;\n }\n\n let normalizedName: string = name.toLowerCase();\n\n const isScoped: boolean = isPackageNameScoped(name);\n const scopedName = name.split('/', 2)[1];\n\n if (isScoped && typeof scopedName !== 'undefined') {\n normalizedName = scopedName.toLowerCase();\n }\n\n /**\n * Some context about the first regex\n * - npm used to have a different tarball naming system.\n * eg: http://registry.npmjs.com/thirty-two\n * https://registry.npmjs.org/thirty-two/-/thirty-two@0.0.1.tgz\n * The file name thirty-two@0.0.1.tgz, the version and the pkg name was separated by an at (@)\n * while nowadays the naming system is based in dashes\n * https://registry.npmjs.org/verdaccio/-/verdaccio-1.4.0.tgz\n *\n * more info here: https://github.com/rlidwka/sinopia/issues/75\n */\n return !(\n !normalizedName.match(/^[-a-zA-Z0-9_.!~*'()@]+$/) ||\n normalizedName.startsWith('.') || // \".bin\", etc.\n ['node_modules', '__proto__', 'favicon.ico'].includes(normalizedName)\n );\n}\n\n/**\n * Validate a package.\n * @return {Boolean} whether the package is valid or not\n */\nexport function validatePackage(name: string): boolean {\n // Split on every separator (no limit) so trailing or interior slashes are not\n // silently dropped, keeping a single canonical form per package name.\n const nameList = name.split('/');\n if (nameList.length === 1) {\n // normal package\n return validateName(nameList[0]);\n } else if (nameList.length === 2) {\n // scoped package\n return (\n nameList[0][0] === '@' && validateName(nameList[0].slice(1)) && validateName(nameList[1])\n );\n }\n // anything with 3+ segments is never a valid package name\n return false;\n}\n\n/**\n * Validate the package metadata, add additional properties whether are missing within\n * the metadata properties.\n * @param {*} manifest\n * @param {*} name\n * @return {Object} the object with additional properties as dist-tags ad versions\n */\nexport function normalizeMetadata(manifest: Manifest, name: string): Manifest {\n assert.strictEqual(manifest.name, name);\n const _manifest = { ...manifest };\n\n if (!isObject(manifest[DIST_TAGS])) {\n _manifest[DIST_TAGS] = {};\n }\n\n if (!Array.isArray(manifest[MAINTAINERS])) {\n _manifest[MAINTAINERS] = [];\n }\n\n // This may not be needed\n if (!isObject(manifest['versions'])) {\n _manifest['versions'] = {};\n }\n\n if (!isObject(manifest['time'])) {\n _manifest['time'] = {};\n }\n\n return _manifest;\n}\n\n/**\n * Check whether an element is an Object\n * @param {*} obj the element\n * @return {Boolean}\n */\nexport function isObject(obj: any): boolean {\n // if (obj === null || typeof obj === 'undefined' || typeof obj === 'string') {\n // return false;\n // }\n\n // return (\n // (typeof obj === 'object' || typeof obj.prototype === 'undefined') &&\n // Array.isArray(obj) === false\n // );\n return Object.prototype.toString.call(obj) === '[object Object]';\n}\n\nexport function validatePassword(\n password: string,\n validation: RegExp = DEFAULT_PASSWORD_VALIDATION\n): boolean {\n return typeof password === 'string' && validation instanceof RegExp\n ? password.match(validation) !== null\n : false;\n}\n\nexport function validateUserName(userName: any, expectedName: string): boolean {\n return (\n typeof userName === 'string' &&\n userName.split(':')[0] === 'org.couchdb.user' &&\n userName.split(':')[1] === expectedName\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AASA,SAAgB,oBAAoB,MAAuB;CACzD,OAAO,KAAK,WAAW,GAAG;AAC5B;;;;;;AAOA,SAAgB,aAAa,MAAuB;CAClD,IAAI,OAAO,SAAS,UAClB,OAAO;CAGT,IAAI,iBAAyB,KAAK,YAAY;CAE9C,MAAM,WAAoB,oBAAoB,IAAI;CAClD,MAAM,aAAa,KAAK,MAAM,KAAK,CAAC,CAAC,CAAC;CAEtC,IAAI,YAAY,OAAO,eAAe,aACpC,iBAAiB,WAAW,YAAY;;;;;;;;;;;;CAc1C,OAAO,EACL,CAAC,eAAe,MAAM,0BAA0B,KAChD,eAAe,WAAW,GAAG,KAC7B;EAAC;EAAgB;EAAa;CAAa,CAAC,CAAC,SAAS,cAAc;AAExE;;;;;AAMA,SAAgB,gBAAgB,MAAuB;CAGrD,MAAM,WAAW,KAAK,MAAM,GAAG;CAC/B,IAAI,SAAS,WAAW,GAEtB,OAAO,aAAa,SAAS,EAAE;MAC1B,IAAI,SAAS,WAAW,GAE7B,OACE,SAAS,EAAE,CAAC,OAAO,OAAO,aAAa,SAAS,EAAE,CAAC,MAAM,CAAC,CAAC,KAAK,aAAa,SAAS,EAAE;CAI5F,OAAO;AACT;;;;;;;;AASA,SAAgB,kBAAkB,UAAoB,MAAwB;CAC5E,OAAO,YAAY,SAAS,MAAM,IAAI;CACtC,MAAM,YAAY,EAAE,GAAG,SAAS;CAEhC,IAAI,CAAC,SAAS,SAAA,YAAmB,GAC/B,UAAU,aAAa,CAAC;CAG1B,IAAI,CAAC,MAAM,QAAQ,SAAA,cAAqB,GACtC,UAAU,eAAe,CAAC;CAI5B,IAAI,CAAC,SAAS,SAAS,WAAW,GAChC,UAAU,cAAc,CAAC;CAG3B,IAAI,CAAC,SAAS,SAAS,OAAO,GAC5B,UAAU,UAAU,CAAC;CAGvB,OAAO;AACT;;;;;;AAOA,SAAgB,SAAS,KAAmB;CAS1C,OAAO,OAAO,UAAU,SAAS,KAAK,GAAG,MAAM;AACjD;AAEA,SAAgB,iBACd,UACA,aAAqB,6BACZ;CACT,OAAO,OAAO,aAAa,YAAY,sBAAsB,SACzD,SAAS,MAAM,UAAU,MAAM,OAC/B;AACN;AAEA,SAAgB,iBAAiB,UAAe,cAA+B;CAC7E,OACE,OAAO,aAAa,YACpB,SAAS,MAAM,GAAG,CAAC,CAAC,OAAO,sBAC3B,SAAS,MAAM,GAAG,CAAC,CAAC,OAAO;AAE/B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@verdaccio/core",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.3.0",
|
|
4
4
|
"description": "Verdaccio Core Components",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"enterprise",
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"ajv": "8.20.0",
|
|
52
52
|
"http-errors": "2.0.1",
|
|
53
53
|
"http-status-codes": "2.3.0",
|
|
54
|
+
"lodash": "4.18.1",
|
|
54
55
|
"minimatch": "10.2.6",
|
|
55
56
|
"process-warning": "1.0.0",
|
|
56
57
|
"semver": "7.8.5"
|