@verdaccio/api 6.0.0-6-next.28 → 6.0.0-6-next.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/build/package.js +2 -1
- package/build/package.js.map +1 -1
- package/build/publish.d.ts +1 -1
- package/build/publish.js +2 -3
- package/build/publish.js.map +1 -1
- package/package.json +11 -11
- package/src/package.ts +1 -0
- package/src/publish.ts +2 -3
- package/test/integration/config/publish-proxy.yaml +26 -0
- package/test/integration/package.spec.ts +81 -45
- package/test/integration/publish.spec.ts +148 -124
- package/test/integration/user.jwt.spec.ts +0 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @verdaccio/api
|
|
2
2
|
|
|
3
|
+
## 6.0.0-6-next.29
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- b849128d: fix: handle upload scoped tarball
|
|
8
|
+
- Updated dependencies [b849128d]
|
|
9
|
+
- @verdaccio/core@6.0.0-6-next.8
|
|
10
|
+
- @verdaccio/store@6.0.0-6-next.26
|
|
11
|
+
- @verdaccio/auth@6.0.0-6-next.25
|
|
12
|
+
- @verdaccio/config@6.0.0-6-next.17
|
|
13
|
+
- @verdaccio/logger@6.0.0-6-next.14
|
|
14
|
+
- @verdaccio/middleware@6.0.0-6-next.25
|
|
15
|
+
- @verdaccio/utils@6.0.0-6-next.14
|
|
16
|
+
|
|
3
17
|
## 6.0.0-6-next.28
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/build/package.js
CHANGED
|
@@ -58,7 +58,8 @@ function _default(route, auth, storage) {
|
|
|
58
58
|
|
|
59
59
|
try {
|
|
60
60
|
const stream = await storage.getTarballNext(pkg, filename, {
|
|
61
|
-
signal: abort.signal //
|
|
61
|
+
signal: abort.signal // TODO: review why this param
|
|
62
|
+
// enableRemote: true,
|
|
62
63
|
|
|
63
64
|
});
|
|
64
65
|
stream.on('content-length', size => {
|
package/build/package.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package.js","names":["debug","buildDebug","route","auth","storage","can","allow","get","req","_res","next","name","params","package","version","write","query","abbreviated","Storage","ABBREVIATED_HEADER","requestOptions","protocol","headers","host","remoteAddress","socket","byPassCache","manifest","getPackageByOptions","uplinksLook","err","res","pkg","filename","abort","AbortController","stream","getTarballNext","signal","on","size","header","HEADER_TYPE","CONTENT_LENGTH","once","locals","report_error","url","HEADERS","CONTENT_TYPE","OCTET_STREAM","pipe"],"sources":["../src/package.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { Router } from 'express';\n\nimport { IAuth } from '@verdaccio/auth';\nimport { HEADERS, HEADER_TYPE } from '@verdaccio/core';\nimport { allow } from '@verdaccio/middleware';\nimport { Storage } from '@verdaccio/store';\n\nimport { $NextFunctionVer, $RequestExtend, $ResponseExtend } from '../types/custom';\n\nconst debug = buildDebug('verdaccio:api:package');\n\nexport default function (route: Router, auth: IAuth, storage: Storage): void {\n const can = allow(auth);\n\n route.get(\n '/:package/:version?',\n can('access'),\n async function (\n req: $RequestExtend,\n _res: $ResponseExtend,\n next: $NextFunctionVer\n ): Promise<void> {\n debug('init package by version');\n const name = req.params.package;\n let version = req.params.version;\n const write = req.query.write === 'true';\n const abbreviated = req.get('Accept') === Storage.ABBREVIATED_HEADER;\n const requestOptions = {\n protocol: req.protocol,\n headers: req.headers as any,\n // FIXME: if we migrate to req.hostname, the port is not longer included.\n host: req.host,\n remoteAddress: req.socket.remoteAddress,\n byPassCache: write,\n };\n\n try {\n const manifest = await storage.getPackageByOptions({\n name,\n uplinksLook: true,\n abbreviated,\n version,\n requestOptions,\n });\n next(manifest);\n } catch (err) {\n next(err);\n }\n }\n );\n\n route.get(\n '/:pkg/-/:filename',\n can('access'),\n async function (req: $RequestExtend, res: $ResponseExtend, next): Promise<void> {\n const { pkg, filename } = req.params;\n const abort = new AbortController();\n try {\n const stream = (await storage.getTarballNext(pkg, filename, {\n signal: abort.signal,\n // enableRemote: true,\n })) as any;\n\n stream.on('content-length', (size) => {\n res.header(HEADER_TYPE.CONTENT_LENGTH, size);\n });\n\n stream.once('error', (err) => {\n res.locals.report_error(err);\n next(err);\n });\n\n req.on('abort', () => {\n debug('request aborted for %o', req.url);\n abort.abort();\n });\n\n res.header(HEADERS.CONTENT_TYPE, HEADERS.OCTET_STREAM);\n stream.pipe(res);\n } catch (err: any) {\n // console.log('catch API error request', err);\n res.locals.report_error(err);\n next(err);\n }\n }\n );\n}\n"],"mappings":";;;;;;;AAAA;;AAIA;;AACA;;AACA;;;;AAIA,MAAMA,KAAK,GAAG,IAAAC,cAAA,EAAW,uBAAX,CAAd;;AAEe,kBAAUC,KAAV,EAAyBC,IAAzB,EAAsCC,OAAtC,EAA8D;EAC3E,MAAMC,GAAG,GAAG,IAAAC,iBAAA,EAAMH,IAAN,CAAZ;EAEAD,KAAK,CAACK,GAAN,CACE,qBADF,EAEEF,GAAG,CAAC,QAAD,CAFL,EAGE,gBACEG,GADF,EAEEC,IAFF,EAGEC,IAHF,EAIiB;IACfV,KAAK,CAAC,yBAAD,CAAL;IACA,MAAMW,IAAI,GAAGH,GAAG,CAACI,MAAJ,CAAWC,OAAxB;IACA,IAAIC,OAAO,GAAGN,GAAG,CAACI,MAAJ,CAAWE,OAAzB;IACA,MAAMC,KAAK,GAAGP,GAAG,CAACQ,KAAJ,CAAUD,KAAV,KAAoB,MAAlC;;IACA,MAAME,WAAW,GAAGT,GAAG,CAACD,GAAJ,CAAQ,QAAR,MAAsBW,cAAA,CAAQC,kBAAlD;;IACA,MAAMC,cAAc,GAAG;MACrBC,QAAQ,EAAEb,GAAG,CAACa,QADO;MAErBC,OAAO,EAAEd,GAAG,CAACc,OAFQ;MAGrB;MACAC,IAAI,EAAEf,GAAG,CAACe,IAJW;MAKrBC,aAAa,EAAEhB,GAAG,CAACiB,MAAJ,CAAWD,aALL;MAMrBE,WAAW,EAAEX;IANQ,CAAvB;;IASA,IAAI;MACF,MAAMY,QAAQ,GAAG,MAAMvB,OAAO,CAACwB,mBAAR,CAA4B;QACjDjB,IADiD;QAEjDkB,WAAW,EAAE,IAFoC;QAGjDZ,WAHiD;QAIjDH,OAJiD;QAKjDM;MALiD,CAA5B,CAAvB;MAOAV,IAAI,CAACiB,QAAD,CAAJ;IACD,CATD,CASE,OAAOG,GAAP,EAAY;MACZpB,IAAI,CAACoB,GAAD,CAAJ;IACD;EACF,CAlCH;EAqCA5B,KAAK,CAACK,GAAN,CACE,mBADF,EAEEF,GAAG,CAAC,QAAD,CAFL,EAGE,gBAAgBG,GAAhB,EAAqCuB,GAArC,EAA2DrB,IAA3D,EAAgF;IAC9E,MAAM;MAAEsB,GAAF;MAAOC;IAAP,IAAoBzB,GAAG,CAACI,MAA9B;IACA,MAAMsB,KAAK,GAAG,IAAIC,eAAJ,EAAd;;IACA,IAAI;MACF,MAAMC,MAAM,GAAI,MAAMhC,OAAO,CAACiC,cAAR,CAAuBL,GAAvB,EAA4BC,QAA5B,EAAsC;QAC1DK,MAAM,EAAEJ,KAAK,CAACI,MAD4C,CAE1D;;
|
|
1
|
+
{"version":3,"file":"package.js","names":["debug","buildDebug","route","auth","storage","can","allow","get","req","_res","next","name","params","package","version","write","query","abbreviated","Storage","ABBREVIATED_HEADER","requestOptions","protocol","headers","host","remoteAddress","socket","byPassCache","manifest","getPackageByOptions","uplinksLook","err","res","pkg","filename","abort","AbortController","stream","getTarballNext","signal","on","size","header","HEADER_TYPE","CONTENT_LENGTH","once","locals","report_error","url","HEADERS","CONTENT_TYPE","OCTET_STREAM","pipe"],"sources":["../src/package.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { Router } from 'express';\n\nimport { IAuth } from '@verdaccio/auth';\nimport { HEADERS, HEADER_TYPE } from '@verdaccio/core';\nimport { allow } from '@verdaccio/middleware';\nimport { Storage } from '@verdaccio/store';\n\nimport { $NextFunctionVer, $RequestExtend, $ResponseExtend } from '../types/custom';\n\nconst debug = buildDebug('verdaccio:api:package');\n\nexport default function (route: Router, auth: IAuth, storage: Storage): void {\n const can = allow(auth);\n\n route.get(\n '/:package/:version?',\n can('access'),\n async function (\n req: $RequestExtend,\n _res: $ResponseExtend,\n next: $NextFunctionVer\n ): Promise<void> {\n debug('init package by version');\n const name = req.params.package;\n let version = req.params.version;\n const write = req.query.write === 'true';\n const abbreviated = req.get('Accept') === Storage.ABBREVIATED_HEADER;\n const requestOptions = {\n protocol: req.protocol,\n headers: req.headers as any,\n // FIXME: if we migrate to req.hostname, the port is not longer included.\n host: req.host,\n remoteAddress: req.socket.remoteAddress,\n byPassCache: write,\n };\n\n try {\n const manifest = await storage.getPackageByOptions({\n name,\n uplinksLook: true,\n abbreviated,\n version,\n requestOptions,\n });\n next(manifest);\n } catch (err) {\n next(err);\n }\n }\n );\n\n route.get(\n '/:pkg/-/:filename',\n can('access'),\n async function (req: $RequestExtend, res: $ResponseExtend, next): Promise<void> {\n const { pkg, filename } = req.params;\n const abort = new AbortController();\n try {\n const stream = (await storage.getTarballNext(pkg, filename, {\n signal: abort.signal,\n // TODO: review why this param\n // enableRemote: true,\n })) as any;\n\n stream.on('content-length', (size) => {\n res.header(HEADER_TYPE.CONTENT_LENGTH, size);\n });\n\n stream.once('error', (err) => {\n res.locals.report_error(err);\n next(err);\n });\n\n req.on('abort', () => {\n debug('request aborted for %o', req.url);\n abort.abort();\n });\n\n res.header(HEADERS.CONTENT_TYPE, HEADERS.OCTET_STREAM);\n stream.pipe(res);\n } catch (err: any) {\n // console.log('catch API error request', err);\n res.locals.report_error(err);\n next(err);\n }\n }\n );\n}\n"],"mappings":";;;;;;;AAAA;;AAIA;;AACA;;AACA;;;;AAIA,MAAMA,KAAK,GAAG,IAAAC,cAAA,EAAW,uBAAX,CAAd;;AAEe,kBAAUC,KAAV,EAAyBC,IAAzB,EAAsCC,OAAtC,EAA8D;EAC3E,MAAMC,GAAG,GAAG,IAAAC,iBAAA,EAAMH,IAAN,CAAZ;EAEAD,KAAK,CAACK,GAAN,CACE,qBADF,EAEEF,GAAG,CAAC,QAAD,CAFL,EAGE,gBACEG,GADF,EAEEC,IAFF,EAGEC,IAHF,EAIiB;IACfV,KAAK,CAAC,yBAAD,CAAL;IACA,MAAMW,IAAI,GAAGH,GAAG,CAACI,MAAJ,CAAWC,OAAxB;IACA,IAAIC,OAAO,GAAGN,GAAG,CAACI,MAAJ,CAAWE,OAAzB;IACA,MAAMC,KAAK,GAAGP,GAAG,CAACQ,KAAJ,CAAUD,KAAV,KAAoB,MAAlC;;IACA,MAAME,WAAW,GAAGT,GAAG,CAACD,GAAJ,CAAQ,QAAR,MAAsBW,cAAA,CAAQC,kBAAlD;;IACA,MAAMC,cAAc,GAAG;MACrBC,QAAQ,EAAEb,GAAG,CAACa,QADO;MAErBC,OAAO,EAAEd,GAAG,CAACc,OAFQ;MAGrB;MACAC,IAAI,EAAEf,GAAG,CAACe,IAJW;MAKrBC,aAAa,EAAEhB,GAAG,CAACiB,MAAJ,CAAWD,aALL;MAMrBE,WAAW,EAAEX;IANQ,CAAvB;;IASA,IAAI;MACF,MAAMY,QAAQ,GAAG,MAAMvB,OAAO,CAACwB,mBAAR,CAA4B;QACjDjB,IADiD;QAEjDkB,WAAW,EAAE,IAFoC;QAGjDZ,WAHiD;QAIjDH,OAJiD;QAKjDM;MALiD,CAA5B,CAAvB;MAOAV,IAAI,CAACiB,QAAD,CAAJ;IACD,CATD,CASE,OAAOG,GAAP,EAAY;MACZpB,IAAI,CAACoB,GAAD,CAAJ;IACD;EACF,CAlCH;EAqCA5B,KAAK,CAACK,GAAN,CACE,mBADF,EAEEF,GAAG,CAAC,QAAD,CAFL,EAGE,gBAAgBG,GAAhB,EAAqCuB,GAArC,EAA2DrB,IAA3D,EAAgF;IAC9E,MAAM;MAAEsB,GAAF;MAAOC;IAAP,IAAoBzB,GAAG,CAACI,MAA9B;IACA,MAAMsB,KAAK,GAAG,IAAIC,eAAJ,EAAd;;IACA,IAAI;MACF,MAAMC,MAAM,GAAI,MAAMhC,OAAO,CAACiC,cAAR,CAAuBL,GAAvB,EAA4BC,QAA5B,EAAsC;QAC1DK,MAAM,EAAEJ,KAAK,CAACI,MAD4C,CAE1D;QACA;;MAH0D,CAAtC,CAAtB;MAMAF,MAAM,CAACG,EAAP,CAAU,gBAAV,EAA6BC,IAAD,IAAU;QACpCT,GAAG,CAACU,MAAJ,CAAWC,iBAAA,CAAYC,cAAvB,EAAuCH,IAAvC;MACD,CAFD;MAIAJ,MAAM,CAACQ,IAAP,CAAY,OAAZ,EAAsBd,GAAD,IAAS;QAC5BC,GAAG,CAACc,MAAJ,CAAWC,YAAX,CAAwBhB,GAAxB;QACApB,IAAI,CAACoB,GAAD,CAAJ;MACD,CAHD;MAKAtB,GAAG,CAAC+B,EAAJ,CAAO,OAAP,EAAgB,MAAM;QACpBvC,KAAK,CAAC,wBAAD,EAA2BQ,GAAG,CAACuC,GAA/B,CAAL;QACAb,KAAK,CAACA,KAAN;MACD,CAHD;MAKAH,GAAG,CAACU,MAAJ,CAAWO,aAAA,CAAQC,YAAnB,EAAiCD,aAAA,CAAQE,YAAzC;MACAd,MAAM,CAACe,IAAP,CAAYpB,GAAZ;IACD,CAvBD,CAuBE,OAAOD,GAAP,EAAiB;MACjB;MACAC,GAAG,CAACc,MAAJ,CAAWC,YAAX,CAAwBhB,GAAxB;MACApB,IAAI,CAACoB,GAAD,CAAJ;IACD;EACF,CAlCH;AAoCD"}
|
package/build/publish.d.ts
CHANGED
|
@@ -67,7 +67,7 @@ import { Storage } from '@verdaccio/store';
|
|
|
67
67
|
* specific flag for star or un start.
|
|
68
68
|
* The URL for star is similar to the unpublish (change package format)
|
|
69
69
|
*
|
|
70
|
-
* npm has no
|
|
70
|
+
* npm has no endpoint for star a package, rather mutate the metadata and acts as, the difference
|
|
71
71
|
* is the users property which is part of the payload and the body only includes
|
|
72
72
|
*
|
|
73
73
|
* {
|
package/build/publish.js
CHANGED
|
@@ -87,7 +87,7 @@ const debug = (0, _debug.default)('verdaccio:api:publish');
|
|
|
87
87
|
* specific flag for star or un start.
|
|
88
88
|
* The URL for star is similar to the unpublish (change package format)
|
|
89
89
|
*
|
|
90
|
-
* npm has no
|
|
90
|
+
* npm has no endpoint for star a package, rather mutate the metadata and acts as, the difference
|
|
91
91
|
* is the users property which is part of the payload and the body only includes
|
|
92
92
|
*
|
|
93
93
|
* {
|
|
@@ -200,13 +200,12 @@ function publishPackageNext(storage) {
|
|
|
200
200
|
return next({
|
|
201
201
|
// TODO: this could be also Package Updated based on the
|
|
202
202
|
// action, deprecate, star, publish new version, or create a package
|
|
203
|
-
// the
|
|
203
|
+
// the message some return from the method
|
|
204
204
|
ok: _core.API_MESSAGE.PKG_CREATED,
|
|
205
205
|
success: true
|
|
206
206
|
});
|
|
207
207
|
} catch (err) {
|
|
208
208
|
// TODO: review if we need the abort controller here
|
|
209
|
-
ac.abort();
|
|
210
209
|
next(err);
|
|
211
210
|
}
|
|
212
211
|
};
|
package/build/publish.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publish.js","names":["debug","buildDebug","publish","router","auth","storage","can","allow","put","media","mime","getType","expectJson","publishPackageNext","delete","req","res","next","packageName","params","package","rev","revision","logger","removePackage","status","HTTP_STATUS","CREATED","ok","API_MESSAGE","PKG_REMOVED","err","filename","removeTarball","TARBALL_REMOVED","_res","ac","AbortController","metadata","body","updateManifest","name","signal","requestOptions","host","hostname","protocol","headers","PKG_CREATED","success","abort"],"sources":["../src/publish.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { Router } from 'express';\nimport mime from 'mime';\n\nimport { IAuth } from '@verdaccio/auth';\nimport { API_MESSAGE, HTTP_STATUS } from '@verdaccio/core';\nimport { logger } from '@verdaccio/logger';\nimport { allow, expectJson, media } from '@verdaccio/middleware';\nimport { Storage } from '@verdaccio/store';\n\nimport { $NextFunctionVer, $RequestExtend, $ResponseExtend } from '../types/custom';\n\n// import star from './star';\n// import { isPublishablePackage, isRelatedToDeprecation } from './utils';\n\nconst debug = buildDebug('verdaccio:api:publish');\n\n/**\n * Publish a package / update package / un/start a package\n *\n * There are multiples scenarios here to be considered:\n *\n * 1. Publish scenario\n *\n * Publish a package consist of at least 1 step (PUT) with a metadata payload.\n * When a package is published, an _attachment property is present that contains the data\n * of the tarball.\n *\n * Example flow of publish.\n *\n * npm http fetch PUT 201 http://localhost:4873/@scope%2ftest1 9627ms\n npm info lifecycle @scope/test1@1.0.1~publish: @scope/test1@1.0.1\n npm info lifecycle @scope/test1@1.0.1~postpublish: @scope/test1@1.0.1\n + @scope/test1@1.0.1\n npm verb exit [ 0, true ]\n *\n *\n * 2. Unpublish scenario\n *\n * Unpublish consist in 3 steps.\n * 1. Try to fetch metadata -> if it fails, return 404\n * 2. Compute metadata locally (client side) and send a mutate payload excluding the version to\n * be unpublished\n * eg: if metadata reflects 1.0.1, 1.0.2 and 1.0.3, the computed metadata won't include 1.0.3.\n * 3. Once the second step has been successfully finished, delete the tarball.\n *\n * All these steps are consecutive and required, there is no transacions here, if step 3 fails,\n * metadata might get corrupted.\n *\n * Note the unpublish call will suffix in the url a /-rev/14-5d500cfce92f90fd revision number,\n * this not\n * used internally.\n *\n *\n * Example flow of unpublish.\n *\n * There are two possible flows:\n *\n * - Remove all packages (entirely)\n * eg: npm unpublish package-name@* --force\n * eg: npm unpublish package-name --force\n *\n * npm http fetch GET 200 http://localhost:4873/custom-name?write=true 1680ms\n * npm http fetch DELETE 201 http://localhost:4873/custom-name/-/test1-1.0.3.tgz/-rev/16-e11c8db282b2d992 19ms\n *\n * - Remove a specific version\n * eg: npm unpublish package-name@1.0.0 --force\n *\n * Get fresh manifest\n * npm http fetch GET 200 http://localhost:4873/custom-name?write=true 1680ms\n * Update manifest without the version to be unpublished\n * npm http fetch PUT 201 http://localhost:4873/custom-name/-rev/14-5d500cfce92f90fd 956606ms\n * Get fresh manifest (revision should be different)\n * npm http fetch GET 200 http://localhost:4873/custom-name?write=true 1601ms\n * Remove the tarball\n * npm http fetch DELETE 201 http://localhost:4873/custom-name/-/test1-1.0.3.tgz/-rev/16-e11c8db282b2d992 19ms\n * \n * 3. Star a package\n *\n * Permissions: start a package depends of the publish and unpublish permissions, there is no\n * specific flag for star or un start.\n * The URL for star is similar to the unpublish (change package format)\n *\n * npm has no enpoint for star a package, rather mutate the metadata and acts as, the difference\n * is the users property which is part of the payload and the body only includes\n *\n * {\n\t\t \"_id\": pkgName,\n\t \t\"_rev\": \"3-b0cdaefc9bdb77c8\",\n\t\t \"users\": {\n\t\t [username]: boolean value (true, false)\n\t\t }\n\t}\n *\n */\nexport default function publish(router: Router, auth: IAuth, storage: Storage): void {\n const can = allow(auth);\n // publish (update manifest) v6\n router.put(\n '/:package',\n can('publish'),\n media(mime.getType('json')),\n expectJson,\n publishPackageNext(storage)\n );\n\n // unpublish a pacakge v6\n router.put(\n '/:package/-rev/:revision',\n can('unpublish'),\n media(mime.getType('json')),\n expectJson,\n publishPackageNext(storage)\n );\n\n /**\n * Un-publishing an entire package.\n *\n * This scenario happens when the first call detect there is only one version remaining\n * in the metadata, then the client decides to DELETE the resource\n * npm http fetch GET 304 http://localhost:4873/package-name?write=true 1076ms (from cache)\n * npm http fetch DELETE 201 http://localhost:4873/package-name/-rev/18-d8ebe3020bd4ac9c 22ms\n */\n // v6\n router.delete(\n '/:package/-rev/:revision',\n can('unpublish'),\n async function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {\n const packageName = req.params.package;\n const rev = req.params.revision;\n\n logger.debug({ packageName }, `unpublishing @{packageName}`);\n try {\n await storage.removePackage(packageName, rev);\n debug('package %s unpublished', packageName);\n res.status(HTTP_STATUS.CREATED);\n return next({ ok: API_MESSAGE.PKG_REMOVED });\n } catch (err) {\n return next(err);\n }\n }\n );\n\n /*\n Remove a tarball, this happens when npm unpublish a package unique version.\n npm http fetch DELETE 201 http://localhost:4873/package-name/-rev/18-d8ebe3020bd4ac9c 22ms\n */\n router.delete(\n '/:package/-/:filename/-rev/:revision',\n can('unpublish'),\n can('publish'),\n async function (\n req: $RequestExtend,\n res: $ResponseExtend,\n next: $NextFunctionVer\n ): Promise<void> {\n const packageName = req.params.package;\n const { filename, revision } = req.params;\n\n logger.debug(\n { packageName, filename, revision },\n `removing a tarball for @{packageName}-@{tarballName}-@{revision}`\n );\n try {\n await storage.removeTarball(packageName, filename, revision);\n res.status(HTTP_STATUS.CREATED);\n\n logger.debug(\n { packageName, filename, revision },\n `success remove tarball for @{packageName}-@{tarballName}-@{revision}`\n );\n return next({ ok: API_MESSAGE.TARBALL_REMOVED });\n } catch (err) {\n return next(err);\n }\n }\n );\n}\n\nexport function publishPackageNext(storage: Storage): any {\n return async function (\n req: $RequestExtend,\n _res: $ResponseExtend,\n next: $NextFunctionVer\n ): Promise<void> {\n const ac = new AbortController();\n const packageName = req.params.package;\n const { revision } = req.params;\n const metadata = req.body;\n\n try {\n debug('publishing %s', packageName);\n await storage.updateManifest(metadata, {\n name: packageName,\n revision,\n signal: ac.signal,\n requestOptions: {\n host: req.hostname,\n protocol: req.protocol,\n // @ts-ignore\n headers: req.headers,\n },\n });\n _res.status(HTTP_STATUS.CREATED);\n\n return next({\n // TODO: this could be also Package Updated based on the\n // action, deprecate, star, publish new version, or create a package\n // the mssage some return from the method\n ok: API_MESSAGE.PKG_CREATED,\n success: true,\n });\n } catch (err: any) {\n // TODO: review if we need the abort controller here\n ac.abort();\n next(err);\n }\n };\n}\n"],"mappings":";;;;;;;;AAAA;;AAEA;;AAGA;;AACA;;AACA;;;;AAKA;AACA;AAEA,MAAMA,KAAK,GAAG,IAAAC,cAAA,EAAW,uBAAX,CAAd;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACe,SAASC,OAAT,CAAiBC,MAAjB,EAAiCC,IAAjC,EAA8CC,OAA9C,EAAsE;EACnF,MAAMC,GAAG,GAAG,IAAAC,iBAAA,EAAMH,IAAN,CAAZ,CADmF,CAEnF;;EACAD,MAAM,CAACK,GAAP,CACE,WADF,EAEEF,GAAG,CAAC,SAAD,CAFL,EAGE,IAAAG,iBAAA,EAAMC,aAAA,CAAKC,OAAL,CAAa,MAAb,CAAN,CAHF,EAIEC,sBAJF,EAKEC,kBAAkB,CAACR,OAAD,CALpB,EAHmF,CAWnF;;EACAF,MAAM,CAACK,GAAP,CACE,0BADF,EAEEF,GAAG,CAAC,WAAD,CAFL,EAGE,IAAAG,iBAAA,EAAMC,aAAA,CAAKC,OAAL,CAAa,MAAb,CAAN,CAHF,EAIEC,sBAJF,EAKEC,kBAAkB,CAACR,OAAD,CALpB;EAQA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;EACE;;EACAF,MAAM,CAACW,MAAP,CACE,0BADF,EAEER,GAAG,CAAC,WAAD,CAFL,EAGE,gBAAgBS,GAAhB,EAAqCC,GAArC,EAA2DC,IAA3D,EAAmF;IACjF,MAAMC,WAAW,GAAGH,GAAG,CAACI,MAAJ,CAAWC,OAA/B;IACA,MAAMC,GAAG,GAAGN,GAAG,CAACI,MAAJ,CAAWG,QAAvB;;IAEAC,cAAA,CAAOvB,KAAP,CAAa;MAAEkB;IAAF,CAAb,EAA+B,6BAA/B;;IACA,IAAI;MACF,MAAMb,OAAO,CAACmB,aAAR,CAAsBN,WAAtB,EAAmCG,GAAnC,CAAN;MACArB,KAAK,CAAC,wBAAD,EAA2BkB,WAA3B,CAAL;MACAF,GAAG,CAACS,MAAJ,CAAWC,iBAAA,CAAYC,OAAvB;MACA,OAAOV,IAAI,CAAC;QAAEW,EAAE,EAAEC,iBAAA,CAAYC;MAAlB,CAAD,CAAX;IACD,CALD,CAKE,OAAOC,GAAP,EAAY;MACZ,OAAOd,IAAI,CAACc,GAAD,CAAX;IACD;EACF,CAhBH;EAmBA;AACF;AACA;AACA;;EACE5B,MAAM,CAACW,MAAP,CACE,sCADF,EAEER,GAAG,CAAC,WAAD,CAFL,EAGEA,GAAG,CAAC,SAAD,CAHL,EAIE,gBACES,GADF,EAEEC,GAFF,EAGEC,IAHF,EAIiB;IACf,MAAMC,WAAW,GAAGH,GAAG,CAACI,MAAJ,CAAWC,OAA/B;IACA,MAAM;MAAEY,QAAF;MAAYV;IAAZ,IAAyBP,GAAG,CAACI,MAAnC;;IAEAI,cAAA,CAAOvB,KAAP,CACE;MAAEkB,WAAF;MAAec,QAAf;MAAyBV;IAAzB,CADF,EAEG,kEAFH;;IAIA,IAAI;MACF,MAAMjB,OAAO,CAAC4B,aAAR,CAAsBf,WAAtB,EAAmCc,QAAnC,EAA6CV,QAA7C,CAAN;MACAN,GAAG,CAACS,MAAJ,CAAWC,iBAAA,CAAYC,OAAvB;;MAEAJ,cAAA,CAAOvB,KAAP,CACE;QAAEkB,WAAF;QAAec,QAAf;QAAyBV;MAAzB,CADF,EAEG,sEAFH;;MAIA,OAAOL,IAAI,CAAC;QAAEW,EAAE,EAAEC,iBAAA,CAAYK;MAAlB,CAAD,CAAX;IACD,CATD,CASE,OAAOH,GAAP,EAAY;MACZ,OAAOd,IAAI,CAACc,GAAD,CAAX;IACD;EACF,CA5BH;AA8BD;;AAEM,SAASlB,kBAAT,CAA4BR,OAA5B,EAAmD;EACxD,OAAO,gBACLU,GADK,EAELoB,IAFK,EAGLlB,IAHK,EAIU;IACf,MAAMmB,EAAE,GAAG,IAAIC,eAAJ,EAAX;IACA,MAAMnB,WAAW,GAAGH,GAAG,CAACI,MAAJ,CAAWC,OAA/B;IACA,MAAM;MAAEE;IAAF,IAAeP,GAAG,CAACI,MAAzB;IACA,MAAMmB,QAAQ,GAAGvB,GAAG,CAACwB,IAArB;;IAEA,IAAI;MACFvC,KAAK,CAAC,eAAD,EAAkBkB,WAAlB,CAAL;MACA,MAAMb,OAAO,CAACmC,cAAR,CAAuBF,QAAvB,EAAiC;QACrCG,IAAI,EAAEvB,WAD+B;QAErCI,QAFqC;QAGrCoB,MAAM,EAAEN,EAAE,CAACM,MAH0B;QAIrCC,cAAc,EAAE;UACdC,IAAI,EAAE7B,GAAG,CAAC8B,QADI;UAEdC,QAAQ,EAAE/B,GAAG,CAAC+B,QAFA;UAGd;UACAC,OAAO,EAAEhC,GAAG,CAACgC;QAJC;MAJqB,CAAjC,CAAN;;MAWAZ,IAAI,CAACV,MAAL,CAAYC,iBAAA,CAAYC,OAAxB;;MAEA,OAAOV,IAAI,CAAC;QACV;QACA;QACA;QACAW,EAAE,EAAEC,iBAAA,CAAYmB,WAJN;QAKVC,OAAO,EAAE;MALC,CAAD,CAAX;IAOD,CAtBD,CAsBE,OAAOlB,GAAP,EAAiB;MACjB;MACAK,EAAE,CAACc,KAAH;MACAjC,IAAI,CAACc,GAAD,CAAJ;IACD;EACF,CArCD;AAsCD"}
|
|
1
|
+
{"version":3,"file":"publish.js","names":["debug","buildDebug","publish","router","auth","storage","can","allow","put","media","mime","getType","expectJson","publishPackageNext","delete","req","res","next","packageName","params","package","rev","revision","logger","removePackage","status","HTTP_STATUS","CREATED","ok","API_MESSAGE","PKG_REMOVED","err","filename","removeTarball","TARBALL_REMOVED","_res","ac","AbortController","metadata","body","updateManifest","name","signal","requestOptions","host","hostname","protocol","headers","PKG_CREATED","success"],"sources":["../src/publish.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { Router } from 'express';\nimport mime from 'mime';\n\nimport { IAuth } from '@verdaccio/auth';\nimport { API_MESSAGE, HTTP_STATUS } from '@verdaccio/core';\nimport { logger } from '@verdaccio/logger';\nimport { allow, expectJson, media } from '@verdaccio/middleware';\nimport { Storage } from '@verdaccio/store';\n\nimport { $NextFunctionVer, $RequestExtend, $ResponseExtend } from '../types/custom';\n\n// import star from './star';\n// import { isPublishablePackage, isRelatedToDeprecation } from './utils';\n\nconst debug = buildDebug('verdaccio:api:publish');\n\n/**\n * Publish a package / update package / un/start a package\n *\n * There are multiples scenarios here to be considered:\n *\n * 1. Publish scenario\n *\n * Publish a package consist of at least 1 step (PUT) with a metadata payload.\n * When a package is published, an _attachment property is present that contains the data\n * of the tarball.\n *\n * Example flow of publish.\n *\n * npm http fetch PUT 201 http://localhost:4873/@scope%2ftest1 9627ms\n npm info lifecycle @scope/test1@1.0.1~publish: @scope/test1@1.0.1\n npm info lifecycle @scope/test1@1.0.1~postpublish: @scope/test1@1.0.1\n + @scope/test1@1.0.1\n npm verb exit [ 0, true ]\n *\n *\n * 2. Unpublish scenario\n *\n * Unpublish consist in 3 steps.\n * 1. Try to fetch metadata -> if it fails, return 404\n * 2. Compute metadata locally (client side) and send a mutate payload excluding the version to\n * be unpublished\n * eg: if metadata reflects 1.0.1, 1.0.2 and 1.0.3, the computed metadata won't include 1.0.3.\n * 3. Once the second step has been successfully finished, delete the tarball.\n *\n * All these steps are consecutive and required, there is no transacions here, if step 3 fails,\n * metadata might get corrupted.\n *\n * Note the unpublish call will suffix in the url a /-rev/14-5d500cfce92f90fd revision number,\n * this not\n * used internally.\n *\n *\n * Example flow of unpublish.\n *\n * There are two possible flows:\n *\n * - Remove all packages (entirely)\n * eg: npm unpublish package-name@* --force\n * eg: npm unpublish package-name --force\n *\n * npm http fetch GET 200 http://localhost:4873/custom-name?write=true 1680ms\n * npm http fetch DELETE 201 http://localhost:4873/custom-name/-/test1-1.0.3.tgz/-rev/16-e11c8db282b2d992 19ms\n *\n * - Remove a specific version\n * eg: npm unpublish package-name@1.0.0 --force\n *\n * Get fresh manifest\n * npm http fetch GET 200 http://localhost:4873/custom-name?write=true 1680ms\n * Update manifest without the version to be unpublished\n * npm http fetch PUT 201 http://localhost:4873/custom-name/-rev/14-5d500cfce92f90fd 956606ms\n * Get fresh manifest (revision should be different)\n * npm http fetch GET 200 http://localhost:4873/custom-name?write=true 1601ms\n * Remove the tarball\n * npm http fetch DELETE 201 http://localhost:4873/custom-name/-/test1-1.0.3.tgz/-rev/16-e11c8db282b2d992 19ms\n * \n * 3. Star a package\n *\n * Permissions: start a package depends of the publish and unpublish permissions, there is no\n * specific flag for star or un start.\n * The URL for star is similar to the unpublish (change package format)\n *\n * npm has no endpoint for star a package, rather mutate the metadata and acts as, the difference\n * is the users property which is part of the payload and the body only includes\n *\n * {\n\t\t \"_id\": pkgName,\n\t \t\"_rev\": \"3-b0cdaefc9bdb77c8\",\n\t\t \"users\": {\n\t\t [username]: boolean value (true, false)\n\t\t }\n\t}\n *\n */\nexport default function publish(router: Router, auth: IAuth, storage: Storage): void {\n const can = allow(auth);\n // publish (update manifest) v6\n router.put(\n '/:package',\n can('publish'),\n media(mime.getType('json')),\n expectJson,\n publishPackageNext(storage)\n );\n\n // unpublish a pacakge v6\n router.put(\n '/:package/-rev/:revision',\n can('unpublish'),\n media(mime.getType('json')),\n expectJson,\n publishPackageNext(storage)\n );\n\n /**\n * Un-publishing an entire package.\n *\n * This scenario happens when the first call detect there is only one version remaining\n * in the metadata, then the client decides to DELETE the resource\n * npm http fetch GET 304 http://localhost:4873/package-name?write=true 1076ms (from cache)\n * npm http fetch DELETE 201 http://localhost:4873/package-name/-rev/18-d8ebe3020bd4ac9c 22ms\n */\n // v6\n router.delete(\n '/:package/-rev/:revision',\n can('unpublish'),\n async function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {\n const packageName = req.params.package;\n const rev = req.params.revision;\n\n logger.debug({ packageName }, `unpublishing @{packageName}`);\n try {\n await storage.removePackage(packageName, rev);\n debug('package %s unpublished', packageName);\n res.status(HTTP_STATUS.CREATED);\n return next({ ok: API_MESSAGE.PKG_REMOVED });\n } catch (err) {\n return next(err);\n }\n }\n );\n\n /*\n Remove a tarball, this happens when npm unpublish a package unique version.\n npm http fetch DELETE 201 http://localhost:4873/package-name/-rev/18-d8ebe3020bd4ac9c 22ms\n */\n router.delete(\n '/:package/-/:filename/-rev/:revision',\n can('unpublish'),\n can('publish'),\n async function (\n req: $RequestExtend,\n res: $ResponseExtend,\n next: $NextFunctionVer\n ): Promise<void> {\n const packageName = req.params.package;\n const { filename, revision } = req.params;\n\n logger.debug(\n { packageName, filename, revision },\n `removing a tarball for @{packageName}-@{tarballName}-@{revision}`\n );\n try {\n await storage.removeTarball(packageName, filename, revision);\n res.status(HTTP_STATUS.CREATED);\n\n logger.debug(\n { packageName, filename, revision },\n `success remove tarball for @{packageName}-@{tarballName}-@{revision}`\n );\n return next({ ok: API_MESSAGE.TARBALL_REMOVED });\n } catch (err) {\n return next(err);\n }\n }\n );\n}\n\nexport function publishPackageNext(storage: Storage): any {\n return async function (\n req: $RequestExtend,\n _res: $ResponseExtend,\n next: $NextFunctionVer\n ): Promise<void> {\n const ac = new AbortController();\n const packageName = req.params.package;\n const { revision } = req.params;\n const metadata = req.body;\n\n try {\n debug('publishing %s', packageName);\n await storage.updateManifest(metadata, {\n name: packageName,\n revision,\n signal: ac.signal,\n requestOptions: {\n host: req.hostname,\n protocol: req.protocol,\n // @ts-ignore\n headers: req.headers,\n },\n });\n _res.status(HTTP_STATUS.CREATED);\n\n return next({\n // TODO: this could be also Package Updated based on the\n // action, deprecate, star, publish new version, or create a package\n // the message some return from the method\n ok: API_MESSAGE.PKG_CREATED,\n success: true,\n });\n } catch (err: any) {\n // TODO: review if we need the abort controller here\n next(err);\n }\n };\n}\n"],"mappings":";;;;;;;;AAAA;;AAEA;;AAGA;;AACA;;AACA;;;;AAKA;AACA;AAEA,MAAMA,KAAK,GAAG,IAAAC,cAAA,EAAW,uBAAX,CAAd;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACe,SAASC,OAAT,CAAiBC,MAAjB,EAAiCC,IAAjC,EAA8CC,OAA9C,EAAsE;EACnF,MAAMC,GAAG,GAAG,IAAAC,iBAAA,EAAMH,IAAN,CAAZ,CADmF,CAEnF;;EACAD,MAAM,CAACK,GAAP,CACE,WADF,EAEEF,GAAG,CAAC,SAAD,CAFL,EAGE,IAAAG,iBAAA,EAAMC,aAAA,CAAKC,OAAL,CAAa,MAAb,CAAN,CAHF,EAIEC,sBAJF,EAKEC,kBAAkB,CAACR,OAAD,CALpB,EAHmF,CAWnF;;EACAF,MAAM,CAACK,GAAP,CACE,0BADF,EAEEF,GAAG,CAAC,WAAD,CAFL,EAGE,IAAAG,iBAAA,EAAMC,aAAA,CAAKC,OAAL,CAAa,MAAb,CAAN,CAHF,EAIEC,sBAJF,EAKEC,kBAAkB,CAACR,OAAD,CALpB;EAQA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;EACE;;EACAF,MAAM,CAACW,MAAP,CACE,0BADF,EAEER,GAAG,CAAC,WAAD,CAFL,EAGE,gBAAgBS,GAAhB,EAAqCC,GAArC,EAA2DC,IAA3D,EAAmF;IACjF,MAAMC,WAAW,GAAGH,GAAG,CAACI,MAAJ,CAAWC,OAA/B;IACA,MAAMC,GAAG,GAAGN,GAAG,CAACI,MAAJ,CAAWG,QAAvB;;IAEAC,cAAA,CAAOvB,KAAP,CAAa;MAAEkB;IAAF,CAAb,EAA+B,6BAA/B;;IACA,IAAI;MACF,MAAMb,OAAO,CAACmB,aAAR,CAAsBN,WAAtB,EAAmCG,GAAnC,CAAN;MACArB,KAAK,CAAC,wBAAD,EAA2BkB,WAA3B,CAAL;MACAF,GAAG,CAACS,MAAJ,CAAWC,iBAAA,CAAYC,OAAvB;MACA,OAAOV,IAAI,CAAC;QAAEW,EAAE,EAAEC,iBAAA,CAAYC;MAAlB,CAAD,CAAX;IACD,CALD,CAKE,OAAOC,GAAP,EAAY;MACZ,OAAOd,IAAI,CAACc,GAAD,CAAX;IACD;EACF,CAhBH;EAmBA;AACF;AACA;AACA;;EACE5B,MAAM,CAACW,MAAP,CACE,sCADF,EAEER,GAAG,CAAC,WAAD,CAFL,EAGEA,GAAG,CAAC,SAAD,CAHL,EAIE,gBACES,GADF,EAEEC,GAFF,EAGEC,IAHF,EAIiB;IACf,MAAMC,WAAW,GAAGH,GAAG,CAACI,MAAJ,CAAWC,OAA/B;IACA,MAAM;MAAEY,QAAF;MAAYV;IAAZ,IAAyBP,GAAG,CAACI,MAAnC;;IAEAI,cAAA,CAAOvB,KAAP,CACE;MAAEkB,WAAF;MAAec,QAAf;MAAyBV;IAAzB,CADF,EAEG,kEAFH;;IAIA,IAAI;MACF,MAAMjB,OAAO,CAAC4B,aAAR,CAAsBf,WAAtB,EAAmCc,QAAnC,EAA6CV,QAA7C,CAAN;MACAN,GAAG,CAACS,MAAJ,CAAWC,iBAAA,CAAYC,OAAvB;;MAEAJ,cAAA,CAAOvB,KAAP,CACE;QAAEkB,WAAF;QAAec,QAAf;QAAyBV;MAAzB,CADF,EAEG,sEAFH;;MAIA,OAAOL,IAAI,CAAC;QAAEW,EAAE,EAAEC,iBAAA,CAAYK;MAAlB,CAAD,CAAX;IACD,CATD,CASE,OAAOH,GAAP,EAAY;MACZ,OAAOd,IAAI,CAACc,GAAD,CAAX;IACD;EACF,CA5BH;AA8BD;;AAEM,SAASlB,kBAAT,CAA4BR,OAA5B,EAAmD;EACxD,OAAO,gBACLU,GADK,EAELoB,IAFK,EAGLlB,IAHK,EAIU;IACf,MAAMmB,EAAE,GAAG,IAAIC,eAAJ,EAAX;IACA,MAAMnB,WAAW,GAAGH,GAAG,CAACI,MAAJ,CAAWC,OAA/B;IACA,MAAM;MAAEE;IAAF,IAAeP,GAAG,CAACI,MAAzB;IACA,MAAMmB,QAAQ,GAAGvB,GAAG,CAACwB,IAArB;;IAEA,IAAI;MACFvC,KAAK,CAAC,eAAD,EAAkBkB,WAAlB,CAAL;MACA,MAAMb,OAAO,CAACmC,cAAR,CAAuBF,QAAvB,EAAiC;QACrCG,IAAI,EAAEvB,WAD+B;QAErCI,QAFqC;QAGrCoB,MAAM,EAAEN,EAAE,CAACM,MAH0B;QAIrCC,cAAc,EAAE;UACdC,IAAI,EAAE7B,GAAG,CAAC8B,QADI;UAEdC,QAAQ,EAAE/B,GAAG,CAAC+B,QAFA;UAGd;UACAC,OAAO,EAAEhC,GAAG,CAACgC;QAJC;MAJqB,CAAjC,CAAN;;MAWAZ,IAAI,CAACV,MAAL,CAAYC,iBAAA,CAAYC,OAAxB;;MAEA,OAAOV,IAAI,CAAC;QACV;QACA;QACA;QACAW,EAAE,EAAEC,iBAAA,CAAYmB,WAJN;QAKVC,OAAO,EAAE;MALC,CAAD,CAAX;IAOD,CAtBD,CAsBE,OAAOlB,GAAP,EAAiB;MACjB;MACAd,IAAI,CAACc,GAAD,CAAJ;IACD;EACF,CApCD;AAqCD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@verdaccio/api",
|
|
3
|
-
"version": "6.0.0-6-next.
|
|
3
|
+
"version": "6.0.0-6-next.29",
|
|
4
4
|
"description": "loaders logic",
|
|
5
5
|
"main": "./build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -30,13 +30,13 @@
|
|
|
30
30
|
},
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@verdaccio/auth": "6.0.0-6-next.
|
|
34
|
-
"@verdaccio/config": "6.0.0-6-next.
|
|
35
|
-
"@verdaccio/core": "6.0.0-6-next.
|
|
36
|
-
"@verdaccio/logger": "6.0.0-6-next.
|
|
37
|
-
"@verdaccio/middleware": "6.0.0-6-next.
|
|
38
|
-
"@verdaccio/store": "6.0.0-6-next.
|
|
39
|
-
"@verdaccio/utils": "6.0.0-6-next.
|
|
33
|
+
"@verdaccio/auth": "6.0.0-6-next.25",
|
|
34
|
+
"@verdaccio/config": "6.0.0-6-next.17",
|
|
35
|
+
"@verdaccio/core": "6.0.0-6-next.8",
|
|
36
|
+
"@verdaccio/logger": "6.0.0-6-next.14",
|
|
37
|
+
"@verdaccio/middleware": "6.0.0-6-next.25",
|
|
38
|
+
"@verdaccio/store": "6.0.0-6-next.26",
|
|
39
|
+
"@verdaccio/utils": "6.0.0-6-next.14",
|
|
40
40
|
"abortcontroller-polyfill": "1.7.3",
|
|
41
41
|
"cookies": "0.8.0",
|
|
42
42
|
"debug": "4.3.4",
|
|
@@ -48,9 +48,9 @@
|
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@types/node": "16.11.56",
|
|
51
|
-
"@verdaccio/server": "6.0.0-6-next.
|
|
52
|
-
"@verdaccio/types": "11.0.0-6-next.
|
|
53
|
-
"@verdaccio/test-helper": "1.1.0-6-next.
|
|
51
|
+
"@verdaccio/server": "6.0.0-6-next.35",
|
|
52
|
+
"@verdaccio/types": "11.0.0-6-next.16",
|
|
53
|
+
"@verdaccio/test-helper": "1.1.0-6-next.4",
|
|
54
54
|
"supertest": "6.2.4",
|
|
55
55
|
"nock": "13.2.9",
|
|
56
56
|
"mockdate": "3.0.5"
|
package/src/package.ts
CHANGED
package/src/publish.ts
CHANGED
|
@@ -81,7 +81,7 @@ const debug = buildDebug('verdaccio:api:publish');
|
|
|
81
81
|
* specific flag for star or un start.
|
|
82
82
|
* The URL for star is similar to the unpublish (change package format)
|
|
83
83
|
*
|
|
84
|
-
* npm has no
|
|
84
|
+
* npm has no endpoint for star a package, rather mutate the metadata and acts as, the difference
|
|
85
85
|
* is the users property which is part of the payload and the body only includes
|
|
86
86
|
*
|
|
87
87
|
* {
|
|
@@ -206,13 +206,12 @@ export function publishPackageNext(storage: Storage): any {
|
|
|
206
206
|
return next({
|
|
207
207
|
// TODO: this could be also Package Updated based on the
|
|
208
208
|
// action, deprecate, star, publish new version, or create a package
|
|
209
|
-
// the
|
|
209
|
+
// the message some return from the method
|
|
210
210
|
ok: API_MESSAGE.PKG_CREATED,
|
|
211
211
|
success: true,
|
|
212
212
|
});
|
|
213
213
|
} catch (err: any) {
|
|
214
214
|
// TODO: review if we need the abort controller here
|
|
215
|
-
ac.abort();
|
|
216
215
|
next(err);
|
|
217
216
|
}
|
|
218
217
|
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
auth:
|
|
2
|
+
htpasswd:
|
|
3
|
+
file: ./htpasswd-publish-proxy
|
|
4
|
+
web:
|
|
5
|
+
enable: true
|
|
6
|
+
title: verdaccio
|
|
7
|
+
|
|
8
|
+
uplinks:
|
|
9
|
+
npmjs:
|
|
10
|
+
url: https://registry.npmjs.org/
|
|
11
|
+
|
|
12
|
+
log: { type: stdout, format: pretty, level: trace }
|
|
13
|
+
|
|
14
|
+
packages:
|
|
15
|
+
'@*/*':
|
|
16
|
+
access: $all
|
|
17
|
+
publish: $anonymous
|
|
18
|
+
unpublish: $anonymous
|
|
19
|
+
proxy: npmjs
|
|
20
|
+
'**':
|
|
21
|
+
access: $all
|
|
22
|
+
publish: $anonymous
|
|
23
|
+
unpublish: $anonymous
|
|
24
|
+
proxy: npmjs
|
|
25
|
+
|
|
26
|
+
_debug: true
|
|
@@ -6,64 +6,100 @@ import { Storage } from '@verdaccio/store';
|
|
|
6
6
|
import { initializeServer, publishVersion } from './_helper';
|
|
7
7
|
|
|
8
8
|
describe('package', () => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
test.each([['foo'], ['@scope/foo']])('should return a foo private package', async (pkg) => {
|
|
15
|
-
await publishVersion(app, pkg, '1.0.0');
|
|
16
|
-
const response = await supertest(app)
|
|
17
|
-
.get(`/${pkg}`)
|
|
18
|
-
.set(HEADERS.ACCEPT, HEADERS.JSON)
|
|
19
|
-
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
|
20
|
-
.expect(HTTP_STATUS.OK);
|
|
21
|
-
expect(response.body.name).toEqual(pkg);
|
|
22
|
-
});
|
|
9
|
+
describe('get tarball', () => {
|
|
10
|
+
let app;
|
|
11
|
+
beforeEach(async () => {
|
|
12
|
+
app = await initializeServer('package.yaml');
|
|
13
|
+
});
|
|
23
14
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
15
|
+
test.each([
|
|
16
|
+
['foo', 'foo-1.0.0.tgz'],
|
|
17
|
+
['@scope/foo', 'foo-1.0.0.tgz'],
|
|
18
|
+
])('should return a file tarball', async (pkg, fileName) => {
|
|
27
19
|
await publishVersion(app, pkg, '1.0.0');
|
|
28
20
|
const response = await supertest(app)
|
|
29
|
-
.get(`/${pkg}`)
|
|
21
|
+
.get(`/${pkg}/-/${fileName}`)
|
|
30
22
|
.set(HEADERS.ACCEPT, HEADERS.JSON)
|
|
31
|
-
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.
|
|
23
|
+
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.OCTET_STREAM)
|
|
32
24
|
.expect(HTTP_STATUS.OK);
|
|
33
|
-
expect(response.body.
|
|
34
|
-
}
|
|
35
|
-
);
|
|
25
|
+
expect(Buffer.from(response.body).toString('utf8')).toBeDefined();
|
|
26
|
+
});
|
|
36
27
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
28
|
+
test.each([
|
|
29
|
+
['foo', 'foo-1.0.0.tgz'],
|
|
30
|
+
['@scope/foo', 'foo-1.0.0.tgz'],
|
|
31
|
+
])('should fails if tarball does not exist', async (pkg, fileName) => {
|
|
32
|
+
await publishVersion(app, pkg, '1.0.1');
|
|
33
|
+
return await supertest(app)
|
|
34
|
+
.get(`/${pkg}/-/${fileName}`)
|
|
43
35
|
.set(HEADERS.ACCEPT, HEADERS.JSON)
|
|
44
|
-
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.
|
|
45
|
-
.expect(HTTP_STATUS.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
36
|
+
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.OCTET_STREAM)
|
|
37
|
+
.expect(HTTP_STATUS.NOT_FOUND);
|
|
38
|
+
});
|
|
39
|
+
test.todo('check content length file header');
|
|
40
|
+
test.todo('fails on file was aborted');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe('get package', () => {
|
|
44
|
+
let app;
|
|
45
|
+
beforeEach(async () => {
|
|
46
|
+
app = await initializeServer('package.yaml');
|
|
47
|
+
});
|
|
49
48
|
|
|
50
|
-
|
|
51
|
-
'should return abbreviated local manifest',
|
|
52
|
-
async (pkg) => {
|
|
49
|
+
test.each([['foo'], ['@scope/foo']])('should return a foo private package', async (pkg) => {
|
|
53
50
|
await publishVersion(app, pkg, '1.0.0');
|
|
54
51
|
const response = await supertest(app)
|
|
55
52
|
.get(`/${pkg}`)
|
|
56
53
|
.set(HEADERS.ACCEPT, HEADERS.JSON)
|
|
57
|
-
.set(HEADERS.ACCEPT, Storage.ABBREVIATED_HEADER)
|
|
58
54
|
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
|
59
55
|
.expect(HTTP_STATUS.OK);
|
|
60
56
|
expect(response.body.name).toEqual(pkg);
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test.each([['foo'], ['@scope/foo']])(
|
|
60
|
+
'should return a foo private package by version',
|
|
61
|
+
async (pkg) => {
|
|
62
|
+
await publishVersion(app, pkg, '1.0.0');
|
|
63
|
+
const response = await supertest(app)
|
|
64
|
+
.get(`/${pkg}`)
|
|
65
|
+
.set(HEADERS.ACCEPT, HEADERS.JSON)
|
|
66
|
+
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
|
67
|
+
.expect(HTTP_STATUS.OK);
|
|
68
|
+
expect(response.body.name).toEqual(pkg);
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
test.each([['foo'], ['@scope/foo']])(
|
|
73
|
+
'should return a foo private package by version',
|
|
74
|
+
async (pkg) => {
|
|
75
|
+
await publishVersion(app, pkg, '1.0.0');
|
|
76
|
+
const response = await supertest(app)
|
|
77
|
+
.get(`/${pkg}`)
|
|
78
|
+
.set(HEADERS.ACCEPT, HEADERS.JSON)
|
|
79
|
+
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
|
80
|
+
.expect(HTTP_STATUS.OK);
|
|
81
|
+
expect(response.body.name).toEqual(pkg);
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
test.each([['foo-abbreviated'], ['@scope/foo-abbreviated']])(
|
|
86
|
+
'should return abbreviated local manifest',
|
|
87
|
+
async (pkg) => {
|
|
88
|
+
await publishVersion(app, pkg, '1.0.0');
|
|
89
|
+
const response = await supertest(app)
|
|
90
|
+
.get(`/${pkg}`)
|
|
91
|
+
.set(HEADERS.ACCEPT, HEADERS.JSON)
|
|
92
|
+
.set(HEADERS.ACCEPT, Storage.ABBREVIATED_HEADER)
|
|
93
|
+
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
|
94
|
+
.expect(HTTP_STATUS.OK);
|
|
95
|
+
expect(response.body.name).toEqual(pkg);
|
|
96
|
+
expect(response.body.time).toBeDefined();
|
|
97
|
+
expect(response.body.modified).toBeDefined();
|
|
98
|
+
expect(response.body[DIST_TAGS]).toEqual({ latest: '1.0.0' });
|
|
99
|
+
expect(response.body.readme).not.toBeDefined();
|
|
100
|
+
expect(response.body._rev).not.toBeDefined();
|
|
101
|
+
expect(response.body.users).not.toBeDefined();
|
|
102
|
+
}
|
|
103
|
+
);
|
|
104
|
+
});
|
|
69
105
|
});
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
import nock from 'nock';
|
|
2
|
+
import { basename } from 'path';
|
|
1
3
|
import supertest from 'supertest';
|
|
2
4
|
|
|
3
5
|
import { HTTP_STATUS } from '@verdaccio/core';
|
|
4
6
|
import { API_ERROR, API_MESSAGE, HEADERS, HEADER_TYPE } from '@verdaccio/core';
|
|
5
|
-
import { generatePackageMetadata } from '@verdaccio/test-helper';
|
|
7
|
+
import { generatePackageMetadata, generateRemotePackageMetadata } from '@verdaccio/test-helper';
|
|
6
8
|
|
|
7
9
|
import { $RequestExtend, $ResponseExtend } from '../../types/custom';
|
|
8
|
-
import { initializeServer, publishVersion } from './_helper';
|
|
10
|
+
import { getPackage, initializeServer, publishVersion } from './_helper';
|
|
9
11
|
|
|
10
12
|
const mockApiJWTmiddleware = jest.fn(
|
|
11
13
|
() =>
|
|
@@ -33,31 +35,8 @@ jest.mock('@verdaccio/auth', () => ({
|
|
|
33
35
|
},
|
|
34
36
|
}));
|
|
35
37
|
|
|
36
|
-
// const mockStorage = jest.fn(() => {
|
|
37
|
-
// const { Storage } = jest.requireActual('@verdaccio/store');
|
|
38
|
-
// return {
|
|
39
|
-
// Storage: class extends Storage {
|
|
40
|
-
// addPackage(name, metadata, cb) {
|
|
41
|
-
// super.addPackage(name, metadata, cb);
|
|
42
|
-
// }
|
|
43
|
-
// }
|
|
44
|
-
// };
|
|
45
|
-
// });
|
|
46
|
-
|
|
47
|
-
// jest.mock('@verdaccio/store', () => {
|
|
48
|
-
// const { Storage } = jest.requireActual('@verdaccio/store');
|
|
49
|
-
// return ({
|
|
50
|
-
// Storage: class extends Storage {
|
|
51
|
-
// addPackage(name, metadata, cb) {
|
|
52
|
-
// // super.addPackage(name, metadata, cb);
|
|
53
|
-
// return mockStorage(name, metadata, cb);
|
|
54
|
-
// }
|
|
55
|
-
// }
|
|
56
|
-
// })
|
|
57
|
-
// });
|
|
58
|
-
|
|
59
38
|
describe('publish', () => {
|
|
60
|
-
describe('handle
|
|
39
|
+
describe('handle errors', () => {
|
|
61
40
|
const pkgName = 'test';
|
|
62
41
|
const pkgMetadata = generatePackageMetadata(pkgName, '1.0.0');
|
|
63
42
|
test('should fail on publish a bad _attachments package', async () => {
|
|
@@ -101,134 +80,179 @@ describe('publish', () => {
|
|
|
101
80
|
});
|
|
102
81
|
|
|
103
82
|
describe('publish a package', () => {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
83
|
+
describe('no proxies setup', () => {
|
|
84
|
+
test.each([['foo', '@scope/foo']])('should publish a package', async (pkgName) => {
|
|
85
|
+
const app = await initializeServer('publish.yaml');
|
|
86
|
+
return new Promise((resolve) => {
|
|
87
|
+
publishVersion(app, pkgName, '1.0.0')
|
|
88
|
+
.expect(HTTP_STATUS.CREATED)
|
|
89
|
+
.then((response) => {
|
|
90
|
+
expect(response.body.ok).toEqual(API_MESSAGE.PKG_CREATED);
|
|
91
|
+
resolve(response);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
113
94
|
});
|
|
114
|
-
});
|
|
115
95
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
96
|
+
test.each([['foo', '@scope/foo']])('should publish a new package', async (pkgName) => {
|
|
97
|
+
const pkgMetadata = generatePackageMetadata(pkgName, '1.0.0');
|
|
98
|
+
const app = await initializeServer('publish.yaml');
|
|
99
|
+
return new Promise((resolve) => {
|
|
100
|
+
supertest(app)
|
|
101
|
+
.put(`/${encodeURIComponent(pkgName)}`)
|
|
102
|
+
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
|
|
103
|
+
.send(JSON.stringify(Object.assign({}, pkgMetadata)))
|
|
104
|
+
.set('accept', HEADERS.GZIP)
|
|
105
|
+
.expect(HTTP_STATUS.CREATED)
|
|
106
|
+
.then((response) => {
|
|
107
|
+
expect(response.body.ok).toEqual(API_MESSAGE.PKG_CREATED);
|
|
108
|
+
resolve(response);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
131
111
|
});
|
|
112
|
+
|
|
113
|
+
test('should publish a new package with no readme', async () => {
|
|
114
|
+
const pkgName = 'test';
|
|
115
|
+
const pkgMetadata = generatePackageMetadata(pkgName, '1.0.0');
|
|
116
|
+
const app = await initializeServer('publish.yaml');
|
|
117
|
+
return new Promise((resolve) => {
|
|
118
|
+
supertest(app)
|
|
119
|
+
.put(`/${encodeURIComponent(pkgName)}`)
|
|
120
|
+
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
|
|
121
|
+
.send(
|
|
122
|
+
JSON.stringify(
|
|
123
|
+
Object.assign({}, pkgMetadata, {
|
|
124
|
+
versions: {
|
|
125
|
+
['1.0.0']: {
|
|
126
|
+
readme: null,
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
})
|
|
130
|
+
)
|
|
131
|
+
)
|
|
132
|
+
.set('accept', HEADERS.GZIP)
|
|
133
|
+
.expect(HTTP_STATUS.CREATED)
|
|
134
|
+
.then((response) => {
|
|
135
|
+
expect(response.body.ok).toEqual(API_MESSAGE.PKG_CREATED);
|
|
136
|
+
resolve(response);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
describe('proxies setup', () => {
|
|
142
|
+
test.each([['foo', '@scope%2Ffoo']])(
|
|
143
|
+
'should publish a a patch package that already exist on a remote',
|
|
144
|
+
async (pkgName) => {
|
|
145
|
+
const upstreamManifest = generateRemotePackageMetadata(
|
|
146
|
+
pkgName,
|
|
147
|
+
'1.0.0',
|
|
148
|
+
'https://registry.npmjs.org',
|
|
149
|
+
['1.0.1', '1.0.2', '1.0.3']
|
|
150
|
+
);
|
|
151
|
+
nock('https://registry.npmjs.org').get(`/${pkgName}`).reply(200, upstreamManifest);
|
|
152
|
+
const app = await initializeServer('publish-proxy.yaml');
|
|
153
|
+
const manifest = await getPackage(app, '', decodeURIComponent(pkgName));
|
|
154
|
+
expect(manifest.body.name).toEqual(decodeURIComponent(pkgName));
|
|
155
|
+
const response = await publishVersion(
|
|
156
|
+
app,
|
|
157
|
+
decodeURIComponent(pkgName),
|
|
158
|
+
'1.0.1-patch'
|
|
159
|
+
).expect(HTTP_STATUS.CREATED);
|
|
160
|
+
expect(response.body.ok).toEqual(API_MESSAGE.PKG_CREATED);
|
|
161
|
+
const response2 = await publishVersion(
|
|
162
|
+
app,
|
|
163
|
+
decodeURIComponent(pkgName),
|
|
164
|
+
'1.0.2-patch'
|
|
165
|
+
).expect(HTTP_STATUS.CREATED);
|
|
166
|
+
expect(response2.body.ok).toEqual(API_MESSAGE.PKG_CREATED);
|
|
167
|
+
}
|
|
168
|
+
);
|
|
132
169
|
});
|
|
170
|
+
});
|
|
133
171
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
172
|
+
test.each([['foo', '@scope/foo']])(
|
|
173
|
+
'should fails on publish a duplicated package',
|
|
174
|
+
async (pkgName) => {
|
|
137
175
|
const app = await initializeServer('publish.yaml');
|
|
176
|
+
await publishVersion(app, pkgName, '1.0.0');
|
|
138
177
|
return new Promise((resolve) => {
|
|
139
|
-
|
|
140
|
-
.
|
|
141
|
-
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
|
|
142
|
-
.send(
|
|
143
|
-
JSON.stringify(
|
|
144
|
-
Object.assign({}, pkgMetadata, {
|
|
145
|
-
versions: {
|
|
146
|
-
['1.0.0']: {
|
|
147
|
-
readme: null,
|
|
148
|
-
},
|
|
149
|
-
},
|
|
150
|
-
})
|
|
151
|
-
)
|
|
152
|
-
)
|
|
153
|
-
.set('accept', HEADERS.GZIP)
|
|
154
|
-
.expect(HTTP_STATUS.CREATED)
|
|
178
|
+
publishVersion(app, pkgName, '1.0.0')
|
|
179
|
+
.expect(HTTP_STATUS.CONFLICT)
|
|
155
180
|
.then((response) => {
|
|
156
|
-
expect(response.body.
|
|
181
|
+
expect(response.body.error).toEqual(API_ERROR.PACKAGE_EXIST);
|
|
157
182
|
resolve(response);
|
|
158
183
|
});
|
|
159
184
|
});
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
test('should fails on publish a duplicated package', async () => {
|
|
164
|
-
const app = await initializeServer('publish.yaml');
|
|
165
|
-
await publishVersion(app, 'foo', '1.0.0');
|
|
166
|
-
return new Promise((resolve) => {
|
|
167
|
-
publishVersion(app, 'foo', '1.0.0')
|
|
168
|
-
.expect(HTTP_STATUS.CONFLICT)
|
|
169
|
-
.then((response) => {
|
|
170
|
-
expect(response.body.error).toEqual(API_ERROR.PACKAGE_EXIST);
|
|
171
|
-
resolve(response);
|
|
172
|
-
});
|
|
173
|
-
});
|
|
174
|
-
});
|
|
185
|
+
}
|
|
186
|
+
);
|
|
175
187
|
|
|
176
188
|
describe('unpublish a package', () => {
|
|
177
|
-
test('should unpublish entirely a package', async () => {
|
|
189
|
+
test.each([['foo', '@scope/foo']])('should unpublish entirely a package', async (pkgName) => {
|
|
178
190
|
const app = await initializeServer('publish.yaml');
|
|
179
|
-
await publishVersion(app,
|
|
191
|
+
await publishVersion(app, pkgName, '1.0.0');
|
|
180
192
|
const response = await supertest(app)
|
|
181
193
|
// FIXME: should be filtered by revision to avoid
|
|
182
194
|
// conflicts
|
|
183
|
-
.delete(`/${encodeURIComponent(
|
|
195
|
+
.delete(`/${encodeURIComponent(pkgName)}/-rev/xxx`)
|
|
184
196
|
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
|
|
185
197
|
.expect(HTTP_STATUS.CREATED);
|
|
186
198
|
expect(response.body.ok).toEqual(API_MESSAGE.PKG_REMOVED);
|
|
187
199
|
// package should be completely un published
|
|
188
200
|
await supertest(app)
|
|
189
|
-
.get(
|
|
201
|
+
.get(`/${pkgName}`)
|
|
190
202
|
.set('Accept', HEADERS.JSON)
|
|
191
203
|
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
|
192
204
|
.expect(HTTP_STATUS.NOT_FOUND);
|
|
193
205
|
});
|
|
194
206
|
|
|
195
|
-
test('
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
207
|
+
test.each([['foo', '@scope/foo']])(
|
|
208
|
+
'should fails unpublish entirely a package',
|
|
209
|
+
async (pkgName) => {
|
|
210
|
+
const app = await initializeServer('publish.yaml');
|
|
211
|
+
const response = await supertest(app)
|
|
212
|
+
.delete(`/${encodeURIComponent(pkgName)}/-rev/1cf3-fe3`)
|
|
213
|
+
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
|
|
214
|
+
.expect(HTTP_STATUS.NOT_FOUND);
|
|
215
|
+
expect(response.body.error).toEqual(API_ERROR.NO_PACKAGE);
|
|
216
|
+
}
|
|
217
|
+
);
|
|
203
218
|
|
|
204
|
-
test('
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
219
|
+
test.each([['foo', '@scope/foo']])(
|
|
220
|
+
'should fails remove a tarball of a package does not exist',
|
|
221
|
+
async (pkgName) => {
|
|
222
|
+
const app = await initializeServer('publish.yaml');
|
|
223
|
+
const response = await supertest(app)
|
|
224
|
+
.delete(`/${pkgName}/-/${basename(pkgName)}-1.0.3.tgz/-rev/revision`)
|
|
225
|
+
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
|
|
226
|
+
.expect(HTTP_STATUS.NOT_FOUND);
|
|
227
|
+
expect(response.body.error).toEqual(API_ERROR.NO_PACKAGE);
|
|
228
|
+
}
|
|
229
|
+
);
|
|
212
230
|
|
|
213
|
-
test('
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
231
|
+
test.each([['foo', '@scope/foo']])(
|
|
232
|
+
'should fails on try remove a tarball does not exist',
|
|
233
|
+
async (pkgName) => {
|
|
234
|
+
const app = await initializeServer('publish.yaml');
|
|
235
|
+
await publishVersion(app, pkgName, '1.0.0');
|
|
236
|
+
const response = await supertest(app)
|
|
237
|
+
.delete(`/${pkgName}/-/${basename(pkgName)}-1.0.3.tgz/-rev/revision`)
|
|
238
|
+
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
|
|
239
|
+
.expect(HTTP_STATUS.NOT_FOUND);
|
|
240
|
+
expect(response.body.error).toEqual(API_ERROR.NO_SUCH_FILE);
|
|
241
|
+
}
|
|
242
|
+
);
|
|
222
243
|
|
|
223
|
-
test('
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
244
|
+
test.each([['foo', '@scope/foo']])(
|
|
245
|
+
'should remove a tarball that does exist',
|
|
246
|
+
async (pkgName) => {
|
|
247
|
+
const app = await initializeServer('publish.yaml');
|
|
248
|
+
await publishVersion(app, pkgName, '1.0.0');
|
|
249
|
+
const response = await supertest(app)
|
|
250
|
+
.delete(`/${pkgName}/-/${basename(pkgName)}-1.0.0.tgz/-rev/revision`)
|
|
251
|
+
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
|
|
252
|
+
.expect(HTTP_STATUS.CREATED);
|
|
253
|
+
expect(response.body.ok).toEqual(API_MESSAGE.TARBALL_REMOVED);
|
|
254
|
+
}
|
|
255
|
+
);
|
|
232
256
|
});
|
|
233
257
|
|
|
234
258
|
describe('star a package', () => {});
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import nock from 'nock';
|
|
2
1
|
import supertest from 'supertest';
|
|
3
2
|
|
|
4
3
|
import { API_ERROR, HEADERS, HEADER_TYPE, HTTP_STATUS, TOKEN_BEARER } from '@verdaccio/core';
|
|
5
|
-
import { generateRemotePackageMetadata } from '@verdaccio/test-helper';
|
|
6
4
|
import { buildToken } from '@verdaccio/utils';
|
|
7
5
|
|
|
8
6
|
import { createUser, getPackage, initializeServer } from './_helper';
|
|
@@ -13,13 +11,6 @@ describe('token', () => {
|
|
|
13
11
|
describe('basics', () => {
|
|
14
12
|
const FAKE_TOKEN: string = buildToken(TOKEN_BEARER, 'fake');
|
|
15
13
|
test.each([['user.yaml'], ['user.jwt.yaml']])('should test add a new user', async (conf) => {
|
|
16
|
-
const upstreamManifest = generateRemotePackageMetadata(
|
|
17
|
-
'vue',
|
|
18
|
-
'1.0.0',
|
|
19
|
-
'https://registry.verdaccio.org'
|
|
20
|
-
);
|
|
21
|
-
nock('https://registry.verdaccio.org').get(`/vue`).reply(201, upstreamManifest);
|
|
22
|
-
|
|
23
14
|
const app = await initializeServer(conf);
|
|
24
15
|
const credentials = { name: 'JotaJWT', password: 'secretPass' };
|
|
25
16
|
const response = await createUser(app, credentials.name, credentials.password);
|