@verdaccio/store 9.0.0-next-9.32 → 9.0.0-next-9.34
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/index.js +3 -0
- package/build/index.mjs +2 -2
- package/build/lib/storage-utils.d.ts +8 -4
- package/build/lib/storage-utils.js +25 -0
- package/build/lib/storage-utils.js.map +1 -1
- package/build/lib/storage-utils.mjs +24 -2
- package/build/lib/storage-utils.mjs.map +1 -1
- package/build/storage.d.ts +11 -3
- package/build/storage.js +67 -42
- package/build/storage.js.map +1 -1
- package/build/storage.mjs +68 -43
- package/build/storage.mjs.map +1 -1
- package/build/type.d.ts +0 -6
- package/package.json +12 -12
package/build/index.js
CHANGED
|
@@ -12,6 +12,7 @@ exports.STAGE_NAMESPACE = require_stage_storage.STAGE_NAMESPACE;
|
|
|
12
12
|
exports.STORAGE = require_storage_utils.STORAGE;
|
|
13
13
|
exports.StageStorage = require_stage_storage.StageStorage;
|
|
14
14
|
exports.Storage = require_storage.Storage;
|
|
15
|
+
exports.UPSTREAM_MAINTAINER_PREFIX = require_storage_utils.UPSTREAM_MAINTAINER_PREFIX;
|
|
15
16
|
exports.WHITELIST = require_storage_utils.WHITELIST;
|
|
16
17
|
exports.applyManifestFilters = require_filter_pipeline.applyManifestFilters;
|
|
17
18
|
exports.checkPackageRemote = require_storage_utils.checkPackageRemote;
|
|
@@ -28,6 +29,7 @@ exports.isNewerVersion = require_versions_utils.isNewerVersion;
|
|
|
28
29
|
exports.isPublishablePackage = require_publish_utils.isPublishablePackage;
|
|
29
30
|
exports.loadFilterPlugins = require_filter_pipeline.loadFilterPlugins;
|
|
30
31
|
exports.lookupDistFile = require_storage_utils.lookupDistFile;
|
|
32
|
+
exports.maintainerAllowsLocalUser = require_storage_utils.maintainerAllowsLocalUser;
|
|
31
33
|
exports.mapManifestToSearchPackageBody = require_storage_utils.mapManifestToSearchPackageBody;
|
|
32
34
|
exports.mergeUplinkTimeIntoLocal = require_storage_utils.mergeUplinkTimeIntoLocal;
|
|
33
35
|
exports.mergeUplinkTimeIntoLocalNext = require_storage_utils.mergeUplinkTimeIntoLocalNext;
|
|
@@ -37,6 +39,7 @@ exports.normalizeDistTags = require_storage_utils.normalizeDistTags;
|
|
|
37
39
|
exports.normalizePackage = require_storage_utils.normalizePackage;
|
|
38
40
|
exports.prepareSearchPackage = require_storage_utils.prepareSearchPackage;
|
|
39
41
|
exports.removeLowerVersions = require_versions_utils.removeLowerVersions;
|
|
42
|
+
exports.scopeUpstreamMaintainers = require_storage_utils.scopeUpstreamMaintainers;
|
|
40
43
|
exports.sortVersionsAndFilterInvalid = require_versions_utils.sortVersionsAndFilterInvalid;
|
|
41
44
|
exports.tagVersion = require_versions_utils.tagVersion;
|
|
42
45
|
exports.tagVersionNext = require_versions_utils.tagVersionNext;
|
package/build/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { applyManifestFilters, loadFilterPlugins } from "./filter-pipeline.mjs";
|
|
2
2
|
import { isPublishablePackage } from "./lib/publish-utils.mjs";
|
|
3
3
|
import { getVersion, isNewerVersion, removeLowerVersions, sortVersionsAndFilterInvalid, tagVersion, tagVersionNext } from "./lib/versions-utils.mjs";
|
|
4
|
-
import { STORAGE, WHITELIST, checkPackageRemote, cleanUpLinksRef, cleanUpReadme, distFileFromVersion, generatePackageTemplate, generateRevision, getLatestReadme, hasDeprecatedVersions, isDeprecatedManifest, lookupDistFile, mapManifestToSearchPackageBody, mergeUplinkTimeIntoLocal, mergeUplinkTimeIntoLocalNext, mergeVersions, normalizeContributors, normalizeDistTags, normalizePackage, prepareSearchPackage, tarballMatchesFilename, updateUpLinkMetadata, uplinkServesUrl } from "./lib/storage-utils.mjs";
|
|
4
|
+
import { STORAGE, UPSTREAM_MAINTAINER_PREFIX, WHITELIST, checkPackageRemote, cleanUpLinksRef, cleanUpReadme, distFileFromVersion, generatePackageTemplate, generateRevision, getLatestReadme, hasDeprecatedVersions, isDeprecatedManifest, lookupDistFile, maintainerAllowsLocalUser, mapManifestToSearchPackageBody, mergeUplinkTimeIntoLocal, mergeUplinkTimeIntoLocalNext, mergeVersions, normalizeContributors, normalizeDistTags, normalizePackage, prepareSearchPackage, scopeUpstreamMaintainers, tarballMatchesFilename, updateUpLinkMetadata, uplinkServesUrl } from "./lib/storage-utils.mjs";
|
|
5
5
|
import { STAGE_NAMESPACE, StageStorage, toStagePackageVersion } from "./stage-storage.mjs";
|
|
6
6
|
import { Storage } from "./storage.mjs";
|
|
7
|
-
export { STAGE_NAMESPACE, STORAGE, StageStorage, Storage, WHITELIST, applyManifestFilters, checkPackageRemote, cleanUpLinksRef, cleanUpReadme, distFileFromVersion, generatePackageTemplate, generateRevision, getLatestReadme, getVersion, hasDeprecatedVersions, isDeprecatedManifest, isNewerVersion, isPublishablePackage, loadFilterPlugins, lookupDistFile, mapManifestToSearchPackageBody, mergeUplinkTimeIntoLocal, mergeUplinkTimeIntoLocalNext, mergeVersions, normalizeContributors, normalizeDistTags, normalizePackage, prepareSearchPackage, removeLowerVersions, sortVersionsAndFilterInvalid, tagVersion, tagVersionNext, tarballMatchesFilename, toStagePackageVersion, updateUpLinkMetadata, uplinkServesUrl };
|
|
7
|
+
export { STAGE_NAMESPACE, STORAGE, StageStorage, Storage, UPSTREAM_MAINTAINER_PREFIX, WHITELIST, applyManifestFilters, checkPackageRemote, cleanUpLinksRef, cleanUpReadme, distFileFromVersion, generatePackageTemplate, generateRevision, getLatestReadme, getVersion, hasDeprecatedVersions, isDeprecatedManifest, isNewerVersion, isPublishablePackage, loadFilterPlugins, lookupDistFile, maintainerAllowsLocalUser, mapManifestToSearchPackageBody, mergeUplinkTimeIntoLocal, mergeUplinkTimeIntoLocalNext, mergeVersions, normalizeContributors, normalizeDistTags, normalizePackage, prepareSearchPackage, removeLowerVersions, scopeUpstreamMaintainers, sortVersionsAndFilterInvalid, tagVersion, tagVersionNext, tarballMatchesFilename, toStagePackageVersion, updateUpLinkMetadata, uplinkServesUrl };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { searchUtils } from '@verdaccio/core';
|
|
2
|
-
import type { Author, DistFile, GenericBody, Manifest, ReadmeOptions, Version } from '@verdaccio/types';
|
|
2
|
+
import type { Author, DistFile, GenericBody, Manifest, Person, ReadmeOptions, Version } from '@verdaccio/types';
|
|
3
3
|
export declare const STORAGE: {
|
|
4
4
|
PACKAGE_FILE_NAME: string;
|
|
5
5
|
FILE_EXIST_ERROR: string;
|
|
@@ -39,8 +39,8 @@ export declare function updateUpLinkMetadata(uplinkName: string, manifest: Manif
|
|
|
39
39
|
'dist-tags': GenericBody;
|
|
40
40
|
time: GenericBody;
|
|
41
41
|
versions: import("@verdaccio/types").Versions;
|
|
42
|
-
maintainers?:
|
|
43
|
-
contributors?:
|
|
42
|
+
maintainers?: Person[];
|
|
43
|
+
contributors?: Person[];
|
|
44
44
|
readme?: string;
|
|
45
45
|
users?: import("@verdaccio/types").PackageUsers;
|
|
46
46
|
access?: any;
|
|
@@ -55,7 +55,7 @@ export declare function updateUpLinkMetadata(uplinkName: string, manifest: Manif
|
|
|
55
55
|
directory?: string;
|
|
56
56
|
};
|
|
57
57
|
keywords?: string[];
|
|
58
|
-
author?:
|
|
58
|
+
author?: Person;
|
|
59
59
|
_distfiles: import("@verdaccio/types").DistFiles;
|
|
60
60
|
_rev: string;
|
|
61
61
|
_attachments: import("@verdaccio/types").AttachMents;
|
|
@@ -70,6 +70,10 @@ export declare function updateUpLinkMetadata(uplinkName: string, manifest: Manif
|
|
|
70
70
|
};
|
|
71
71
|
};
|
|
72
72
|
export declare function prepareSearchPackage(data: Manifest): any;
|
|
73
|
+
/** Maintainer names copied from an uplink. Never a local account. */
|
|
74
|
+
export declare const UPSTREAM_MAINTAINER_PREFIX = "$uplink:";
|
|
75
|
+
export declare function scopeUpstreamMaintainers(maintainers: Person[], uplinkName: string): Person[];
|
|
76
|
+
export declare function maintainerAllowsLocalUser(maintainer: Person, username: string | undefined): boolean;
|
|
73
77
|
/**
|
|
74
78
|
* Function gets a local info and an info from uplinks and tries to merge it
|
|
75
79
|
exported for unit tests only.
|
|
@@ -171,6 +171,28 @@ function prepareSearchPackage(data) {
|
|
|
171
171
|
};
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
|
+
/** Maintainer names copied from an uplink. Never a local account. */
|
|
175
|
+
var UPSTREAM_MAINTAINER_PREFIX = "$uplink:";
|
|
176
|
+
function scopeUpstreamMaintainers(maintainers, uplinkName) {
|
|
177
|
+
const origin = uplinkName.length > 0 ? uplinkName : "remote";
|
|
178
|
+
return maintainers.map((maintainer) => {
|
|
179
|
+
if (typeof maintainer === "string") return scopeUpstreamMaintainerName(origin, maintainer);
|
|
180
|
+
const name = typeof maintainer?.name === "string" ? maintainer.name : "";
|
|
181
|
+
return {
|
|
182
|
+
...maintainer,
|
|
183
|
+
name: scopeUpstreamMaintainerName(origin, name)
|
|
184
|
+
};
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
function scopeUpstreamMaintainerName(uplinkName, name) {
|
|
188
|
+
if (name.startsWith("$uplink:")) return name;
|
|
189
|
+
return `${UPSTREAM_MAINTAINER_PREFIX}${uplinkName}:${name}`;
|
|
190
|
+
}
|
|
191
|
+
function maintainerAllowsLocalUser(maintainer, username) {
|
|
192
|
+
const name = typeof maintainer === "string" ? maintainer : maintainer?.name;
|
|
193
|
+
if (typeof name === "string" && name.startsWith("$uplink:")) return false;
|
|
194
|
+
return name === username || name === _verdaccio_core.ANONYMOUS_USER;
|
|
195
|
+
}
|
|
174
196
|
/**
|
|
175
197
|
* Function gets a local info and an info from uplinks and tries to merge it
|
|
176
198
|
exported for unit tests only.
|
|
@@ -344,6 +366,7 @@ function uplinkServesUrl(uplinkUrl, tarballUrl) {
|
|
|
344
366
|
}
|
|
345
367
|
//#endregion
|
|
346
368
|
exports.STORAGE = STORAGE;
|
|
369
|
+
exports.UPSTREAM_MAINTAINER_PREFIX = UPSTREAM_MAINTAINER_PREFIX;
|
|
347
370
|
exports.WHITELIST = WHITELIST;
|
|
348
371
|
exports.checkPackageRemote = checkPackageRemote;
|
|
349
372
|
exports.cleanUpLinksRef = cleanUpLinksRef;
|
|
@@ -355,6 +378,7 @@ exports.getLatestReadme = getLatestReadme;
|
|
|
355
378
|
exports.hasDeprecatedVersions = hasDeprecatedVersions;
|
|
356
379
|
exports.isDeprecatedManifest = isDeprecatedManifest;
|
|
357
380
|
exports.lookupDistFile = lookupDistFile;
|
|
381
|
+
exports.maintainerAllowsLocalUser = maintainerAllowsLocalUser;
|
|
358
382
|
exports.mapManifestToSearchPackageBody = mapManifestToSearchPackageBody;
|
|
359
383
|
exports.mergeUplinkTimeIntoLocal = mergeUplinkTimeIntoLocal;
|
|
360
384
|
exports.mergeUplinkTimeIntoLocalNext = mergeUplinkTimeIntoLocalNext;
|
|
@@ -363,6 +387,7 @@ exports.normalizeContributors = normalizeContributors;
|
|
|
363
387
|
exports.normalizeDistTags = normalizeDistTags;
|
|
364
388
|
exports.normalizePackage = normalizePackage;
|
|
365
389
|
exports.prepareSearchPackage = prepareSearchPackage;
|
|
390
|
+
exports.scopeUpstreamMaintainers = scopeUpstreamMaintainers;
|
|
366
391
|
exports.tarballMatchesFilename = tarballMatchesFilename;
|
|
367
392
|
exports.updateUpLinkMetadata = updateUpLinkMetadata;
|
|
368
393
|
exports.uplinkServesUrl = uplinkServesUrl;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage-utils.js","names":[],"sources":["../../src/lib/storage-utils.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { isNil, trim } from 'lodash-es';\nimport semver from 'semver';\n\nimport type { searchUtils } from '@verdaccio/core';\nimport {\n API_ERROR,\n DIST_TAGS,\n HTTP_STATUS,\n MAINTAINERS,\n USERS,\n cryptoUtils,\n errorUtils,\n pkgUtils,\n validationUtils,\n} from '@verdaccio/core';\nimport type {\n Author,\n DistFile,\n GenericBody,\n Manifest,\n ReadmeOptions,\n Version,\n} from '@verdaccio/types';\n\nimport { sortVersionsAndFilterInvalid } from './versions-utils';\n\nconst debug = buildDebug('verdaccio:storage:utils');\n\nexport const STORAGE = {\n PACKAGE_FILE_NAME: 'package.json',\n FILE_EXIST_ERROR: 'EEXISTS',\n NO_SUCH_FILE_ERROR: 'ENOENT',\n DEFAULT_REVISION: '0-0000000000000000',\n};\n\n/**\n * Create a new package in the storage, return a boilerplate package\n * @param name package name\n * @returns {Manifest}\n */\nexport function generatePackageTemplate(name: string): Manifest {\n return {\n // standard things\n name,\n versions: {},\n time: {},\n [USERS]: {},\n [DIST_TAGS]: {},\n [MAINTAINERS]: [],\n _uplinks: {},\n _distfiles: {},\n _attachments: {},\n _rev: '',\n };\n}\n\n/**\n * Normalize package properties, tags, revision id.\n * @param {Object} pkg package reference.\n */\nexport function normalizePackage(pkg: Manifest): Manifest {\n const pkgProperties = ['versions', 'dist-tags', '_distfiles', '_attachments', '_uplinks', 'time'];\n\n pkgProperties.forEach((key): void => {\n const pkgProp = pkg[key];\n\n if (isNil(pkgProp) || validationUtils.isObject(pkgProp) === false) {\n pkg[key] = {};\n }\n });\n\n if (typeof pkg?._rev !== 'string') {\n pkg._rev = STORAGE.DEFAULT_REVISION;\n }\n\n if (typeof pkg?._id !== 'string') {\n pkg._id = pkg.name;\n }\n\n // normalize dist-tags\n return normalizeDistTags(pkg);\n}\n\nexport function generateRevision(rev: string): string {\n const _rev = rev.split('-');\n\n return (+_rev[0] || 0) + 1 + '-' + cryptoUtils.generateRandomHexString();\n}\n\nexport function getLatestReadme(pkg: Manifest): string {\n const versions = pkg['versions'] || {};\n const distTags = pkg[DIST_TAGS] || {};\n // FIXME: here is a bit tricky add the types\n const latestVersion: Version | any = distTags['latest'] ? versions[distTags['latest']] || {} : {};\n let readme = trim(pkg.readme || latestVersion.readme || '');\n if (readme) {\n return readme;\n }\n\n // In case of empty readme - trying to get ANY readme in the following order:\n // 'next','beta','alpha','test','dev','canary'\n const readmeDistTagsPriority = ['next', 'beta', 'alpha', 'test', 'dev', 'canary'];\n readmeDistTagsPriority.forEach(function (tag): string | void {\n if (readme) {\n return readme;\n }\n const version: Version | any = distTags[tag] ? versions[distTags[tag]] || {} : {};\n readme = trim(version.readme || readme);\n });\n return readme;\n}\n\n/**\n * Cleanup readme from package version\n *\n * By default, we don't keep readmes for package versions, only one readme per package.\n * Using publish.keep_readmes you can override this behavior and keep all readmes\n * or only readmes for tagged versions.\n */\nexport function cleanUpReadme(\n version: Version,\n distTags?: GenericBody,\n keepReadmes?: ReadmeOptions\n): Version {\n if (keepReadmes === 'all') {\n return version;\n } else if (keepReadmes === 'tagged') {\n if (distTags && Object.values(distTags).includes(version.version)) {\n return version;\n }\n }\n\n if (isNil(version) === false) {\n version.readme = '';\n }\n\n return version;\n}\n\nexport const WHITELIST = [\n '_rev',\n 'name',\n 'versions',\n 'dist-tags',\n 'readme',\n 'time',\n '_id',\n 'users',\n 'maintainers',\n];\n\nexport function cleanUpLinksRef(result: Manifest, keepUpLinkData?: boolean): Manifest {\n const propertyToKeep = [...WHITELIST];\n if (keepUpLinkData === true) {\n propertyToKeep.push('_uplinks');\n }\n\n for (const i in result) {\n if (propertyToKeep.indexOf(i) === -1) {\n // Remove sections like '_uplinks' from response\n delete result[i];\n }\n }\n\n return result;\n}\n\n// TODO: move to abstract storage\n// @deprecated use abstract.storage.ts:checkPackageRemote\nexport function checkPackageRemote(\n name: string,\n isAllowPublishOffline: boolean,\n syncMetadata: Function\n): Promise<any> {\n return new Promise<void>((resolve, reject): void => {\n syncMetadata(name, null, {}, (err, packageJsonLocal, upLinksErrors): void => {\n // something weird\n if (err && err.status !== HTTP_STATUS.NOT_FOUND) {\n return reject(err);\n }\n\n // checking package exist already\n if (isNil(packageJsonLocal) === false) {\n return reject(errorUtils.getConflict(API_ERROR.PACKAGE_EXIST));\n }\n\n for (let errorItem = 0; errorItem < upLinksErrors.length; errorItem++) {\n // checking error\n // if uplink fails with a status other than 404, we report failure\n if (isNil(upLinksErrors[errorItem][0]) === false) {\n if (upLinksErrors[errorItem][0].status !== HTTP_STATUS.NOT_FOUND) {\n if (isAllowPublishOffline) {\n return resolve();\n }\n\n return reject(errorUtils.getServiceUnavailable(API_ERROR.UPLINK_OFFLINE_PUBLISH));\n }\n }\n }\n\n return resolve();\n });\n });\n}\n\n// @deprecated use export function mergeUplinkTimeIntoLocalNext\nexport function mergeUplinkTimeIntoLocal(localMetadata: Manifest, remoteMetadata: Manifest): any {\n if ('time' in remoteMetadata) {\n return Object.assign({}, localMetadata.time, remoteMetadata.time);\n }\n\n return localMetadata.time;\n}\n\nexport function mergeUplinkTimeIntoLocalNext(\n cacheManifest: Manifest,\n remoteManifest: Manifest\n): Manifest {\n if ('time' in remoteManifest) {\n // remote override cache time conflicts\n return { ...cacheManifest, time: { ...cacheManifest.time, ...remoteManifest.time } };\n }\n\n return cacheManifest;\n}\n\nexport function updateUpLinkMetadata(uplinkName: string, manifest: Manifest, etag: string) {\n const _uplinks = {\n ...manifest._uplinks,\n [uplinkName]: {\n etag,\n fetched: Date.now(),\n },\n };\n return {\n ...manifest,\n _uplinks,\n };\n}\n\nexport function prepareSearchPackage(data: Manifest): any {\n const latest = pkgUtils.getLatest(data);\n\n if (latest && data.versions[latest]) {\n const version: Version = data.versions[latest];\n const versions: any = { [latest]: 'latest' };\n const pkg: any = {\n name: version.name,\n description: version.description,\n [DIST_TAGS]: { latest },\n maintainers: version.maintainers || [version.author].filter(Boolean),\n author: version.author,\n repository: version.repository,\n readmeFilename: version.readmeFilename || '',\n homepage: version.homepage,\n keywords: version.keywords,\n bugs: version.bugs,\n license: version.license,\n // time: {\n // modified: time,\n // },\n versions,\n };\n\n return pkg;\n }\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 {*} cacheManifest\n * @param {*} remoteManifest\n */\nexport function mergeVersions(cacheManifest: Manifest, remoteManifest: Manifest): Manifest {\n let _cacheManifest = { ...cacheManifest };\n const { versions, time } = remoteManifest;\n // copy new versions to a cache\n // NOTE: if a certain version was updated, we can't refresh it reliably\n // however, we can refresh the deprecated status\n for (const i in versions) {\n if (typeof _cacheManifest.versions[i] === 'undefined') {\n _cacheManifest.versions[i] = versions[i];\n } else if (versions[i].deprecated) {\n _cacheManifest.versions[i].deprecated = versions[i].deprecated;\n }\n }\n\n for (const i in time) {\n if (typeof _cacheManifest.time[i] === 'undefined') {\n _cacheManifest.time[i] = time[i];\n }\n }\n\n for (const distTag in remoteManifest[DIST_TAGS]) {\n if (_cacheManifest[DIST_TAGS][distTag] !== remoteManifest[DIST_TAGS][distTag]) {\n if (\n !_cacheManifest[DIST_TAGS][distTag] ||\n semver.lte(_cacheManifest[DIST_TAGS][distTag], remoteManifest[DIST_TAGS][distTag])\n ) {\n _cacheManifest[DIST_TAGS][distTag] = remoteManifest[DIST_TAGS][distTag];\n }\n if (\n distTag === 'latest' &&\n _cacheManifest[DIST_TAGS][distTag] === remoteManifest[DIST_TAGS][distTag]\n ) {\n // NOTE: this override the latest publish readme from local cache with\n // the remote one\n _cacheManifest = { ..._cacheManifest, readme: remoteManifest.readme };\n }\n }\n }\n return _cacheManifest;\n}\n\n/**\n * Normalize dist-tags.\n *\n * There is a legacy behaviour where the dist-tags could be an array, in such\n * case, the array is orderded and the highest version becames the\n * latest.\n *\n * The dist-tag tags must be plain strigs, if the latest is empty (for whatever reason) is\n * normalized to be the highest version available.\n *\n * This function cleans up every invalid version on dist-tags, but does not remove\n * invalid versions from the manifest.\n *\n * @param {*} data\n */\nexport function normalizeDistTags(manifest: Manifest): Manifest {\n let sorted;\n // handle missing latest dist-tag\n if (!manifest[DIST_TAGS].latest) {\n // if there is no latest tag, set the highest known version based on semver sort\n sorted = sortVersionsAndFilterInvalid(Object.keys(manifest.versions));\n if (sorted?.length) {\n // get the highest published version\n manifest[DIST_TAGS].latest = sorted.pop();\n }\n }\n\n for (const tag in manifest[DIST_TAGS]) {\n // deprecated (will be removed un future majors)\n // this should not happen, tags should be plain strings, legacy fallback\n if (Array.isArray(manifest[DIST_TAGS][tag])) {\n if (manifest[DIST_TAGS][tag].length) {\n // sort array\n // FIXME: this is clearly wrong, we need to research why this is like this.\n // @ts-ignore\n sorted = sortVersionsAndFilterInvalid(manifest[DIST_TAGS][tag]);\n if (sorted.length) {\n // use highest version based on semver sort\n manifest[DIST_TAGS][tag] = sorted.pop();\n }\n } else {\n delete manifest[DIST_TAGS][tag];\n }\n } else if (typeof manifest[DIST_TAGS][tag] === 'string') {\n if (!semver.parse(manifest[DIST_TAGS][tag], true)) {\n // if the version is invalid, delete the dist-tag entry\n delete manifest[DIST_TAGS][tag];\n }\n }\n }\n\n return manifest;\n}\n\nexport function hasDeprecatedVersions(pkgInfo: Manifest): boolean {\n const { versions } = pkgInfo;\n for (const version in versions) {\n if (Object.prototype.hasOwnProperty.call(versions[version], 'deprecated')) {\n return true;\n }\n }\n return false;\n}\n\nexport function isDeprecatedManifest(manifest: Manifest): boolean {\n return (\n hasDeprecatedVersions(manifest) &&\n (typeof manifest._attachments === 'undefined' ||\n Object.keys(manifest._attachments).length === 0)\n );\n}\n\nexport function mapManifestToSearchPackageBody(\n pkg: Manifest,\n _searchItem: searchUtils.SearchItem\n): searchUtils.SearchPackageBody {\n const latest = pkgUtils.getLatest(pkg);\n const version: Version = pkg.versions[latest];\n // packument maintainers carry `name`, but the npm search API contract uses\n // `username` and the npm CLI crashes on entries without it — emit both\n const maintainers = Array.isArray(version.maintainers)\n ? version.maintainers.map((maintainer: any) =>\n typeof maintainer === 'string'\n ? { username: maintainer, email: '' }\n : {\n ...maintainer,\n username: maintainer?.username ?? maintainer?.name ?? '',\n email: maintainer?.email ?? '',\n }\n )\n : [];\n // npmjs fills `publisher` with the user who published the version; use\n // `_npmUser` when the client provided it and fall back to the first\n // maintainer (verdaccio sets it to the publishing user), otherwise the\n // npm CLI renders \"published by ???\"\n const publisher = version._npmUser?.name\n ? { username: version._npmUser.name, email: version._npmUser.email ?? '' }\n : (maintainers[0] ?? {});\n const links: NonNullable<searchUtils.SearchPackageBody['links']> = {};\n const repository =\n typeof version.repository === 'string' ? version.repository : version.repository?.url;\n const bugs = typeof version.bugs === 'string' ? version.bugs : version.bugs?.url;\n if (version.homepage) {\n links.homepage = version.homepage;\n }\n if (repository) {\n links.repository = repository;\n }\n if (bugs) {\n links.bugs = bugs;\n }\n const result: searchUtils.SearchPackageBody = {\n name: version.name,\n description: version.description,\n version: latest,\n license: version.license,\n keywords: version.keywords,\n date: pkg.time[latest],\n // FIXME: type\n author: version.author as any,\n publisher,\n maintainers,\n };\n\n if (Object.keys(links).length > 0) {\n result.links = links;\n }\n\n return result;\n}\n\nexport function normalizeContributors(contributors: Author[]): Author[] {\n if (isNil(contributors)) {\n return [];\n } else if (contributors && !Array.isArray(contributors)) {\n return [contributors];\n } else if (typeof contributors === 'string') {\n return [\n {\n name: contributors,\n },\n ];\n }\n\n return contributors;\n}\n\n/**\n * Whether the tarball url path ends with the given file name (any query\n * string or fragment is ignored, like the path parsing in\n * `tarballUtils.extractTarballFromUrl`, which creates the `_distfiles`\n * keys — if that parsing ever changes, this must change with it).\n */\nexport function tarballMatchesFilename(tarball: string, filename: string): boolean {\n return tarball.split(/[?#]/)[0].endsWith(`/${filename}`);\n}\n\n/**\n * Build a distfile record from a version's dist metadata when its tarball\n * url matches the given file name.\n */\nexport function distFileFromVersion(\n version: Version | undefined,\n filename: string\n): DistFile | null {\n const dist = version?.dist;\n\n if (dist?.tarball && tarballMatchesFilename(dist.tarball, filename)) {\n return { url: dist.tarball, sha: dist.shasum } as DistFile;\n }\n\n return null;\n}\n\n/**\n * Resolve the distfile record for a tarball filename. Prefers the\n * `_distfiles` bookkeeping, but falls back to the version metadata when the\n * record is missing (storages written by other verdaccio versions cache\n * versions without their distfile records, which made those tarballs\n * permanently unavailable).\n *\n * Note: no extension pre-filter before the scan on purpose — GitHub\n * Packages advertises tarball urls ending in a bare sha-256 digest.\n * @param manifest cached manifest\n * @param filename tarball file name, eg. pkg-1.0.0.tgz\n */\nexport function lookupDistFile(manifest: Manifest, filename: string): DistFile | null {\n const distFile = manifest?._distfiles?.[filename];\n if (isNil(distFile) === false) {\n return distFile;\n }\n\n const versions = manifest?.versions ?? {};\n\n // tarballs are conventionally named <basename>-<version>.tgz, so the\n // version can usually be derived from the filename without scanning\n // manifests that carry thousands of versions\n const packageBasename = manifest?.name?.replace(/^.*\\//, '');\n if (packageBasename && filename.startsWith(`${packageBasename}-`) && filename.endsWith('.tgz')) {\n const versionId = filename.slice(packageBasename.length + 1, -'.tgz'.length);\n const distFromVersion = distFileFromVersion(versions[versionId], filename);\n\n if (distFromVersion) {\n debug('distfile record missing for %o, using version %o dist', filename, versionId);\n return distFromVersion;\n }\n }\n\n // unconventional tarball names: fall back to a scan\n for (const versionId in versions) {\n const distFromVersion = distFileFromVersion(versions[versionId], filename);\n\n if (distFromVersion) {\n debug('distfile record missing for %o, using version %o dist', filename, versionId);\n return distFromVersion;\n }\n }\n\n debug('no distfile record or version dist found for %o', filename);\n return null;\n}\n\n/**\n * Whether an uplink's configured url serves the given tarball url: same\n * protocol, same host and the uplink path is a prefix of the tarball path.\n * WHATWG URL normalizes default ports (https://h:443 === https://h).\n */\nexport function uplinkServesUrl(uplinkUrl: URL, tarballUrl: string): boolean {\n try {\n const parsed = new URL(tarballUrl);\n // Compare on a path segment boundary: an uplink at /registry must not\n // match tarballs under /registry2/... (wrong-uplink selection would send\n // the uplink's credentials to a sibling path).\n const basePath = uplinkUrl.pathname.endsWith('/')\n ? uplinkUrl.pathname\n : `${uplinkUrl.pathname}/`;\n return (\n parsed.protocol === uplinkUrl.protocol &&\n parsed.host === uplinkUrl.host &&\n parsed.pathname.startsWith(basePath)\n );\n } catch {\n return false;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"storage-utils.js","names":[],"sources":["../../src/lib/storage-utils.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { isNil, trim } from 'lodash-es';\nimport semver from 'semver';\n\nimport type { searchUtils } from '@verdaccio/core';\nimport {\n ANONYMOUS_USER,\n API_ERROR,\n DIST_TAGS,\n HTTP_STATUS,\n MAINTAINERS,\n USERS,\n cryptoUtils,\n errorUtils,\n pkgUtils,\n validationUtils,\n} from '@verdaccio/core';\nimport type {\n Author,\n DistFile,\n GenericBody,\n Manifest,\n Person,\n ReadmeOptions,\n Version,\n} from '@verdaccio/types';\n\nimport { sortVersionsAndFilterInvalid } from './versions-utils';\n\nconst debug = buildDebug('verdaccio:storage:utils');\n\nexport const STORAGE = {\n PACKAGE_FILE_NAME: 'package.json',\n FILE_EXIST_ERROR: 'EEXISTS',\n NO_SUCH_FILE_ERROR: 'ENOENT',\n DEFAULT_REVISION: '0-0000000000000000',\n};\n\n/**\n * Create a new package in the storage, return a boilerplate package\n * @param name package name\n * @returns {Manifest}\n */\nexport function generatePackageTemplate(name: string): Manifest {\n return {\n // standard things\n name,\n versions: {},\n time: {},\n [USERS]: {},\n [DIST_TAGS]: {},\n [MAINTAINERS]: [],\n _uplinks: {},\n _distfiles: {},\n _attachments: {},\n _rev: '',\n };\n}\n\n/**\n * Normalize package properties, tags, revision id.\n * @param {Object} pkg package reference.\n */\nexport function normalizePackage(pkg: Manifest): Manifest {\n const pkgProperties = ['versions', 'dist-tags', '_distfiles', '_attachments', '_uplinks', 'time'];\n\n pkgProperties.forEach((key): void => {\n const pkgProp = pkg[key];\n\n if (isNil(pkgProp) || validationUtils.isObject(pkgProp) === false) {\n pkg[key] = {};\n }\n });\n\n if (typeof pkg?._rev !== 'string') {\n pkg._rev = STORAGE.DEFAULT_REVISION;\n }\n\n if (typeof pkg?._id !== 'string') {\n pkg._id = pkg.name;\n }\n\n // normalize dist-tags\n return normalizeDistTags(pkg);\n}\n\nexport function generateRevision(rev: string): string {\n const _rev = rev.split('-');\n\n return (+_rev[0] || 0) + 1 + '-' + cryptoUtils.generateRandomHexString();\n}\n\nexport function getLatestReadme(pkg: Manifest): string {\n const versions = pkg['versions'] || {};\n const distTags = pkg[DIST_TAGS] || {};\n // FIXME: here is a bit tricky add the types\n const latestVersion: Version | any = distTags['latest'] ? versions[distTags['latest']] || {} : {};\n let readme = trim(pkg.readme || latestVersion.readme || '');\n if (readme) {\n return readme;\n }\n\n // In case of empty readme - trying to get ANY readme in the following order:\n // 'next','beta','alpha','test','dev','canary'\n const readmeDistTagsPriority = ['next', 'beta', 'alpha', 'test', 'dev', 'canary'];\n readmeDistTagsPriority.forEach(function (tag): string | void {\n if (readme) {\n return readme;\n }\n const version: Version | any = distTags[tag] ? versions[distTags[tag]] || {} : {};\n readme = trim(version.readme || readme);\n });\n return readme;\n}\n\n/**\n * Cleanup readme from package version\n *\n * By default, we don't keep readmes for package versions, only one readme per package.\n * Using publish.keep_readmes you can override this behavior and keep all readmes\n * or only readmes for tagged versions.\n */\nexport function cleanUpReadme(\n version: Version,\n distTags?: GenericBody,\n keepReadmes?: ReadmeOptions\n): Version {\n if (keepReadmes === 'all') {\n return version;\n } else if (keepReadmes === 'tagged') {\n if (distTags && Object.values(distTags).includes(version.version)) {\n return version;\n }\n }\n\n if (isNil(version) === false) {\n version.readme = '';\n }\n\n return version;\n}\n\nexport const WHITELIST = [\n '_rev',\n 'name',\n 'versions',\n 'dist-tags',\n 'readme',\n 'time',\n '_id',\n 'users',\n 'maintainers',\n];\n\nexport function cleanUpLinksRef(result: Manifest, keepUpLinkData?: boolean): Manifest {\n const propertyToKeep = [...WHITELIST];\n if (keepUpLinkData === true) {\n propertyToKeep.push('_uplinks');\n }\n\n for (const i in result) {\n if (propertyToKeep.indexOf(i) === -1) {\n // Remove sections like '_uplinks' from response\n delete result[i];\n }\n }\n\n return result;\n}\n\n// TODO: move to abstract storage\n// @deprecated use abstract.storage.ts:checkPackageRemote\nexport function checkPackageRemote(\n name: string,\n isAllowPublishOffline: boolean,\n syncMetadata: Function\n): Promise<any> {\n return new Promise<void>((resolve, reject): void => {\n syncMetadata(name, null, {}, (err, packageJsonLocal, upLinksErrors): void => {\n // something weird\n if (err && err.status !== HTTP_STATUS.NOT_FOUND) {\n return reject(err);\n }\n\n // checking package exist already\n if (isNil(packageJsonLocal) === false) {\n return reject(errorUtils.getConflict(API_ERROR.PACKAGE_EXIST));\n }\n\n for (let errorItem = 0; errorItem < upLinksErrors.length; errorItem++) {\n // checking error\n // if uplink fails with a status other than 404, we report failure\n if (isNil(upLinksErrors[errorItem][0]) === false) {\n if (upLinksErrors[errorItem][0].status !== HTTP_STATUS.NOT_FOUND) {\n if (isAllowPublishOffline) {\n return resolve();\n }\n\n return reject(errorUtils.getServiceUnavailable(API_ERROR.UPLINK_OFFLINE_PUBLISH));\n }\n }\n }\n\n return resolve();\n });\n });\n}\n\n// @deprecated use export function mergeUplinkTimeIntoLocalNext\nexport function mergeUplinkTimeIntoLocal(localMetadata: Manifest, remoteMetadata: Manifest): any {\n if ('time' in remoteMetadata) {\n return Object.assign({}, localMetadata.time, remoteMetadata.time);\n }\n\n return localMetadata.time;\n}\n\nexport function mergeUplinkTimeIntoLocalNext(\n cacheManifest: Manifest,\n remoteManifest: Manifest\n): Manifest {\n if ('time' in remoteManifest) {\n // remote override cache time conflicts\n return { ...cacheManifest, time: { ...cacheManifest.time, ...remoteManifest.time } };\n }\n\n return cacheManifest;\n}\n\nexport function updateUpLinkMetadata(uplinkName: string, manifest: Manifest, etag: string) {\n const _uplinks = {\n ...manifest._uplinks,\n [uplinkName]: {\n etag,\n fetched: Date.now(),\n },\n };\n return {\n ...manifest,\n _uplinks,\n };\n}\n\nexport function prepareSearchPackage(data: Manifest): any {\n const latest = pkgUtils.getLatest(data);\n\n if (latest && data.versions[latest]) {\n const version: Version = data.versions[latest];\n const versions: any = { [latest]: 'latest' };\n const pkg: any = {\n name: version.name,\n description: version.description,\n [DIST_TAGS]: { latest },\n maintainers: version.maintainers || [version.author].filter(Boolean),\n author: version.author,\n repository: version.repository,\n readmeFilename: version.readmeFilename || '',\n homepage: version.homepage,\n keywords: version.keywords,\n bugs: version.bugs,\n license: version.license,\n // time: {\n // modified: time,\n // },\n versions,\n };\n\n return pkg;\n }\n}\n\n/** Maintainer names copied from an uplink. Never a local account. */\nexport const UPSTREAM_MAINTAINER_PREFIX = '$uplink:';\n\nexport function scopeUpstreamMaintainers(maintainers: Person[], uplinkName: string): Person[] {\n const origin = uplinkName.length > 0 ? uplinkName : 'remote';\n return maintainers.map((maintainer) => {\n if (typeof maintainer === 'string') {\n return scopeUpstreamMaintainerName(origin, maintainer);\n }\n const name = typeof maintainer?.name === 'string' ? maintainer.name : '';\n return {\n ...maintainer,\n name: scopeUpstreamMaintainerName(origin, name),\n };\n });\n}\n\nfunction scopeUpstreamMaintainerName(uplinkName: string, name: string): string {\n if (name.startsWith(UPSTREAM_MAINTAINER_PREFIX)) {\n return name;\n }\n return `${UPSTREAM_MAINTAINER_PREFIX}${uplinkName}:${name}`;\n}\n\nexport function maintainerAllowsLocalUser(\n maintainer: Person,\n username: string | undefined\n): boolean {\n const name = typeof maintainer === 'string' ? maintainer : maintainer?.name;\n // reserved uplink identities must not authorize the local user who registered that string\n if (typeof name === 'string' && name.startsWith(UPSTREAM_MAINTAINER_PREFIX)) {\n return false;\n }\n return name === username || name === ANONYMOUS_USER;\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 {*} cacheManifest\n * @param {*} remoteManifest\n */\nexport function mergeVersions(cacheManifest: Manifest, remoteManifest: Manifest): Manifest {\n let _cacheManifest = { ...cacheManifest };\n const { versions, time } = remoteManifest;\n // copy new versions to a cache\n // NOTE: if a certain version was updated, we can't refresh it reliably\n // however, we can refresh the deprecated status\n for (const i in versions) {\n if (typeof _cacheManifest.versions[i] === 'undefined') {\n _cacheManifest.versions[i] = versions[i];\n } else if (versions[i].deprecated) {\n _cacheManifest.versions[i].deprecated = versions[i].deprecated;\n }\n }\n\n for (const i in time) {\n if (typeof _cacheManifest.time[i] === 'undefined') {\n _cacheManifest.time[i] = time[i];\n }\n }\n\n for (const distTag in remoteManifest[DIST_TAGS]) {\n if (_cacheManifest[DIST_TAGS][distTag] !== remoteManifest[DIST_TAGS][distTag]) {\n if (\n !_cacheManifest[DIST_TAGS][distTag] ||\n semver.lte(_cacheManifest[DIST_TAGS][distTag], remoteManifest[DIST_TAGS][distTag])\n ) {\n _cacheManifest[DIST_TAGS][distTag] = remoteManifest[DIST_TAGS][distTag];\n }\n if (\n distTag === 'latest' &&\n _cacheManifest[DIST_TAGS][distTag] === remoteManifest[DIST_TAGS][distTag]\n ) {\n // NOTE: this override the latest publish readme from local cache with\n // the remote one\n _cacheManifest = { ..._cacheManifest, readme: remoteManifest.readme };\n }\n }\n }\n return _cacheManifest;\n}\n\n/**\n * Normalize dist-tags.\n *\n * There is a legacy behaviour where the dist-tags could be an array, in such\n * case, the array is orderded and the highest version becames the\n * latest.\n *\n * The dist-tag tags must be plain strigs, if the latest is empty (for whatever reason) is\n * normalized to be the highest version available.\n *\n * This function cleans up every invalid version on dist-tags, but does not remove\n * invalid versions from the manifest.\n *\n * @param {*} data\n */\nexport function normalizeDistTags(manifest: Manifest): Manifest {\n let sorted;\n // handle missing latest dist-tag\n if (!manifest[DIST_TAGS].latest) {\n // if there is no latest tag, set the highest known version based on semver sort\n sorted = sortVersionsAndFilterInvalid(Object.keys(manifest.versions));\n if (sorted?.length) {\n // get the highest published version\n manifest[DIST_TAGS].latest = sorted.pop();\n }\n }\n\n for (const tag in manifest[DIST_TAGS]) {\n // deprecated (will be removed un future majors)\n // this should not happen, tags should be plain strings, legacy fallback\n if (Array.isArray(manifest[DIST_TAGS][tag])) {\n if (manifest[DIST_TAGS][tag].length) {\n // sort array\n // FIXME: this is clearly wrong, we need to research why this is like this.\n // @ts-ignore\n sorted = sortVersionsAndFilterInvalid(manifest[DIST_TAGS][tag]);\n if (sorted.length) {\n // use highest version based on semver sort\n manifest[DIST_TAGS][tag] = sorted.pop();\n }\n } else {\n delete manifest[DIST_TAGS][tag];\n }\n } else if (typeof manifest[DIST_TAGS][tag] === 'string') {\n if (!semver.parse(manifest[DIST_TAGS][tag], true)) {\n // if the version is invalid, delete the dist-tag entry\n delete manifest[DIST_TAGS][tag];\n }\n }\n }\n\n return manifest;\n}\n\nexport function hasDeprecatedVersions(pkgInfo: Manifest): boolean {\n const { versions } = pkgInfo;\n for (const version in versions) {\n if (Object.prototype.hasOwnProperty.call(versions[version], 'deprecated')) {\n return true;\n }\n }\n return false;\n}\n\nexport function isDeprecatedManifest(manifest: Manifest): boolean {\n return (\n hasDeprecatedVersions(manifest) &&\n (typeof manifest._attachments === 'undefined' ||\n Object.keys(manifest._attachments).length === 0)\n );\n}\n\nexport function mapManifestToSearchPackageBody(\n pkg: Manifest,\n _searchItem: searchUtils.SearchItem\n): searchUtils.SearchPackageBody {\n const latest = pkgUtils.getLatest(pkg);\n const version: Version = pkg.versions[latest];\n // packument maintainers carry `name`, but the npm search API contract uses\n // `username` and the npm CLI crashes on entries without it — emit both\n const maintainers = Array.isArray(version.maintainers)\n ? version.maintainers.map((maintainer: any) =>\n typeof maintainer === 'string'\n ? { username: maintainer, email: '' }\n : {\n ...maintainer,\n username: maintainer?.username ?? maintainer?.name ?? '',\n email: maintainer?.email ?? '',\n }\n )\n : [];\n // npmjs fills `publisher` with the user who published the version; use\n // `_npmUser` when the client provided it and fall back to the first\n // maintainer (verdaccio sets it to the publishing user), otherwise the\n // npm CLI renders \"published by ???\"\n const publisher = version._npmUser?.name\n ? { username: version._npmUser.name, email: version._npmUser.email ?? '' }\n : (maintainers[0] ?? {});\n const links: NonNullable<searchUtils.SearchPackageBody['links']> = {};\n const repository =\n typeof version.repository === 'string' ? version.repository : version.repository?.url;\n const bugs = typeof version.bugs === 'string' ? version.bugs : version.bugs?.url;\n if (version.homepage) {\n links.homepage = version.homepage;\n }\n if (repository) {\n links.repository = repository;\n }\n if (bugs) {\n links.bugs = bugs;\n }\n const result: searchUtils.SearchPackageBody = {\n name: version.name,\n description: version.description,\n version: latest,\n license: version.license,\n keywords: version.keywords,\n date: pkg.time[latest],\n // FIXME: type\n author: version.author as any,\n publisher,\n maintainers,\n };\n\n if (Object.keys(links).length > 0) {\n result.links = links;\n }\n\n return result;\n}\n\nexport function normalizeContributors(contributors: Author[]): Author[] {\n if (isNil(contributors)) {\n return [];\n } else if (contributors && !Array.isArray(contributors)) {\n return [contributors];\n } else if (typeof contributors === 'string') {\n return [\n {\n name: contributors,\n },\n ];\n }\n\n return contributors;\n}\n\n/**\n * Whether the tarball url path ends with the given file name (any query\n * string or fragment is ignored, like the path parsing in\n * `tarballUtils.extractTarballFromUrl`, which creates the `_distfiles`\n * keys — if that parsing ever changes, this must change with it).\n */\nexport function tarballMatchesFilename(tarball: string, filename: string): boolean {\n return tarball.split(/[?#]/)[0].endsWith(`/${filename}`);\n}\n\n/**\n * Build a distfile record from a version's dist metadata when its tarball\n * url matches the given file name.\n */\nexport function distFileFromVersion(\n version: Version | undefined,\n filename: string\n): DistFile | null {\n const dist = version?.dist;\n\n if (dist?.tarball && tarballMatchesFilename(dist.tarball, filename)) {\n return { url: dist.tarball, sha: dist.shasum } as DistFile;\n }\n\n return null;\n}\n\n/**\n * Resolve the distfile record for a tarball filename. Prefers the\n * `_distfiles` bookkeeping, but falls back to the version metadata when the\n * record is missing (storages written by other verdaccio versions cache\n * versions without their distfile records, which made those tarballs\n * permanently unavailable).\n *\n * Note: no extension pre-filter before the scan on purpose — GitHub\n * Packages advertises tarball urls ending in a bare sha-256 digest.\n * @param manifest cached manifest\n * @param filename tarball file name, eg. pkg-1.0.0.tgz\n */\nexport function lookupDistFile(manifest: Manifest, filename: string): DistFile | null {\n const distFile = manifest?._distfiles?.[filename];\n if (isNil(distFile) === false) {\n return distFile;\n }\n\n const versions = manifest?.versions ?? {};\n\n // tarballs are conventionally named <basename>-<version>.tgz, so the\n // version can usually be derived from the filename without scanning\n // manifests that carry thousands of versions\n const packageBasename = manifest?.name?.replace(/^.*\\//, '');\n if (packageBasename && filename.startsWith(`${packageBasename}-`) && filename.endsWith('.tgz')) {\n const versionId = filename.slice(packageBasename.length + 1, -'.tgz'.length);\n const distFromVersion = distFileFromVersion(versions[versionId], filename);\n\n if (distFromVersion) {\n debug('distfile record missing for %o, using version %o dist', filename, versionId);\n return distFromVersion;\n }\n }\n\n // unconventional tarball names: fall back to a scan\n for (const versionId in versions) {\n const distFromVersion = distFileFromVersion(versions[versionId], filename);\n\n if (distFromVersion) {\n debug('distfile record missing for %o, using version %o dist', filename, versionId);\n return distFromVersion;\n }\n }\n\n debug('no distfile record or version dist found for %o', filename);\n return null;\n}\n\n/**\n * Whether an uplink's configured url serves the given tarball url: same\n * protocol, same host and the uplink path is a prefix of the tarball path.\n * WHATWG URL normalizes default ports (https://h:443 === https://h).\n */\nexport function uplinkServesUrl(uplinkUrl: URL, tarballUrl: string): boolean {\n try {\n const parsed = new URL(tarballUrl);\n // Compare on a path segment boundary: an uplink at /registry must not\n // match tarballs under /registry2/... (wrong-uplink selection would send\n // the uplink's credentials to a sibling path).\n const basePath = uplinkUrl.pathname.endsWith('/')\n ? uplinkUrl.pathname\n : `${uplinkUrl.pathname}/`;\n return (\n parsed.protocol === uplinkUrl.protocol &&\n parsed.host === uplinkUrl.host &&\n parsed.pathname.startsWith(basePath)\n );\n } catch {\n return false;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { sortVersionsAndFilterInvalid } from "./versions-utils.mjs";
|
|
2
2
|
import buildDebug from "debug";
|
|
3
3
|
import { isNil, trim } from "lodash-es";
|
|
4
|
-
import { API_ERROR, DIST_TAGS, HTTP_STATUS, MAINTAINERS, USERS, cryptoUtils, errorUtils, pkgUtils, validationUtils } from "@verdaccio/core";
|
|
4
|
+
import { ANONYMOUS_USER, API_ERROR, DIST_TAGS, HTTP_STATUS, MAINTAINERS, USERS, cryptoUtils, errorUtils, pkgUtils, validationUtils } from "@verdaccio/core";
|
|
5
5
|
import semver from "semver";
|
|
6
6
|
//#region src/lib/storage-utils.ts
|
|
7
7
|
var debug = buildDebug("verdaccio:storage:utils");
|
|
@@ -168,6 +168,28 @@ function prepareSearchPackage(data) {
|
|
|
168
168
|
};
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
|
+
/** Maintainer names copied from an uplink. Never a local account. */
|
|
172
|
+
var UPSTREAM_MAINTAINER_PREFIX = "$uplink:";
|
|
173
|
+
function scopeUpstreamMaintainers(maintainers, uplinkName) {
|
|
174
|
+
const origin = uplinkName.length > 0 ? uplinkName : "remote";
|
|
175
|
+
return maintainers.map((maintainer) => {
|
|
176
|
+
if (typeof maintainer === "string") return scopeUpstreamMaintainerName(origin, maintainer);
|
|
177
|
+
const name = typeof maintainer?.name === "string" ? maintainer.name : "";
|
|
178
|
+
return {
|
|
179
|
+
...maintainer,
|
|
180
|
+
name: scopeUpstreamMaintainerName(origin, name)
|
|
181
|
+
};
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
function scopeUpstreamMaintainerName(uplinkName, name) {
|
|
185
|
+
if (name.startsWith("$uplink:")) return name;
|
|
186
|
+
return `${UPSTREAM_MAINTAINER_PREFIX}${uplinkName}:${name}`;
|
|
187
|
+
}
|
|
188
|
+
function maintainerAllowsLocalUser(maintainer, username) {
|
|
189
|
+
const name = typeof maintainer === "string" ? maintainer : maintainer?.name;
|
|
190
|
+
if (typeof name === "string" && name.startsWith("$uplink:")) return false;
|
|
191
|
+
return name === username || name === ANONYMOUS_USER;
|
|
192
|
+
}
|
|
171
193
|
/**
|
|
172
194
|
* Function gets a local info and an info from uplinks and tries to merge it
|
|
173
195
|
exported for unit tests only.
|
|
@@ -340,6 +362,6 @@ function uplinkServesUrl(uplinkUrl, tarballUrl) {
|
|
|
340
362
|
}
|
|
341
363
|
}
|
|
342
364
|
//#endregion
|
|
343
|
-
export { STORAGE, WHITELIST, checkPackageRemote, cleanUpLinksRef, cleanUpReadme, distFileFromVersion, generatePackageTemplate, generateRevision, getLatestReadme, hasDeprecatedVersions, isDeprecatedManifest, lookupDistFile, mapManifestToSearchPackageBody, mergeUplinkTimeIntoLocal, mergeUplinkTimeIntoLocalNext, mergeVersions, normalizeContributors, normalizeDistTags, normalizePackage, prepareSearchPackage, tarballMatchesFilename, updateUpLinkMetadata, uplinkServesUrl };
|
|
365
|
+
export { STORAGE, UPSTREAM_MAINTAINER_PREFIX, WHITELIST, checkPackageRemote, cleanUpLinksRef, cleanUpReadme, distFileFromVersion, generatePackageTemplate, generateRevision, getLatestReadme, hasDeprecatedVersions, isDeprecatedManifest, lookupDistFile, maintainerAllowsLocalUser, mapManifestToSearchPackageBody, mergeUplinkTimeIntoLocal, mergeUplinkTimeIntoLocalNext, mergeVersions, normalizeContributors, normalizeDistTags, normalizePackage, prepareSearchPackage, scopeUpstreamMaintainers, tarballMatchesFilename, updateUpLinkMetadata, uplinkServesUrl };
|
|
344
366
|
|
|
345
367
|
//# sourceMappingURL=storage-utils.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage-utils.mjs","names":[],"sources":["../../src/lib/storage-utils.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { isNil, trim } from 'lodash-es';\nimport semver from 'semver';\n\nimport type { searchUtils } from '@verdaccio/core';\nimport {\n API_ERROR,\n DIST_TAGS,\n HTTP_STATUS,\n MAINTAINERS,\n USERS,\n cryptoUtils,\n errorUtils,\n pkgUtils,\n validationUtils,\n} from '@verdaccio/core';\nimport type {\n Author,\n DistFile,\n GenericBody,\n Manifest,\n ReadmeOptions,\n Version,\n} from '@verdaccio/types';\n\nimport { sortVersionsAndFilterInvalid } from './versions-utils';\n\nconst debug = buildDebug('verdaccio:storage:utils');\n\nexport const STORAGE = {\n PACKAGE_FILE_NAME: 'package.json',\n FILE_EXIST_ERROR: 'EEXISTS',\n NO_SUCH_FILE_ERROR: 'ENOENT',\n DEFAULT_REVISION: '0-0000000000000000',\n};\n\n/**\n * Create a new package in the storage, return a boilerplate package\n * @param name package name\n * @returns {Manifest}\n */\nexport function generatePackageTemplate(name: string): Manifest {\n return {\n // standard things\n name,\n versions: {},\n time: {},\n [USERS]: {},\n [DIST_TAGS]: {},\n [MAINTAINERS]: [],\n _uplinks: {},\n _distfiles: {},\n _attachments: {},\n _rev: '',\n };\n}\n\n/**\n * Normalize package properties, tags, revision id.\n * @param {Object} pkg package reference.\n */\nexport function normalizePackage(pkg: Manifest): Manifest {\n const pkgProperties = ['versions', 'dist-tags', '_distfiles', '_attachments', '_uplinks', 'time'];\n\n pkgProperties.forEach((key): void => {\n const pkgProp = pkg[key];\n\n if (isNil(pkgProp) || validationUtils.isObject(pkgProp) === false) {\n pkg[key] = {};\n }\n });\n\n if (typeof pkg?._rev !== 'string') {\n pkg._rev = STORAGE.DEFAULT_REVISION;\n }\n\n if (typeof pkg?._id !== 'string') {\n pkg._id = pkg.name;\n }\n\n // normalize dist-tags\n return normalizeDistTags(pkg);\n}\n\nexport function generateRevision(rev: string): string {\n const _rev = rev.split('-');\n\n return (+_rev[0] || 0) + 1 + '-' + cryptoUtils.generateRandomHexString();\n}\n\nexport function getLatestReadme(pkg: Manifest): string {\n const versions = pkg['versions'] || {};\n const distTags = pkg[DIST_TAGS] || {};\n // FIXME: here is a bit tricky add the types\n const latestVersion: Version | any = distTags['latest'] ? versions[distTags['latest']] || {} : {};\n let readme = trim(pkg.readme || latestVersion.readme || '');\n if (readme) {\n return readme;\n }\n\n // In case of empty readme - trying to get ANY readme in the following order:\n // 'next','beta','alpha','test','dev','canary'\n const readmeDistTagsPriority = ['next', 'beta', 'alpha', 'test', 'dev', 'canary'];\n readmeDistTagsPriority.forEach(function (tag): string | void {\n if (readme) {\n return readme;\n }\n const version: Version | any = distTags[tag] ? versions[distTags[tag]] || {} : {};\n readme = trim(version.readme || readme);\n });\n return readme;\n}\n\n/**\n * Cleanup readme from package version\n *\n * By default, we don't keep readmes for package versions, only one readme per package.\n * Using publish.keep_readmes you can override this behavior and keep all readmes\n * or only readmes for tagged versions.\n */\nexport function cleanUpReadme(\n version: Version,\n distTags?: GenericBody,\n keepReadmes?: ReadmeOptions\n): Version {\n if (keepReadmes === 'all') {\n return version;\n } else if (keepReadmes === 'tagged') {\n if (distTags && Object.values(distTags).includes(version.version)) {\n return version;\n }\n }\n\n if (isNil(version) === false) {\n version.readme = '';\n }\n\n return version;\n}\n\nexport const WHITELIST = [\n '_rev',\n 'name',\n 'versions',\n 'dist-tags',\n 'readme',\n 'time',\n '_id',\n 'users',\n 'maintainers',\n];\n\nexport function cleanUpLinksRef(result: Manifest, keepUpLinkData?: boolean): Manifest {\n const propertyToKeep = [...WHITELIST];\n if (keepUpLinkData === true) {\n propertyToKeep.push('_uplinks');\n }\n\n for (const i in result) {\n if (propertyToKeep.indexOf(i) === -1) {\n // Remove sections like '_uplinks' from response\n delete result[i];\n }\n }\n\n return result;\n}\n\n// TODO: move to abstract storage\n// @deprecated use abstract.storage.ts:checkPackageRemote\nexport function checkPackageRemote(\n name: string,\n isAllowPublishOffline: boolean,\n syncMetadata: Function\n): Promise<any> {\n return new Promise<void>((resolve, reject): void => {\n syncMetadata(name, null, {}, (err, packageJsonLocal, upLinksErrors): void => {\n // something weird\n if (err && err.status !== HTTP_STATUS.NOT_FOUND) {\n return reject(err);\n }\n\n // checking package exist already\n if (isNil(packageJsonLocal) === false) {\n return reject(errorUtils.getConflict(API_ERROR.PACKAGE_EXIST));\n }\n\n for (let errorItem = 0; errorItem < upLinksErrors.length; errorItem++) {\n // checking error\n // if uplink fails with a status other than 404, we report failure\n if (isNil(upLinksErrors[errorItem][0]) === false) {\n if (upLinksErrors[errorItem][0].status !== HTTP_STATUS.NOT_FOUND) {\n if (isAllowPublishOffline) {\n return resolve();\n }\n\n return reject(errorUtils.getServiceUnavailable(API_ERROR.UPLINK_OFFLINE_PUBLISH));\n }\n }\n }\n\n return resolve();\n });\n });\n}\n\n// @deprecated use export function mergeUplinkTimeIntoLocalNext\nexport function mergeUplinkTimeIntoLocal(localMetadata: Manifest, remoteMetadata: Manifest): any {\n if ('time' in remoteMetadata) {\n return Object.assign({}, localMetadata.time, remoteMetadata.time);\n }\n\n return localMetadata.time;\n}\n\nexport function mergeUplinkTimeIntoLocalNext(\n cacheManifest: Manifest,\n remoteManifest: Manifest\n): Manifest {\n if ('time' in remoteManifest) {\n // remote override cache time conflicts\n return { ...cacheManifest, time: { ...cacheManifest.time, ...remoteManifest.time } };\n }\n\n return cacheManifest;\n}\n\nexport function updateUpLinkMetadata(uplinkName: string, manifest: Manifest, etag: string) {\n const _uplinks = {\n ...manifest._uplinks,\n [uplinkName]: {\n etag,\n fetched: Date.now(),\n },\n };\n return {\n ...manifest,\n _uplinks,\n };\n}\n\nexport function prepareSearchPackage(data: Manifest): any {\n const latest = pkgUtils.getLatest(data);\n\n if (latest && data.versions[latest]) {\n const version: Version = data.versions[latest];\n const versions: any = { [latest]: 'latest' };\n const pkg: any = {\n name: version.name,\n description: version.description,\n [DIST_TAGS]: { latest },\n maintainers: version.maintainers || [version.author].filter(Boolean),\n author: version.author,\n repository: version.repository,\n readmeFilename: version.readmeFilename || '',\n homepage: version.homepage,\n keywords: version.keywords,\n bugs: version.bugs,\n license: version.license,\n // time: {\n // modified: time,\n // },\n versions,\n };\n\n return pkg;\n }\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 {*} cacheManifest\n * @param {*} remoteManifest\n */\nexport function mergeVersions(cacheManifest: Manifest, remoteManifest: Manifest): Manifest {\n let _cacheManifest = { ...cacheManifest };\n const { versions, time } = remoteManifest;\n // copy new versions to a cache\n // NOTE: if a certain version was updated, we can't refresh it reliably\n // however, we can refresh the deprecated status\n for (const i in versions) {\n if (typeof _cacheManifest.versions[i] === 'undefined') {\n _cacheManifest.versions[i] = versions[i];\n } else if (versions[i].deprecated) {\n _cacheManifest.versions[i].deprecated = versions[i].deprecated;\n }\n }\n\n for (const i in time) {\n if (typeof _cacheManifest.time[i] === 'undefined') {\n _cacheManifest.time[i] = time[i];\n }\n }\n\n for (const distTag in remoteManifest[DIST_TAGS]) {\n if (_cacheManifest[DIST_TAGS][distTag] !== remoteManifest[DIST_TAGS][distTag]) {\n if (\n !_cacheManifest[DIST_TAGS][distTag] ||\n semver.lte(_cacheManifest[DIST_TAGS][distTag], remoteManifest[DIST_TAGS][distTag])\n ) {\n _cacheManifest[DIST_TAGS][distTag] = remoteManifest[DIST_TAGS][distTag];\n }\n if (\n distTag === 'latest' &&\n _cacheManifest[DIST_TAGS][distTag] === remoteManifest[DIST_TAGS][distTag]\n ) {\n // NOTE: this override the latest publish readme from local cache with\n // the remote one\n _cacheManifest = { ..._cacheManifest, readme: remoteManifest.readme };\n }\n }\n }\n return _cacheManifest;\n}\n\n/**\n * Normalize dist-tags.\n *\n * There is a legacy behaviour where the dist-tags could be an array, in such\n * case, the array is orderded and the highest version becames the\n * latest.\n *\n * The dist-tag tags must be plain strigs, if the latest is empty (for whatever reason) is\n * normalized to be the highest version available.\n *\n * This function cleans up every invalid version on dist-tags, but does not remove\n * invalid versions from the manifest.\n *\n * @param {*} data\n */\nexport function normalizeDistTags(manifest: Manifest): Manifest {\n let sorted;\n // handle missing latest dist-tag\n if (!manifest[DIST_TAGS].latest) {\n // if there is no latest tag, set the highest known version based on semver sort\n sorted = sortVersionsAndFilterInvalid(Object.keys(manifest.versions));\n if (sorted?.length) {\n // get the highest published version\n manifest[DIST_TAGS].latest = sorted.pop();\n }\n }\n\n for (const tag in manifest[DIST_TAGS]) {\n // deprecated (will be removed un future majors)\n // this should not happen, tags should be plain strings, legacy fallback\n if (Array.isArray(manifest[DIST_TAGS][tag])) {\n if (manifest[DIST_TAGS][tag].length) {\n // sort array\n // FIXME: this is clearly wrong, we need to research why this is like this.\n // @ts-ignore\n sorted = sortVersionsAndFilterInvalid(manifest[DIST_TAGS][tag]);\n if (sorted.length) {\n // use highest version based on semver sort\n manifest[DIST_TAGS][tag] = sorted.pop();\n }\n } else {\n delete manifest[DIST_TAGS][tag];\n }\n } else if (typeof manifest[DIST_TAGS][tag] === 'string') {\n if (!semver.parse(manifest[DIST_TAGS][tag], true)) {\n // if the version is invalid, delete the dist-tag entry\n delete manifest[DIST_TAGS][tag];\n }\n }\n }\n\n return manifest;\n}\n\nexport function hasDeprecatedVersions(pkgInfo: Manifest): boolean {\n const { versions } = pkgInfo;\n for (const version in versions) {\n if (Object.prototype.hasOwnProperty.call(versions[version], 'deprecated')) {\n return true;\n }\n }\n return false;\n}\n\nexport function isDeprecatedManifest(manifest: Manifest): boolean {\n return (\n hasDeprecatedVersions(manifest) &&\n (typeof manifest._attachments === 'undefined' ||\n Object.keys(manifest._attachments).length === 0)\n );\n}\n\nexport function mapManifestToSearchPackageBody(\n pkg: Manifest,\n _searchItem: searchUtils.SearchItem\n): searchUtils.SearchPackageBody {\n const latest = pkgUtils.getLatest(pkg);\n const version: Version = pkg.versions[latest];\n // packument maintainers carry `name`, but the npm search API contract uses\n // `username` and the npm CLI crashes on entries without it — emit both\n const maintainers = Array.isArray(version.maintainers)\n ? version.maintainers.map((maintainer: any) =>\n typeof maintainer === 'string'\n ? { username: maintainer, email: '' }\n : {\n ...maintainer,\n username: maintainer?.username ?? maintainer?.name ?? '',\n email: maintainer?.email ?? '',\n }\n )\n : [];\n // npmjs fills `publisher` with the user who published the version; use\n // `_npmUser` when the client provided it and fall back to the first\n // maintainer (verdaccio sets it to the publishing user), otherwise the\n // npm CLI renders \"published by ???\"\n const publisher = version._npmUser?.name\n ? { username: version._npmUser.name, email: version._npmUser.email ?? '' }\n : (maintainers[0] ?? {});\n const links: NonNullable<searchUtils.SearchPackageBody['links']> = {};\n const repository =\n typeof version.repository === 'string' ? version.repository : version.repository?.url;\n const bugs = typeof version.bugs === 'string' ? version.bugs : version.bugs?.url;\n if (version.homepage) {\n links.homepage = version.homepage;\n }\n if (repository) {\n links.repository = repository;\n }\n if (bugs) {\n links.bugs = bugs;\n }\n const result: searchUtils.SearchPackageBody = {\n name: version.name,\n description: version.description,\n version: latest,\n license: version.license,\n keywords: version.keywords,\n date: pkg.time[latest],\n // FIXME: type\n author: version.author as any,\n publisher,\n maintainers,\n };\n\n if (Object.keys(links).length > 0) {\n result.links = links;\n }\n\n return result;\n}\n\nexport function normalizeContributors(contributors: Author[]): Author[] {\n if (isNil(contributors)) {\n return [];\n } else if (contributors && !Array.isArray(contributors)) {\n return [contributors];\n } else if (typeof contributors === 'string') {\n return [\n {\n name: contributors,\n },\n ];\n }\n\n return contributors;\n}\n\n/**\n * Whether the tarball url path ends with the given file name (any query\n * string or fragment is ignored, like the path parsing in\n * `tarballUtils.extractTarballFromUrl`, which creates the `_distfiles`\n * keys — if that parsing ever changes, this must change with it).\n */\nexport function tarballMatchesFilename(tarball: string, filename: string): boolean {\n return tarball.split(/[?#]/)[0].endsWith(`/${filename}`);\n}\n\n/**\n * Build a distfile record from a version's dist metadata when its tarball\n * url matches the given file name.\n */\nexport function distFileFromVersion(\n version: Version | undefined,\n filename: string\n): DistFile | null {\n const dist = version?.dist;\n\n if (dist?.tarball && tarballMatchesFilename(dist.tarball, filename)) {\n return { url: dist.tarball, sha: dist.shasum } as DistFile;\n }\n\n return null;\n}\n\n/**\n * Resolve the distfile record for a tarball filename. Prefers the\n * `_distfiles` bookkeeping, but falls back to the version metadata when the\n * record is missing (storages written by other verdaccio versions cache\n * versions without their distfile records, which made those tarballs\n * permanently unavailable).\n *\n * Note: no extension pre-filter before the scan on purpose — GitHub\n * Packages advertises tarball urls ending in a bare sha-256 digest.\n * @param manifest cached manifest\n * @param filename tarball file name, eg. pkg-1.0.0.tgz\n */\nexport function lookupDistFile(manifest: Manifest, filename: string): DistFile | null {\n const distFile = manifest?._distfiles?.[filename];\n if (isNil(distFile) === false) {\n return distFile;\n }\n\n const versions = manifest?.versions ?? {};\n\n // tarballs are conventionally named <basename>-<version>.tgz, so the\n // version can usually be derived from the filename without scanning\n // manifests that carry thousands of versions\n const packageBasename = manifest?.name?.replace(/^.*\\//, '');\n if (packageBasename && filename.startsWith(`${packageBasename}-`) && filename.endsWith('.tgz')) {\n const versionId = filename.slice(packageBasename.length + 1, -'.tgz'.length);\n const distFromVersion = distFileFromVersion(versions[versionId], filename);\n\n if (distFromVersion) {\n debug('distfile record missing for %o, using version %o dist', filename, versionId);\n return distFromVersion;\n }\n }\n\n // unconventional tarball names: fall back to a scan\n for (const versionId in versions) {\n const distFromVersion = distFileFromVersion(versions[versionId], filename);\n\n if (distFromVersion) {\n debug('distfile record missing for %o, using version %o dist', filename, versionId);\n return distFromVersion;\n }\n }\n\n debug('no distfile record or version dist found for %o', filename);\n return null;\n}\n\n/**\n * Whether an uplink's configured url serves the given tarball url: same\n * protocol, same host and the uplink path is a prefix of the tarball path.\n * WHATWG URL normalizes default ports (https://h:443 === https://h).\n */\nexport function uplinkServesUrl(uplinkUrl: URL, tarballUrl: string): boolean {\n try {\n const parsed = new URL(tarballUrl);\n // Compare on a path segment boundary: an uplink at /registry must not\n // match tarballs under /registry2/... (wrong-uplink selection would send\n // the uplink's credentials to a sibling path).\n const basePath = uplinkUrl.pathname.endsWith('/')\n ? uplinkUrl.pathname\n : `${uplinkUrl.pathname}/`;\n return (\n parsed.protocol === uplinkUrl.protocol &&\n parsed.host === uplinkUrl.host &&\n parsed.pathname.startsWith(basePath)\n );\n } catch {\n return false;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"storage-utils.mjs","names":[],"sources":["../../src/lib/storage-utils.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { isNil, trim } from 'lodash-es';\nimport semver from 'semver';\n\nimport type { searchUtils } from '@verdaccio/core';\nimport {\n ANONYMOUS_USER,\n API_ERROR,\n DIST_TAGS,\n HTTP_STATUS,\n MAINTAINERS,\n USERS,\n cryptoUtils,\n errorUtils,\n pkgUtils,\n validationUtils,\n} from '@verdaccio/core';\nimport type {\n Author,\n DistFile,\n GenericBody,\n Manifest,\n Person,\n ReadmeOptions,\n Version,\n} from '@verdaccio/types';\n\nimport { sortVersionsAndFilterInvalid } from './versions-utils';\n\nconst debug = buildDebug('verdaccio:storage:utils');\n\nexport const STORAGE = {\n PACKAGE_FILE_NAME: 'package.json',\n FILE_EXIST_ERROR: 'EEXISTS',\n NO_SUCH_FILE_ERROR: 'ENOENT',\n DEFAULT_REVISION: '0-0000000000000000',\n};\n\n/**\n * Create a new package in the storage, return a boilerplate package\n * @param name package name\n * @returns {Manifest}\n */\nexport function generatePackageTemplate(name: string): Manifest {\n return {\n // standard things\n name,\n versions: {},\n time: {},\n [USERS]: {},\n [DIST_TAGS]: {},\n [MAINTAINERS]: [],\n _uplinks: {},\n _distfiles: {},\n _attachments: {},\n _rev: '',\n };\n}\n\n/**\n * Normalize package properties, tags, revision id.\n * @param {Object} pkg package reference.\n */\nexport function normalizePackage(pkg: Manifest): Manifest {\n const pkgProperties = ['versions', 'dist-tags', '_distfiles', '_attachments', '_uplinks', 'time'];\n\n pkgProperties.forEach((key): void => {\n const pkgProp = pkg[key];\n\n if (isNil(pkgProp) || validationUtils.isObject(pkgProp) === false) {\n pkg[key] = {};\n }\n });\n\n if (typeof pkg?._rev !== 'string') {\n pkg._rev = STORAGE.DEFAULT_REVISION;\n }\n\n if (typeof pkg?._id !== 'string') {\n pkg._id = pkg.name;\n }\n\n // normalize dist-tags\n return normalizeDistTags(pkg);\n}\n\nexport function generateRevision(rev: string): string {\n const _rev = rev.split('-');\n\n return (+_rev[0] || 0) + 1 + '-' + cryptoUtils.generateRandomHexString();\n}\n\nexport function getLatestReadme(pkg: Manifest): string {\n const versions = pkg['versions'] || {};\n const distTags = pkg[DIST_TAGS] || {};\n // FIXME: here is a bit tricky add the types\n const latestVersion: Version | any = distTags['latest'] ? versions[distTags['latest']] || {} : {};\n let readme = trim(pkg.readme || latestVersion.readme || '');\n if (readme) {\n return readme;\n }\n\n // In case of empty readme - trying to get ANY readme in the following order:\n // 'next','beta','alpha','test','dev','canary'\n const readmeDistTagsPriority = ['next', 'beta', 'alpha', 'test', 'dev', 'canary'];\n readmeDistTagsPriority.forEach(function (tag): string | void {\n if (readme) {\n return readme;\n }\n const version: Version | any = distTags[tag] ? versions[distTags[tag]] || {} : {};\n readme = trim(version.readme || readme);\n });\n return readme;\n}\n\n/**\n * Cleanup readme from package version\n *\n * By default, we don't keep readmes for package versions, only one readme per package.\n * Using publish.keep_readmes you can override this behavior and keep all readmes\n * or only readmes for tagged versions.\n */\nexport function cleanUpReadme(\n version: Version,\n distTags?: GenericBody,\n keepReadmes?: ReadmeOptions\n): Version {\n if (keepReadmes === 'all') {\n return version;\n } else if (keepReadmes === 'tagged') {\n if (distTags && Object.values(distTags).includes(version.version)) {\n return version;\n }\n }\n\n if (isNil(version) === false) {\n version.readme = '';\n }\n\n return version;\n}\n\nexport const WHITELIST = [\n '_rev',\n 'name',\n 'versions',\n 'dist-tags',\n 'readme',\n 'time',\n '_id',\n 'users',\n 'maintainers',\n];\n\nexport function cleanUpLinksRef(result: Manifest, keepUpLinkData?: boolean): Manifest {\n const propertyToKeep = [...WHITELIST];\n if (keepUpLinkData === true) {\n propertyToKeep.push('_uplinks');\n }\n\n for (const i in result) {\n if (propertyToKeep.indexOf(i) === -1) {\n // Remove sections like '_uplinks' from response\n delete result[i];\n }\n }\n\n return result;\n}\n\n// TODO: move to abstract storage\n// @deprecated use abstract.storage.ts:checkPackageRemote\nexport function checkPackageRemote(\n name: string,\n isAllowPublishOffline: boolean,\n syncMetadata: Function\n): Promise<any> {\n return new Promise<void>((resolve, reject): void => {\n syncMetadata(name, null, {}, (err, packageJsonLocal, upLinksErrors): void => {\n // something weird\n if (err && err.status !== HTTP_STATUS.NOT_FOUND) {\n return reject(err);\n }\n\n // checking package exist already\n if (isNil(packageJsonLocal) === false) {\n return reject(errorUtils.getConflict(API_ERROR.PACKAGE_EXIST));\n }\n\n for (let errorItem = 0; errorItem < upLinksErrors.length; errorItem++) {\n // checking error\n // if uplink fails with a status other than 404, we report failure\n if (isNil(upLinksErrors[errorItem][0]) === false) {\n if (upLinksErrors[errorItem][0].status !== HTTP_STATUS.NOT_FOUND) {\n if (isAllowPublishOffline) {\n return resolve();\n }\n\n return reject(errorUtils.getServiceUnavailable(API_ERROR.UPLINK_OFFLINE_PUBLISH));\n }\n }\n }\n\n return resolve();\n });\n });\n}\n\n// @deprecated use export function mergeUplinkTimeIntoLocalNext\nexport function mergeUplinkTimeIntoLocal(localMetadata: Manifest, remoteMetadata: Manifest): any {\n if ('time' in remoteMetadata) {\n return Object.assign({}, localMetadata.time, remoteMetadata.time);\n }\n\n return localMetadata.time;\n}\n\nexport function mergeUplinkTimeIntoLocalNext(\n cacheManifest: Manifest,\n remoteManifest: Manifest\n): Manifest {\n if ('time' in remoteManifest) {\n // remote override cache time conflicts\n return { ...cacheManifest, time: { ...cacheManifest.time, ...remoteManifest.time } };\n }\n\n return cacheManifest;\n}\n\nexport function updateUpLinkMetadata(uplinkName: string, manifest: Manifest, etag: string) {\n const _uplinks = {\n ...manifest._uplinks,\n [uplinkName]: {\n etag,\n fetched: Date.now(),\n },\n };\n return {\n ...manifest,\n _uplinks,\n };\n}\n\nexport function prepareSearchPackage(data: Manifest): any {\n const latest = pkgUtils.getLatest(data);\n\n if (latest && data.versions[latest]) {\n const version: Version = data.versions[latest];\n const versions: any = { [latest]: 'latest' };\n const pkg: any = {\n name: version.name,\n description: version.description,\n [DIST_TAGS]: { latest },\n maintainers: version.maintainers || [version.author].filter(Boolean),\n author: version.author,\n repository: version.repository,\n readmeFilename: version.readmeFilename || '',\n homepage: version.homepage,\n keywords: version.keywords,\n bugs: version.bugs,\n license: version.license,\n // time: {\n // modified: time,\n // },\n versions,\n };\n\n return pkg;\n }\n}\n\n/** Maintainer names copied from an uplink. Never a local account. */\nexport const UPSTREAM_MAINTAINER_PREFIX = '$uplink:';\n\nexport function scopeUpstreamMaintainers(maintainers: Person[], uplinkName: string): Person[] {\n const origin = uplinkName.length > 0 ? uplinkName : 'remote';\n return maintainers.map((maintainer) => {\n if (typeof maintainer === 'string') {\n return scopeUpstreamMaintainerName(origin, maintainer);\n }\n const name = typeof maintainer?.name === 'string' ? maintainer.name : '';\n return {\n ...maintainer,\n name: scopeUpstreamMaintainerName(origin, name),\n };\n });\n}\n\nfunction scopeUpstreamMaintainerName(uplinkName: string, name: string): string {\n if (name.startsWith(UPSTREAM_MAINTAINER_PREFIX)) {\n return name;\n }\n return `${UPSTREAM_MAINTAINER_PREFIX}${uplinkName}:${name}`;\n}\n\nexport function maintainerAllowsLocalUser(\n maintainer: Person,\n username: string | undefined\n): boolean {\n const name = typeof maintainer === 'string' ? maintainer : maintainer?.name;\n // reserved uplink identities must not authorize the local user who registered that string\n if (typeof name === 'string' && name.startsWith(UPSTREAM_MAINTAINER_PREFIX)) {\n return false;\n }\n return name === username || name === ANONYMOUS_USER;\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 {*} cacheManifest\n * @param {*} remoteManifest\n */\nexport function mergeVersions(cacheManifest: Manifest, remoteManifest: Manifest): Manifest {\n let _cacheManifest = { ...cacheManifest };\n const { versions, time } = remoteManifest;\n // copy new versions to a cache\n // NOTE: if a certain version was updated, we can't refresh it reliably\n // however, we can refresh the deprecated status\n for (const i in versions) {\n if (typeof _cacheManifest.versions[i] === 'undefined') {\n _cacheManifest.versions[i] = versions[i];\n } else if (versions[i].deprecated) {\n _cacheManifest.versions[i].deprecated = versions[i].deprecated;\n }\n }\n\n for (const i in time) {\n if (typeof _cacheManifest.time[i] === 'undefined') {\n _cacheManifest.time[i] = time[i];\n }\n }\n\n for (const distTag in remoteManifest[DIST_TAGS]) {\n if (_cacheManifest[DIST_TAGS][distTag] !== remoteManifest[DIST_TAGS][distTag]) {\n if (\n !_cacheManifest[DIST_TAGS][distTag] ||\n semver.lte(_cacheManifest[DIST_TAGS][distTag], remoteManifest[DIST_TAGS][distTag])\n ) {\n _cacheManifest[DIST_TAGS][distTag] = remoteManifest[DIST_TAGS][distTag];\n }\n if (\n distTag === 'latest' &&\n _cacheManifest[DIST_TAGS][distTag] === remoteManifest[DIST_TAGS][distTag]\n ) {\n // NOTE: this override the latest publish readme from local cache with\n // the remote one\n _cacheManifest = { ..._cacheManifest, readme: remoteManifest.readme };\n }\n }\n }\n return _cacheManifest;\n}\n\n/**\n * Normalize dist-tags.\n *\n * There is a legacy behaviour where the dist-tags could be an array, in such\n * case, the array is orderded and the highest version becames the\n * latest.\n *\n * The dist-tag tags must be plain strigs, if the latest is empty (for whatever reason) is\n * normalized to be the highest version available.\n *\n * This function cleans up every invalid version on dist-tags, but does not remove\n * invalid versions from the manifest.\n *\n * @param {*} data\n */\nexport function normalizeDistTags(manifest: Manifest): Manifest {\n let sorted;\n // handle missing latest dist-tag\n if (!manifest[DIST_TAGS].latest) {\n // if there is no latest tag, set the highest known version based on semver sort\n sorted = sortVersionsAndFilterInvalid(Object.keys(manifest.versions));\n if (sorted?.length) {\n // get the highest published version\n manifest[DIST_TAGS].latest = sorted.pop();\n }\n }\n\n for (const tag in manifest[DIST_TAGS]) {\n // deprecated (will be removed un future majors)\n // this should not happen, tags should be plain strings, legacy fallback\n if (Array.isArray(manifest[DIST_TAGS][tag])) {\n if (manifest[DIST_TAGS][tag].length) {\n // sort array\n // FIXME: this is clearly wrong, we need to research why this is like this.\n // @ts-ignore\n sorted = sortVersionsAndFilterInvalid(manifest[DIST_TAGS][tag]);\n if (sorted.length) {\n // use highest version based on semver sort\n manifest[DIST_TAGS][tag] = sorted.pop();\n }\n } else {\n delete manifest[DIST_TAGS][tag];\n }\n } else if (typeof manifest[DIST_TAGS][tag] === 'string') {\n if (!semver.parse(manifest[DIST_TAGS][tag], true)) {\n // if the version is invalid, delete the dist-tag entry\n delete manifest[DIST_TAGS][tag];\n }\n }\n }\n\n return manifest;\n}\n\nexport function hasDeprecatedVersions(pkgInfo: Manifest): boolean {\n const { versions } = pkgInfo;\n for (const version in versions) {\n if (Object.prototype.hasOwnProperty.call(versions[version], 'deprecated')) {\n return true;\n }\n }\n return false;\n}\n\nexport function isDeprecatedManifest(manifest: Manifest): boolean {\n return (\n hasDeprecatedVersions(manifest) &&\n (typeof manifest._attachments === 'undefined' ||\n Object.keys(manifest._attachments).length === 0)\n );\n}\n\nexport function mapManifestToSearchPackageBody(\n pkg: Manifest,\n _searchItem: searchUtils.SearchItem\n): searchUtils.SearchPackageBody {\n const latest = pkgUtils.getLatest(pkg);\n const version: Version = pkg.versions[latest];\n // packument maintainers carry `name`, but the npm search API contract uses\n // `username` and the npm CLI crashes on entries without it — emit both\n const maintainers = Array.isArray(version.maintainers)\n ? version.maintainers.map((maintainer: any) =>\n typeof maintainer === 'string'\n ? { username: maintainer, email: '' }\n : {\n ...maintainer,\n username: maintainer?.username ?? maintainer?.name ?? '',\n email: maintainer?.email ?? '',\n }\n )\n : [];\n // npmjs fills `publisher` with the user who published the version; use\n // `_npmUser` when the client provided it and fall back to the first\n // maintainer (verdaccio sets it to the publishing user), otherwise the\n // npm CLI renders \"published by ???\"\n const publisher = version._npmUser?.name\n ? { username: version._npmUser.name, email: version._npmUser.email ?? '' }\n : (maintainers[0] ?? {});\n const links: NonNullable<searchUtils.SearchPackageBody['links']> = {};\n const repository =\n typeof version.repository === 'string' ? version.repository : version.repository?.url;\n const bugs = typeof version.bugs === 'string' ? version.bugs : version.bugs?.url;\n if (version.homepage) {\n links.homepage = version.homepage;\n }\n if (repository) {\n links.repository = repository;\n }\n if (bugs) {\n links.bugs = bugs;\n }\n const result: searchUtils.SearchPackageBody = {\n name: version.name,\n description: version.description,\n version: latest,\n license: version.license,\n keywords: version.keywords,\n date: pkg.time[latest],\n // FIXME: type\n author: version.author as any,\n publisher,\n maintainers,\n };\n\n if (Object.keys(links).length > 0) {\n result.links = links;\n }\n\n return result;\n}\n\nexport function normalizeContributors(contributors: Author[]): Author[] {\n if (isNil(contributors)) {\n return [];\n } else if (contributors && !Array.isArray(contributors)) {\n return [contributors];\n } else if (typeof contributors === 'string') {\n return [\n {\n name: contributors,\n },\n ];\n }\n\n return contributors;\n}\n\n/**\n * Whether the tarball url path ends with the given file name (any query\n * string or fragment is ignored, like the path parsing in\n * `tarballUtils.extractTarballFromUrl`, which creates the `_distfiles`\n * keys — if that parsing ever changes, this must change with it).\n */\nexport function tarballMatchesFilename(tarball: string, filename: string): boolean {\n return tarball.split(/[?#]/)[0].endsWith(`/${filename}`);\n}\n\n/**\n * Build a distfile record from a version's dist metadata when its tarball\n * url matches the given file name.\n */\nexport function distFileFromVersion(\n version: Version | undefined,\n filename: string\n): DistFile | null {\n const dist = version?.dist;\n\n if (dist?.tarball && tarballMatchesFilename(dist.tarball, filename)) {\n return { url: dist.tarball, sha: dist.shasum } as DistFile;\n }\n\n return null;\n}\n\n/**\n * Resolve the distfile record for a tarball filename. Prefers the\n * `_distfiles` bookkeeping, but falls back to the version metadata when the\n * record is missing (storages written by other verdaccio versions cache\n * versions without their distfile records, which made those tarballs\n * permanently unavailable).\n *\n * Note: no extension pre-filter before the scan on purpose — GitHub\n * Packages advertises tarball urls ending in a bare sha-256 digest.\n * @param manifest cached manifest\n * @param filename tarball file name, eg. pkg-1.0.0.tgz\n */\nexport function lookupDistFile(manifest: Manifest, filename: string): DistFile | null {\n const distFile = manifest?._distfiles?.[filename];\n if (isNil(distFile) === false) {\n return distFile;\n }\n\n const versions = manifest?.versions ?? {};\n\n // tarballs are conventionally named <basename>-<version>.tgz, so the\n // version can usually be derived from the filename without scanning\n // manifests that carry thousands of versions\n const packageBasename = manifest?.name?.replace(/^.*\\//, '');\n if (packageBasename && filename.startsWith(`${packageBasename}-`) && filename.endsWith('.tgz')) {\n const versionId = filename.slice(packageBasename.length + 1, -'.tgz'.length);\n const distFromVersion = distFileFromVersion(versions[versionId], filename);\n\n if (distFromVersion) {\n debug('distfile record missing for %o, using version %o dist', filename, versionId);\n return distFromVersion;\n }\n }\n\n // unconventional tarball names: fall back to a scan\n for (const versionId in versions) {\n const distFromVersion = distFileFromVersion(versions[versionId], filename);\n\n if (distFromVersion) {\n debug('distfile record missing for %o, using version %o dist', filename, versionId);\n return distFromVersion;\n }\n }\n\n debug('no distfile record or version dist found for %o', filename);\n return null;\n}\n\n/**\n * Whether an uplink's configured url serves the given tarball url: same\n * protocol, same host and the uplink path is a prefix of the tarball path.\n * WHATWG URL normalizes default ports (https://h:443 === https://h).\n */\nexport function uplinkServesUrl(uplinkUrl: URL, tarballUrl: string): boolean {\n try {\n const parsed = new URL(tarballUrl);\n // Compare on a path segment boundary: an uplink at /registry must not\n // match tarballs under /registry2/... (wrong-uplink selection would send\n // the uplink's credentials to a sibling path).\n const basePath = uplinkUrl.pathname.endsWith('/')\n ? uplinkUrl.pathname\n : `${uplinkUrl.pathname}/`;\n return (\n parsed.protocol === uplinkUrl.protocol &&\n parsed.host === uplinkUrl.host &&\n parsed.pathname.startsWith(basePath)\n );\n } catch {\n return false;\n }\n}\n"],"mappings":"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"}
|
package/build/storage.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { PassThrough, Readable } from 'node:stream';
|
|
2
2
|
import type { searchUtils } from '@verdaccio/core';
|
|
3
3
|
import type { ISyncUplinksOptions, ProxyInstanceList, ProxySearchParams } from '@verdaccio/proxy';
|
|
4
|
+
import type { RequestOptions } from '@verdaccio/url';
|
|
4
5
|
import type { AbbreviatedManifest, Config, Logger, Manifest, MergeTags, Token, TokenFilter, UnPublishManifest, Version } from '@verdaccio/types';
|
|
5
6
|
import type { UpdateManifestOptions } from '.';
|
|
6
7
|
import { type Filters } from './filter-pipeline';
|
|
@@ -25,7 +26,9 @@ declare class Storage {
|
|
|
25
26
|
Function changes a package info from local storage and all uplinks with write access./
|
|
26
27
|
Used storages: local (write)
|
|
27
28
|
*/
|
|
28
|
-
changePackage(name: string, metadata: Manifest, revision: string
|
|
29
|
+
changePackage(name: string, metadata: Manifest, revision: string, auth?: {
|
|
30
|
+
username?: string;
|
|
31
|
+
}): Promise<void>;
|
|
29
32
|
removePackage(name: string, revision: string, username: string): Promise<void>;
|
|
30
33
|
/**
|
|
31
34
|
Remove a tarball from a system
|
|
@@ -121,7 +124,7 @@ declare class Storage {
|
|
|
121
124
|
* @param name package name
|
|
122
125
|
* @param tags list of dist-tags
|
|
123
126
|
*/
|
|
124
|
-
mergeTagsNext(name: string, tags: MergeTags): Promise<Manifest>;
|
|
127
|
+
mergeTagsNext(name: string, tags: MergeTags, requestOptions?: RequestOptions): Promise<Manifest>;
|
|
125
128
|
/**
|
|
126
129
|
* Resolve the uplink to fetch a distfile url from, or null when the fetch
|
|
127
130
|
* must be refused.
|
|
@@ -134,6 +137,11 @@ declare class Storage {
|
|
|
134
137
|
*/
|
|
135
138
|
private getUpLinkForDistFile;
|
|
136
139
|
updateManifest(manifest: Manifest | OwnerManifestBody | UnPublishManifest, options: UpdateManifestOptions): Promise<string | undefined>;
|
|
140
|
+
/**
|
|
141
|
+
* Read the stored manifest and apply `publish.check_owners` before
|
|
142
|
+
* `changePackage` takes the package lock. The locked path checks again.
|
|
143
|
+
*/
|
|
144
|
+
private getLocalManifestCheckOwnership;
|
|
137
145
|
private deprecate;
|
|
138
146
|
private unPublishAPackage;
|
|
139
147
|
private changeOwners;
|
|
@@ -292,7 +300,7 @@ declare class Storage {
|
|
|
292
300
|
@param remoteManifest
|
|
293
301
|
@returns return a merged manifest.
|
|
294
302
|
*/
|
|
295
|
-
updateVersionsNext(name: string, remoteManifest: Manifest): Promise<Manifest>;
|
|
303
|
+
updateVersionsNext(name: string, remoteManifest: Manifest, uplinkName?: string): Promise<Manifest>;
|
|
296
304
|
private getTarballStats;
|
|
297
305
|
private checkAllowedToChangePackage;
|
|
298
306
|
}
|