diff --git a/.pnp.js b/.pnp.js index 52c9b2016..c4ca80411 100755 --- a/.pnp.js +++ b/.pnp.js @@ -85,7 +85,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@verdaccio/local-storage", "npm:10.3.1"], ["@verdaccio/readme", "npm:10.4.1"], ["@verdaccio/streams", "npm:10.2.0"], - ["@verdaccio/types", "npm:10.5.2"], + ["@verdaccio/types", "npm:10.6.0"], ["@verdaccio/ui-theme", "npm:6.0.0-6-next.28"], ["JSONStream", "npm:1.3.5"], ["all-contributors-cli", "npm:6.20.0"], @@ -5946,10 +5946,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["@verdaccio/types", [ - ["npm:10.5.2", { - "packageLocation": "./.yarn/cache/@verdaccio-types-npm-10.5.2-df408a0b4b-60f8a1068b.zip/node_modules/@verdaccio/types/", + ["npm:10.6.0", { + "packageLocation": "./.yarn/cache/@verdaccio-types-npm-10.6.0-31edb84449-7065a8551b.zip/node_modules/@verdaccio/types/", "packageDependencies": [ - ["@verdaccio/types", "npm:10.5.2"] + ["@verdaccio/types", "npm:10.6.0"] ], "linkType": "HARD", }] @@ -8138,14 +8138,14 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ]], ["core-js", [ ["npm:2.6.9", { - "packageLocation": "./.yarn/cache/core-js-npm-2.6.9-f821bf686c-00c30207eb.zip/node_modules/core-js/", + "packageLocation": "./.yarn/unplugged/core-js-npm-2.6.9-f821bf686c/node_modules/core-js/", "packageDependencies": [ ["core-js", "npm:2.6.9"] ], "linkType": "HARD", }], ["npm:3.22.4", { - "packageLocation": "./.yarn/cache/core-js-npm-3.22.4-4469b89edf-1305b2b9c1.zip/node_modules/core-js/", + "packageLocation": "./.yarn/unplugged/core-js-npm-3.22.4-4469b89edf/node_modules/core-js/", "packageDependencies": [ ["core-js", "npm:3.22.4"] ], @@ -8174,7 +8174,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ]], ["core-js-pure", [ ["npm:3.23.1", { - "packageLocation": "./.yarn/cache/core-js-pure-npm-3.23.1-352ee71e9f-bb20413b8f.zip/node_modules/core-js-pure/", + "packageLocation": "./.yarn/unplugged/core-js-pure-npm-3.23.1-352ee71e9f/node_modules/core-js-pure/", "packageDependencies": [ ["core-js-pure", "npm:3.23.1"] ], @@ -15379,7 +15379,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ]], ["puppeteer", [ ["npm:5.5.0", { - "packageLocation": "./.yarn/cache/puppeteer-npm-5.5.0-bba75ba998-08ba8a7da5.zip/node_modules/puppeteer/", + "packageLocation": "./.yarn/unplugged/puppeteer-npm-5.5.0-bba75ba998/node_modules/puppeteer/", "packageDependencies": [ ["puppeteer", "npm:5.5.0"], ["debug", "virtual:e9a07d9e500f265638a80b6a2d60a63d2c1402dd6a58d2f05af9d82e52be33df29a16291c32b33b9e23f1a0efea054868bd3312893433fe0583e4dba376fe47e#npm:4.1.1"], @@ -18148,7 +18148,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@verdaccio/local-storage", "npm:10.3.1"], ["@verdaccio/readme", "npm:10.4.1"], ["@verdaccio/streams", "npm:10.2.0"], - ["@verdaccio/types", "npm:10.5.2"], + ["@verdaccio/types", "npm:10.6.0"], ["@verdaccio/ui-theme", "npm:6.0.0-6-next.28"], ["JSONStream", "npm:1.3.5"], ["all-contributors-cli", "npm:6.20.0"], diff --git a/.yarn/cache/@verdaccio-types-npm-10.5.2-df408a0b4b-60f8a1068b.zip b/.yarn/cache/@verdaccio-types-npm-10.5.2-df408a0b4b-60f8a1068b.zip deleted file mode 100644 index 5abc1256d..000000000 Binary files a/.yarn/cache/@verdaccio-types-npm-10.5.2-df408a0b4b-60f8a1068b.zip and /dev/null differ diff --git a/.yarn/cache/@verdaccio-types-npm-10.6.0-31edb84449-7065a8551b.zip b/.yarn/cache/@verdaccio-types-npm-10.6.0-31edb84449-7065a8551b.zip new file mode 100644 index 000000000..a79d538f7 Binary files /dev/null and b/.yarn/cache/@verdaccio-types-npm-10.6.0-31edb84449-7065a8551b.zip differ diff --git a/package.json b/package.json index 1d32e4cb6..0adb7d410 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,7 @@ "@typescript-eslint/parser": "5.22.0", "@verdaccio-scope/verdaccio-auth-foo": "0.0.2", "@verdaccio/eslint-config": "^10.0.0", - "@verdaccio/types": "10.5.2", + "@verdaccio/types": "10.6.0", "all-contributors-cli": "6.20.0", "babel-eslint": "10.1.0", "babel-jest": "26.6.3", diff --git a/src/api/endpoint/api/package.ts b/src/api/endpoint/api/package.ts index 89856b57a..4a002dfc0 100644 --- a/src/api/endpoint/api/package.ts +++ b/src/api/endpoint/api/package.ts @@ -8,6 +8,7 @@ import { API_ERROR, DIST_TAGS, HEADERS } from '../../../lib/constants'; import { ErrorCode, convertDistRemoteToLocalTarballUrls, getVersion } from '../../../lib/utils'; import { allow } from '../../middleware'; +const ABBREVIATED_HEADER = 'application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*'; const downloadStream = (packageName: string, filename: string, storage: any, req: $RequestExtend, res: $ResponseExtend): void => { const stream = storage.getTarball(packageName, filename); @@ -72,11 +73,12 @@ export default function (route: Router, auth: IAuth, storage: IStorageHandler, c } return next(ErrorCode.getNotFound(`${API_ERROR.VERSION_NOT_EXIST}: ${req.params.version}`)); }; - + const abbreviated = req.get('Accept') === ABBREVIATED_HEADER; storage.getPackage({ name: req.params.package, uplinksLook: true, req, + abbreviated, callback: getPackageMetaCallback, }); }); diff --git a/src/lib/storage-utils.ts b/src/lib/storage-utils.ts index 645248482..3082ff287 100644 --- a/src/lib/storage-utils.ts +++ b/src/lib/storage-utils.ts @@ -1,6 +1,6 @@ import _ from 'lodash'; -import { Author, Package, Version } from '@verdaccio/types'; +import { AbbreviatedManifest, AbbreviatedVersions, Author, Manifest, Package, Version } from '@verdaccio/types'; import { IStorage } from '../../types'; import { generateRandomHexString } from '../lib/crypto-utils'; @@ -236,3 +236,44 @@ export function isPublishablePackage(pkg: Package): boolean { return _.includes(keys, 'versions'); } + +export function convertAbbreviatedManifest(manifest: Manifest): AbbreviatedManifest { + const abbreviatedVersions = Object.keys(manifest.versions).reduce((acc: AbbreviatedVersions, version: string) => { + const _version = manifest.versions[version]; + // This should be align with this document + // https://github.com/npm/registry/blob/master/docs/responses/package-metadata.md#abbreviated-version-object + const _version_abbreviated = { + name: _version.name, + version: _version.version, + description: _version.description, + deprecated: _version.deprecated, + bin: _version.bin, + dist: _version.dist, + engines: _version.engines, + funding: _version.funding, + directories: _version.directories, + dependencies: _version.dependencies, + devDependencies: _version.devDependencies, + peerDependencies: _version.peerDependencies, + optionalDependencies: _version.optionalDependencies, + bundleDependencies: _version.bundleDependencies, + // npm cli specifics + _hasShrinkwrap: _version._hasShrinkwrap, + hasInstallScript: _version.hasInstallScript, + }; + acc[version] = _version_abbreviated; + return acc; + }, {}); + const convertedManifest = { + name: manifest['name'], + [DIST_TAGS]: manifest[DIST_TAGS], + versions: abbreviatedVersions, + // @ts-ignore + modified: manifest?.time?.modified, + // NOTE: special case for pnpm https://github.com/pnpm/rfcs/pull/2 + time: manifest?.time, + }; + + // @ts-ignore + return convertedManifest; +} diff --git a/src/lib/storage.ts b/src/lib/storage.ts index 9e53b5289..667eece17 100644 --- a/src/lib/storage.ts +++ b/src/lib/storage.ts @@ -15,7 +15,15 @@ import { API_ERROR, DIST_TAGS, HTTP_STATUS } from './constants'; import LocalStorage from './local-storage'; import { mergeVersions } from './metadata-utils'; import Search from './search'; -import { checkPackageLocal, checkPackageRemote, cleanUpLinksRef, generatePackageTemplate, mergeUplinkTimeIntoLocal, publishPackage } from './storage-utils'; +import { + checkPackageLocal, + checkPackageRemote, + cleanUpLinksRef, + convertAbbreviatedManifest, + generatePackageTemplate, + mergeUplinkTimeIntoLocal, + publishPackage, +} from './storage-utils'; import ProxyStorage from './up-storage'; import { setupUpLinks, updateVersionsHiddenUpLink } from './uplink-util'; import { ErrorCode, isObject, normalizeDistTags, validateMetadata } from './utils'; @@ -323,8 +331,11 @@ class Storage implements IStorageHandler { // npm can throw if this field doesn't exist result._attachments = {}; - - options.callback(null, result, uplinkErrors); + if (options.abbreviated === true) { + options.callback(null, convertAbbreviatedManifest(result), uplinkErrors); + } else { + options.callback(null, result, uplinkErrors); + } } ); }); diff --git a/test/unit/modules/api/api.spec.ts b/test/unit/modules/api/api.spec.ts index 1d156e007..259eeca9b 100644 --- a/test/unit/modules/api/api.spec.ts +++ b/test/unit/modules/api/api.spec.ts @@ -6,7 +6,7 @@ import { Readable } from 'stream'; import request from 'supertest'; import endPointAPI from '../../../../src/api'; -import { API_ERROR, API_MESSAGE, HEADERS, HEADER_TYPE, HTTP_STATUS, TOKEN_BEARER } from '../../../../src/lib/constants'; +import { API_ERROR, API_MESSAGE, DIST_TAGS, HEADERS, HEADER_TYPE, HTTP_STATUS, TOKEN_BEARER } from '../../../../src/lib/constants'; import { buildToken, encodeScopedUri } from '../../../../src/lib/utils'; import { DOMAIN_SERVERS } from '../../../functional/config.functional'; import { generateUnPublishURI, getNewToken, getPackage, putPackage, verifyPackageVersionDoesExist } from '../../__helper/api'; @@ -339,6 +339,31 @@ describe('endpoint unit test', () => { }); }); + test('should fetch abbreviated jquery package from remote uplink', (done) => { + request(app) + .get('/jquery') + .set('accept', 'application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*') + .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) + .expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET) + .expect(HTTP_STATUS.OK) + .end(function (err, res) { + if (err) { + return done(err); + } + const manifest = res.body; + expect(manifest).toBeDefined(); + expect(manifest.name).toMatch(/jquery/); + expect(manifest.description).not.toBeDefined(); + expect(manifest.readme).not.toBeDefined(); + expect(manifest[DIST_TAGS]).toBeDefined(); + expect(manifest.modified).toBeDefined(); + expect(Object.keys(manifest.versions)).toHaveLength(48); + // NOTE: special case for pnpm https://github.com/pnpm/rfcs/pull/2 + expect(Object.keys(manifest.time)).toHaveLength(51); + done(); + }); + }); + test('should fails with socket time out fetch tarball timeout package from remote uplink', async () => { const timeOutPkg = generatePackageMetadata('timeout', '1.5.1'); const responseText = 'fooooooooooooooooo'; diff --git a/types/index.ts b/types/index.ts index f1c02a3e3..444a4523c 100644 --- a/types/index.ts +++ b/types/index.ts @@ -171,6 +171,7 @@ export interface IGetPackageOptions { keepUpLinkData: boolean; uplinksLook: boolean; req: any; + abbreviated?: boolean; } export interface ISyncUplinks { diff --git a/yarn.lock b/yarn.lock index b08dcb1de..08ec5f512 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4071,10 +4071,10 @@ __metadata: languageName: node linkType: hard -"@verdaccio/types@npm:10.5.2": - version: 10.5.2 - resolution: "@verdaccio/types@npm:10.5.2" - checksum: 60f8a1068be4872d4c971e40862df641fab65a554c3783106b776c26aac01328a33af3d566a083711f86cac72d89d9d83fb0d63c0b0485b6a76ef1eb579033b9 +"@verdaccio/types@npm:10.6.0": + version: 10.6.0 + resolution: "@verdaccio/types@npm:10.6.0" + checksum: 7065a8551b9e3f622143fba73e0088a824bf432fb4ea9b02d6f3042929f1faf3a2c1289a0b724963631bdbd5d9a17c96471bede5452a2538f4ecc63e3880628c languageName: node linkType: hard @@ -15056,7 +15056,7 @@ typescript@4.1.3: "@verdaccio/local-storage": 10.3.1 "@verdaccio/readme": 10.4.1 "@verdaccio/streams": 10.2.0 - "@verdaccio/types": 10.5.2 + "@verdaccio/types": 10.6.0 "@verdaccio/ui-theme": 6.0.0-6-next.28 JSONStream: 1.3.5 all-contributors-cli: 6.20.0