Compare commits

..

90 Commits

Author SHA1 Message Date
Juan Picado
3c2f5741f4 chore: update versions (6-next) (#3350)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-04 11:56:23 +02:00
Juan Picado
85413ae8b6 Update changesets.yml 2022-09-04 11:50:28 +02:00
Juan Picado
cbff8e4e31 chore: update jest major (#3351)
* chore: update jest major

* remove unused deps
2022-09-04 11:48:51 +02:00
Juan Picado
e24eb59237 Update changesets.yml 2022-09-04 11:42:46 +02:00
Juan Picado
8297e2b36e chore: remove unused dep 2022-09-04 10:49:41 +02:00
Juan Picado
020ede43f6 fix: version output with breakline (#3349) 2022-09-04 10:46:57 +02:00
renovate[bot]
dd177d7166 fix(deps): update dependency msw to v0.47.0 (#3348)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-04 10:14:14 +02:00
Juan Picado
5e53e168d4 chore: fix packages release config 2022-09-04 07:58:26 +02:00
renovate[bot]
e9ff724b68 fix(deps): update all core dependencies (master) (#3342)
* fix(deps): update all core dependencies

* Update Search.test.tsx.snap

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Juan Picado <juanpicado19@gmail.com>
2022-09-03 18:47:59 +02:00
Juan Picado
5a61cdd0cf chore: update versions (6-next) (#3341)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-02 20:52:37 +02:00
Juan Picado
b849128ded fix: handle upload scoped tarball and add new deprecations (#3340)
* chore: add local publish support

* chore: fix upload scoped tarball

* add e2e
2022-09-02 20:40:12 +02:00
verdacciobot
efa2efe531 chore: updated contributors list 2022-09-01 00:14:39 +00:00
renovate[bot]
62ef397df1 chore(deps): update actions/github-script digest to c713e51 (#3336)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-31 08:09:06 +02:00
dependabot[bot]
e8fd4daf78 chore(deps): bump actions/github-script from 6.1.1 to 6.2.0 (#3337)
Bumps [actions/github-script](https://github.com/actions/github-script) from 6.1.1 to 6.2.0.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](d50f485531...c713e510db)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-31 08:08:19 +02:00
dependabot[bot]
acc5862323 chore(deps): bump github/codeql-action from 2.1.20 to 2.1.21 (#3338)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.1.20 to 2.1.21.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](7fee4ca032...c7f292ea4f)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-31 08:08:00 +02:00
Aron Hafner
43c164efe0 docs: update config to use log property (#3339)
Update config.yaml to use log property instead of the depreciated logs

When using logs the following error occurs

```
Error: Error: the property config "logs" property is longer supported, rename to "log" and use object instead
```
2022-08-31 08:07:25 +02:00
verdacciobot
cd02e8d56a chore: updated contributors list 2022-08-29 00:14:20 +00:00
Juan Picado
5b270bdd06 Update package.json 2022-08-28 17:18:29 +02:00
Juan Picado
e06d8a0956 chore: update versions (6-next) (#3334)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-08-28 13:32:17 +02:00
Juan Picado
44b7a0f300 chore: remove website from changeset 2022-08-28 06:10:46 +02:00
Zoltan Kochan
351aeeaa88 fix(deps): @verdaccio/utils should be a prod dep of local-storage (#3333)
* fix(deps): @verdaccio/utils should be a prod dep of local-storage

* add changeset

Co-authored-by: Juan Picado <juanpicado19@gmail.com>
2022-08-28 07:44:48 +02:00
Juan Picado
3089c1c9cb chore: update versions (6-next) (#3331)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-08-27 19:33:00 +02:00
Juan Picado
d202128a06 chore: remove local packacages 2022-08-27 19:27:03 +02:00
Juan Picado
3c81bf8945 chore: update contributors script (#3332)
* chore: update script

* chore: update contributors file
2022-08-27 19:24:57 +02:00
okyanusoz
20d63dc30e ui: basic grammatical fixes in the Ukraine Message (#3330)
* Update Support.tsx

* Update Support.tsx

* chore: add changeset

Co-authored-by: Juan Picado <juanpicado19@gmail.com>
2022-08-27 19:12:35 +02:00
Juan Picado
5e22a52d9d Update changesets.yml 2022-08-27 16:25:59 +02:00
renovate[bot]
f332927f02 fix(deps): update all core dependencies (#3327)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-27 15:41:25 +02:00
github-actions[bot]
4137a96c20 chore: update versions (6-next) (#3329) 2022-08-27 15:07:19 +02:00
Juan Picado
37274e4c8d feat: implement abbreviated manifest (#3322)
* feat: implement abbreviated manifest

* chore: add time field

* chore: add abbreviated version

* chore: fix missing time

* chore: fix merge time issue

* Update jest.config.js

* add tests

* chore: add tests

* chore: add missing fields
2022-08-27 12:52:23 +02:00
Shenhe
f1527f5f20 docs: changed the deprecated installation method (#3323)
* Changed the deprecated installation method

Altered the `npm` global installation command i.e. `npm i -g` and `npm install --global` to `npm i --location=global` and `npm install --location=global` respectively. Also added methods for installing using `yarn` and `pnpm`

* Changed the deprecated installation method for `npm`

Changed the installation flag from `--global` and `-g` to `--location=global` for `npm` i.e. to `npm --location=global`

Co-authored-by: Juan Picado <juanpicado19@gmail.com>
2022-08-27 09:20:09 +02:00
Marc Bernard
a32a7e617e Update docs for cli (#3325)
- Minor corrections and additions
- Added link to possible formats for `listen` command
2022-08-26 19:53:35 +02:00
Marc Bernard
08c36e688e docs: add statement about npm security best practices (#3324)
OWASP is explicitly mentioning Verdaccio in one of their recommendations for npm security best practices. 

It's high praise so should be mentioned in a central place. If not here, you might find another page to add it.
2022-08-24 17:59:08 +02:00
Juan Picado
ba3d100b63 chore: fix format 2022-08-24 07:23:09 +02:00
Shenhe
37da9e0f61 Changed the deprecated installation method (#3321)
Altered the `npm` global installation command i.e. `npm i -g` and `npm install --global` to `npm i --location=global` and `npm install --location=global` respectively. Also added methods for installing using `yarn` and `pnpm`
2022-08-24 07:13:55 +02:00
Juan Picado
e630954923 website: restore github button front page 2022-08-22 20:46:20 +02:00
Juan Picado
4b61029718 chore: add more install notes 2022-08-22 20:31:59 +02:00
Juan Picado
13398c6ab8 update docker plugins examples 2022-08-22 18:51:04 +02:00
renovate[bot]
16f847fd7d chore(deps): pin dependencies (#3319)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-22 17:58:45 +02:00
Juan Picado
225b5235a9 update help website page 2022-08-21 15:15:40 +02:00
Juan Picado
1b5bcfeac6 Update renovate.json 2022-08-21 15:00:15 +02:00
Juan Picado
eaebffaf9e Update renovate.json 2022-08-21 14:31:43 +02:00
Juan Picado
dc4fa8e20d chore: remove unused file 2022-08-21 14:21:08 +02:00
Juan Picado
99b947a2a5 chore: clean unused code 2022-08-21 14:19:59 +02:00
Juan Picado
83c4705821 chore: migrate material ui old dep (#3318) 2022-08-21 14:15:20 +02:00
Juan Picado
3f5a1ee22a chore: update front page website (#3317)
* chore: update front page website

* Update UsedBy.tsx

* update links
2022-08-20 19:23:24 +02:00
Juan Picado
bf0f331dfc chore: remove empty website page 2022-08-20 18:20:22 +02:00
renovate[bot]
89b2b9104f fix(deps): update all linting dependencies (#3312) 2022-08-20 10:18:38 +02:00
renovate[bot]
21478f3221 fix(deps): update all core dependencies (#3298) 2022-08-20 09:28:29 +02:00
github-actions[bot]
12a05875c7 chore: update versions (6-next) (#3276)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-08-19 23:48:06 +02:00
Juan Picado
24c5d7ede5 chore: upgrade website reps (#3311) 2022-08-19 23:33:41 +02:00
Juan Picado
b179541e66 chore: remove ref to removed package 2022-08-19 21:07:26 +02:00
Juan Picado
353c9f386f chore: refactor server express tests (#3306) 2022-08-19 20:25:20 +02:00
Juan Picado
f42db638eb chore: fix missing dep on master (#3310)
* Update dist-tags.ts

* Update ci.yml

* chore: fix missing dep on master

* chore: fix missing dep on master
2022-08-19 08:03:14 +02:00
Juan Picado
a3a209b5e2 feat: upgrade to pino 8 with async logging (#3308) 2022-08-18 21:39:34 +02:00
NotWearingPants
9bff9045f8 docs: update links in ci.md (#3309) 2022-08-18 21:03:13 +02:00
verdacciobot
df7600d08a chore: updated contributors list 2022-08-18 00:12:46 +00:00
Marc Bernard
a136cefd49 Fix link to readme (#3302)
Fixes link from https://github.com/verdaccio/verdaccio/tree/master/docker-examples/v6 to this readme
2022-08-17 17:15:14 +02:00
verdacciobot
93102eacc5 chore: updated contributors list 2022-08-15 00:12:27 +00:00
verdacciobot
7d05f03525 chore: updated contributors list 2022-08-11 00:13:37 +00:00
renovate[bot]
04cc86374d fix(deps): update all linting dependencies (master) (#3296)
* fix(deps): update all linting dependencies

* chore: fix lint

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Juan Picado <juanpicado19@gmail.com>
2022-08-08 19:20:37 +02:00
NotWearingPants
bbf897d05a docs: fix formatting in packages/core/types/README (#3292)
* docs: fix formatting in packages/core/types/README

* format

Co-authored-by: Juan Picado <juanpicado19@gmail.com>
2022-08-08 18:48:42 +02:00
renovate[bot]
e21ccea3a1 fix(deps): update all core dependencies (master) (#3278)
* fix(deps): update all core dependencies

* chore: restore docusaurus

* restore versions

* fix types

* chore: fix error

* chore: update snapshots

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Juan Picado <juanpicado19@gmail.com>
2022-08-08 08:55:41 +02:00
Juan Picado
5cf041a1a5 add changeset 2022-08-08 07:40:24 +02:00
NotWearingPants
57908e24ba feat: add dist.signatures to core/types (#3294) 2022-08-08 07:29:04 +02:00
Juan Picado
00d1d2a179 chore: env variable for launch fastify (#3295)
* chore: relocate package server

* chore: relocate server packages

* Update ci.yml

* rename packages

* rename package

* chore: refactor fastify endpoints

* chore: fix types requests

* fix warnings

* chore: refactor endpoints

* refactor launch fastify

* Update package.json

* chore: update deps

* Create green-yaks-divide.md
2022-08-08 07:14:23 +02:00
NotWearingPants
8db9cf93ce docs: fix typo in CONTRIBUTING.md (#3293) 2022-08-08 06:59:58 +02:00
verdacciobot
a6c88932a2 chore: updated contributors list 2022-08-08 00:12:57 +00:00
Juan Picado
399343c6f9 chore: pin action 2022-08-04 20:34:04 +02:00
Juan Picado
6f8a2d37e6 chore: add yarn modern (2, 3, 4) to cli E2E (#3289)
* test: add more packages managers to e2e cli

* chore: remove old conf files

* add yarn modern to e2e cli

* chore: add yarn 4

* ignore binary

* fix for tests yarn 3

* chore: tests

* update website ci

* Update package.json

* chore: try yarn 3 as binary

* chore: remove unused dependency

* Update utils.ts

* Update package.json

* Update package.json

* speed up build

* Update ci.yml

* Update ci.yml

* Update website.yml

* test

* chore: reenable all tests

* chore: restore ci

* chore: clean debug code
2022-08-04 20:04:12 +02:00
verdacciobot
0773e2ee2e chore: updated contributors list 2022-08-04 00:12:58 +00:00
Juan Picado
a4c17858bf test: add more packages managers to e2e cli (#3283)
* test: add more packages managers to e2e cli

* chore: remove old conf files

* Update ci.yml
2022-08-03 08:01:27 +02:00
Juan Picado
313c71c938 remove e2e packages changeset 2022-08-03 06:50:09 +02:00
Juan Picado
8342abde70 remove e2e packages changeset 2022-08-02 22:55:29 +02:00
Juan Picado
1755840cd3 e2e cli npm 6 (#3282)
* chore: add config utility

* improve verdaccio bin location

* add new npm cli e2e tests

* add tests

* rename files
2022-08-02 22:45:16 +02:00
verdacciobot
a123775f20 chore: updated contributors list 2022-08-01 00:14:01 +00:00
Juan Picado
292c0a37fc feat!: replace deprecated request dependency by got (#3100) 2022-07-29 20:51:45 +02:00
verdacciobot
743ccff5ef chore: updated contributors list 2022-07-28 00:13:48 +00:00
verdacciobot
4afb06347a chore: updated contributors list 2022-07-25 00:13:39 +00:00
verdacciobot
bfe996735a chore: updated contributors list 2022-07-21 00:13:51 +00:00
verdacciobot
1c7eb368ee chore: updated contributors list 2022-07-18 00:12:10 +00:00
verdacciobot
09125ff004 chore: updated contributors list 2022-07-14 00:13:57 +00:00
Juan Picado
43dd445200 chore: fix update python 3 docker image 2022-07-12 22:30:06 +02:00
Snyk bot
63f8a8aa2e fix: Dockerfile to reduce vulnerabilities (#3257)
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-ALPINE315-OPENSSL-2941810
- https://snyk.io/vuln/SNYK-ALPINE315-OPENSSL-2941810
2022-07-11 07:28:37 +02:00
verdacciobot
fcbc4bb781 chore: updated contributors list 2022-07-11 00:13:30 +00:00
verdacciobot
d964353cb8 chore: updated contributors list 2022-07-07 00:14:02 +00:00
Morrain
c5a6ff89bb update logger.md (#3256) 2022-07-06 19:57:32 +02:00
verdacciobot
d7dec2695f chore: updated contributors list 2022-07-04 00:14:18 +00:00
Thomi Richards
9beb77a44e docs: small language tweak to uplinks.md. (#3252) 2022-07-01 09:24:22 +03:00
verdacciobot
cfcdbf6282 chore: updated contributors list 2022-06-30 00:13:03 +00:00
verdacciobot
f75ddf8231 chore: updated contributors list 2022-06-27 00:13:28 +00:00
758 changed files with 31323 additions and 135436 deletions

View File

@@ -0,0 +1,52 @@
---
'@verdaccio/api': major
'@verdaccio/auth': major
'@verdaccio/cli': major
'@verdaccio/config': major
'@verdaccio/core': major
'@verdaccio/file-locking': major
'@verdaccio/readme': major
'@verdaccio/tarball': major
'@verdaccio/types': major
'@verdaccio/url': major
'@verdaccio/hooks': major
'@verdaccio/loaders': major
'@verdaccio/logger': major
'@verdaccio/logger-prettify': major
'@verdaccio/middleware': major
'@verdaccio/node-api': major
'verdaccio-audit': major
'verdaccio-auth-memory': major
'verdaccio-htpasswd': major
'@verdaccio/local-storage': major
'verdaccio-memory': major
'@verdaccio/ui-theme': major
'@verdaccio/proxy': major
'@verdaccio/server': major
'@verdaccio/store': major
'@verdaccio/utils': major
'verdaccio': major
'@verdaccio/web': major
---
feat!: replace deprecated request dependency by got
This is a big refactoring of the core, fetching dependencies, improve code, more tests and better stability. This is essential for the next release, will take some time but would allow modularize more the core.
## Notes
- Remove deprecated `request` by other `got`, retry improved, custom Agent ( got does not include it built-in)
- Remove `async` dependency from storage (used by core) it was linked with proxy somehow safe to remove now
- Refactor with promises instead callback wherever is possible
- ~Document the API~
- Improve testing, integration tests
- Bugfix
- Clean up old validations
- Improve performance
## 💥 Breaking changes
- Plugin API methods were callbacks based are returning promises, this will break current storage plugins, check documentation for upgrade.
- Write Tarball, Read Tarball methods parameters change, a new set of options like `AbortController` signals are being provided to the `addAbortSignal` can be internally used with Streams when a request is aborted. eg: `addAbortSignal(signal, fs.createReadStream(pathName));`
- `@verdaccio/streams` stream abort support is legacy is being deprecated removed
- Remove AWS and Google Cloud packages for future refactoring [#2574](https://github.com/verdaccio/verdaccio/pull/2574).

View File

@@ -1,6 +1,6 @@
---
'@verdaccio/api': major
'@verdaccio/fastify-migration': major
'@verdaccio/server-fastify': major
'@verdaccio/tarball': major
'@verdaccio/local-storage': major
'verdaccio-memory': major

View File

@@ -0,0 +1,11 @@
---
'@verdaccio/cli': major
'@verdaccio/core': major
'@verdaccio/types': major
'@verdaccio/logger': major
'@verdaccio/logger-prettify': major
'verdaccio-audit': major
'@verdaccio/eslint-config': major
---
feat: migrate to pino.js 8

View File

@@ -2,7 +2,9 @@
"$schema": "https://unpkg.com/@changesets/config@1.3.0/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"linked": [],
"fixed": [
["verdaccio", "@verdaccio/cli", "@verdaccio/core", "@verdaccio/config", "@verdaccio/node-api"]
],
"access": "public",
"baseBranch": "master",
"updateInternalDependencies": "patch",

View File

@@ -6,7 +6,7 @@
'@verdaccio/commons-api': major
'@verdaccio/core': major
'@verdaccio/local-storage': major
'@verdaccio/fastify-migration': major
'@verdaccio/server-fastify': major
'@verdaccio/streams': major
'@verdaccio/types': major
'@verdaccio/hooks': major

View File

@@ -7,7 +7,7 @@
'@verdaccio/file-locking': major
'verdaccio-htpasswd': major
'@verdaccio/readme': major
'@verdaccio/fastify-migration': major
'@verdaccio/server-fastify': major
'@verdaccio/streams': major
'@verdaccio/tarball': major
'@verdaccio/types': major
@@ -16,7 +16,6 @@
'@verdaccio/loaders': major
'@verdaccio/logger': major
'@verdaccio/middleware': major
'@verdaccio/mock': major
'@verdaccio/node-api': major
'@verdaccio/active-directory': major
'verdaccio-audit': major

View File

@@ -0,0 +1,42 @@
---
'@verdaccio/api': patch
'@verdaccio/auth': patch
'@verdaccio/cli': patch
'@verdaccio/core': patch
'@verdaccio/file-locking': patch
'@verdaccio/readme': patch
'@verdaccio/tarball': patch
'@verdaccio/types': patch
'@verdaccio/url': patch
'@verdaccio/hooks': patch
'@verdaccio/loaders': patch
'@verdaccio/logger': patch
'@verdaccio/node-api': patch
'verdaccio-audit': patch
'verdaccio-auth-memory': patch
'verdaccio-htpasswd': patch
'@verdaccio/local-storage': patch
'verdaccio-memory': patch
'@verdaccio/ui-theme': patch
'@verdaccio/proxy': patch
'@verdaccio/server': patch
'@verdaccio/server-fastify': patch
'@verdaccio/cli-standalone': patch
'@verdaccio/store': patch
'docusaurus-plugin-contributors': patch
'@verdaccio/test-helper': patch
'verdaccio': patch
'@verdaccio/web': patch
'@verdaccio/test-cli-commons': patch
'@verdaccio/e2e-cli-npm6': patch
'@verdaccio/e2e-cli-npm7': patch
'@verdaccio/e2e-cli-npm8': patch
'@verdaccio/e2e-cli-pnpm6': patch
'@verdaccio/e2e-cli-pnpm7': patch
'@verdaccio/e2e-cli-yarn1': patch
'@verdaccio/e2e-cli-yarn2': patch
'@verdaccio/e2e-cli-yarn3': patch
'@verdaccio/e2e-cli-yarn4': patch
---
fix(deps): @verdaccio/utils should be a prod dep of local-storage

View File

@@ -15,7 +15,6 @@
'@verdaccio/logger': major
'@verdaccio/logger-prettify': major
'@verdaccio/middleware': major
'@verdaccio/mock': major
'@verdaccio/node-api': major
'@verdaccio/active-directory': major
'verdaccio-audit': major
@@ -30,7 +29,6 @@
'@verdaccio/utils': major
'verdaccio': major
'@verdaccio/web': major
'@verdaccio/website': major
---
feat!: experiments config renamed to flags

View File

@@ -1,6 +1,6 @@
---
'@verdaccio/api': minor
'@verdaccio/fastify-migration': minor
'@verdaccio/server-fastify': minor
'@verdaccio/hooks': minor
'@verdaccio/logger-prettify': minor
'@verdaccio/proxy': minor

View File

@@ -15,7 +15,6 @@
'@verdaccio/logger': major
'@verdaccio/logger-prettify': major
'@verdaccio/middleware': major
'@verdaccio/mock': major
'@verdaccio/node-api': major
'@verdaccio/proxy': major
'@verdaccio/server': major

View File

@@ -0,0 +1,29 @@
---
'@verdaccio/api': minor
'@verdaccio/cli': minor
'@verdaccio/core': minor
'@verdaccio/node-api': minor
'@verdaccio/server': minor
'@verdaccio/server-fastify': minor
'verdaccio': minor
---
chore: env variable for launch fastify
- Update fastify to major release `v4.3.0`
- Update CLI launcher
via CLI
```
VERDACCIO_SERVER=fastify verdaccio
```
with docker
```
docker run -it --rm --name verdaccio \
-e "VERDACCIO_SERVER=8080" -p 8080:8080 \
-e "VERDACCIO_SERVER=fastify" \
verdaccio/verdaccio
```

View File

@@ -1,6 +1,6 @@
---
'@verdaccio/cli': minor
'@verdaccio/fastify-migration': minor
'@verdaccio/server-fastify': minor
---
[Fastify] Add ping endpoint

View File

@@ -17,7 +17,6 @@
'@verdaccio/logger': patch
'@verdaccio/logger-prettify': patch
'@verdaccio/middleware': patch
'@verdaccio/mock': patch
'@verdaccio/node-api': patch
'@verdaccio/active-directory': patch
'verdaccio-audit': patch
@@ -31,9 +30,6 @@
'@verdaccio/utils': patch
'verdaccio': patch
'@verdaccio/web': patch
'@verdaccio/e2e-cli': patch
'@verdaccio/e2e-ui': patch
'@verdaccio/website': patch
---
chore: add release step to private regisry on merge changeset pr

View File

@@ -1,6 +1,5 @@
---
'@verdaccio/tarball': patch
'@verdaccio/mock': patch
'@verdaccio/ui-theme': patch
'@verdaccio/server': patch
'@verdaccio/utils': patch

View File

@@ -0,0 +1,5 @@
---
'@verdaccio/cli': patch
---
fix: version with breakline

View File

@@ -15,7 +15,6 @@
'@verdaccio/logger': minor
'@verdaccio/logger-prettify': minor
'@verdaccio/middleware': minor
'@verdaccio/mock': minor
'@verdaccio/node-api': minor
'@verdaccio/active-directory': minor
'verdaccio-audit': minor

View File

@@ -6,7 +6,7 @@
'@verdaccio/core': minor
'verdaccio-htpasswd': minor
'@verdaccio/local-storage': minor
'@verdaccio/fastify-migration': minor
'@verdaccio/server-fastify': minor
'@verdaccio/tarball': minor
'@verdaccio/types': minor
'@verdaccio/url': minor
@@ -14,7 +14,6 @@
'@verdaccio/loaders': minor
'@verdaccio/logger': minor
'@verdaccio/middleware': minor
'@verdaccio/mock': minor
'@verdaccio/node-api': minor
'@verdaccio/active-directory': minor
'verdaccio-auth-memory': minor

View File

@@ -15,7 +15,6 @@
'@verdaccio/logger': minor
'@verdaccio/logger-prettify': minor
'@verdaccio/middleware': minor
'@verdaccio/mock': minor
'@verdaccio/node-api': minor
'@verdaccio/proxy': minor
'@verdaccio/server': minor
@@ -24,7 +23,6 @@
'@verdaccio/utils': minor
'verdaccio': minor
'@verdaccio/web': minor
'@verdaccio/website': minor
---
feat: add typescript project references settings

View File

@@ -10,14 +10,12 @@
"verdaccio-htpasswd": "11.0.0-alpha.0",
"@verdaccio/local-storage": "11.0.0-alpha.0",
"@verdaccio/readme": "11.0.0-alpha.0",
"@verdaccio/streams": "11.0.0-alpha.0",
"@verdaccio/types": "11.0.0-alpha.0",
"@verdaccio/hooks": "6.0.0-alpha.0",
"@verdaccio/loaders": "6.0.0-alpha.0",
"@verdaccio/logger": "6.0.0-alpha.0",
"@verdaccio/logger-prettify": "6.0.0-alpha.0",
"@verdaccio/middleware": "6.0.0-alpha.0",
"@verdaccio/mock": "6.0.0-alpha.0",
"@verdaccio/node-api": "6.0.0-alpha.0",
"@verdaccio/proxy": "6.0.0-alpha.0",
"@verdaccio/server": "6.0.0-alpha.0",
@@ -33,32 +31,44 @@
"verdaccio-google-cloud": "11.0.0-alpha.0",
"verdaccio-memory": "11.0.0-alpha.0",
"@verdaccio/ui-theme": "6.0.0-alpha.1",
"@verdaccio/e2e-cli": "1.0.0",
"@verdaccio/e2e-ui": "1.0.0",
"@verdaccio/cli-standalone": "6.0.0-alpha.3",
"@verdaccio/tarball": "11.0.0-alpha.3",
"@verdaccio/url": "11.0.0-alpha.3",
"@verdaccio/fastify-migration": "6.0.0-6-next.9",
"@verdaccio/server-fastify": "6.0.0-6-next.9",
"@verdaccio/eslint-config": "1.0.0",
"@verdaccio/benchmark": "1.0.0",
"@verdaccio/core": "6.0.0-next.0",
"@verdaccio/test-helper": "1.0.0",
"docusaurus-plugin-contributors": "1.0.0",
"@verdaccio/website": "5.4.0"
"@verdaccio/website": "5.4.0",
"@verdaccio/test-cli-commons": "1.0.1-6-next.1",
"@verdaccio/e2e-cli-npm6": "1.0.1-6-next.1",
"@verdaccio/e2e-cli-npm7": "1.0.1-6-next.1",
"@verdaccio/e2e-cli-npm8": "1.0.1-6-next.1",
"@verdaccio/e2e-cli-pnpm6": "1.0.1-6-next.1",
"@verdaccio/e2e-cli-pnpm7": "1.0.1-6-next.1",
"@verdaccio/e2e-cli-yarn1": "1.0.1-6-next.1",
"@verdaccio/e2e-cli-yarn2": "1.0.1-6-next.1",
"@verdaccio/e2e-cli-yarn3": "1.0.1-6-next.1",
"@verdaccio/e2e-cli-yarn4": "1.0.1-6-next.1",
"@verdaccio/local-publish": "0.0.1"
},
"changesets": [
"afraid-mice-obey",
"angry-nails-appear",
"big-lobsters-sin",
"bright-poems-obey",
"brown-cycles-laugh",
"brown-pandas-wink",
"calm-pants-impress",
"chilled-ways-fetch",
"clever-pugs-warn",
"dry-planes-tap",
"dull-monkeys-search",
"eleven-brooms-hunt",
"eleven-spoons-matter",
"fair-lemons-beam",
"famous-tigers-doubt",
"few-cooks-destroy",
"few-mangos-grow",
"fifty-jars-rest",
@@ -67,6 +77,7 @@
"gentle-parrots-lay",
"gentle-trains-switch",
"gold-vans-tease",
"green-yaks-divide",
"healthy-bikes-behave",
"healthy-pants-smash",
"healthy-poets-compare",
@@ -81,6 +92,7 @@
"lovely-drinks-argue",
"many-vans-care",
"modern-spies-tell",
"moody-clocks-roll",
"neat-toes-report",
"neat-toys-float",
"olive-candles-speak",
@@ -103,9 +115,11 @@
"slow-carrots-relate",
"smart-apricots-kneel",
"smart-beds-cross",
"smooth-owls-pump",
"sour-buses-shout",
"spicy-frogs-press",
"spicy-snakes-sip",
"strange-ladybugs-nail",
"swift-pumpkins-knock",
"ten-parents-breathe",
"tender-bags-call",
@@ -114,7 +128,9 @@
"three-moles-drop",
"three-pots-sit",
"tiny-seals-join",
"tricky-taxis-watch",
"two-dolls-check",
"wild-jokes-beam"
"wild-jokes-beam",
"witty-ties-speak"
]
}

View File

@@ -1,9 +1,8 @@
---
'verdaccio-htpasswd': patch
'@verdaccio/local-storage': patch
'@verdaccio/fastify-migration': patch
'@verdaccio/server-fastify': patch
'@verdaccio/hooks': patch
'@verdaccio/mock': patch
'@verdaccio/node-api': patch
---

View File

@@ -14,11 +14,8 @@
'@verdaccio/ui-theme': major
'@verdaccio/proxy': major
'@verdaccio/server': major
'@verdaccio/mock': major
'verdaccio': major
'@verdaccio/web': major
'@verdaccio/e2e-cli': major
'@verdaccio/website': major
---
feat!: config.logs throw an error, logging config not longer accept array or logs property

View File

@@ -4,7 +4,6 @@
'@verdaccio/dev-types': major
'@verdaccio/web': major
'@verdaccio/e2e-ui': major
'@verdaccio/website': major
---
feat: upgrade to material ui 5

View File

@@ -0,0 +1,5 @@
---
'@verdaccio/ui-theme': patch
---
ui: basic grammatical fixes in the Ukraine Message

View File

@@ -1,9 +1,8 @@
---
'@verdaccio/fastify-migration': minor
'@verdaccio/server-fastify': minor
'@verdaccio/store': minor
'@verdaccio/utils': minor
'@verdaccio/web': minor
'@verdaccio/website': minor
---
feat: migrate web sidebar endpoint to fastify

View File

@@ -0,0 +1,9 @@
---
'@verdaccio/types': minor
---
feat: add dist.signatures to core/types
According to [`npm`](https://docs.npmjs.com/about-registry-signatures): _"Signatures are provided in the package's `packument` in each published version within the `dist` object"_
Here's an [example of a package version from the public npm registry with `dist.signatures`](https://registry.npmjs.org/light-cycle/1.4.3).

View File

@@ -1,6 +1,6 @@
---
'@verdaccio/auth': minor
'@verdaccio/fastify-migration': minor
'@verdaccio/server-fastify': minor
'@verdaccio/web': minor
---

View File

@@ -14,7 +14,6 @@
'@verdaccio/logger': patch
'@verdaccio/logger-prettify': patch
'@verdaccio/middleware': patch
'@verdaccio/mock': patch
'@verdaccio/node-api': patch
'@verdaccio/proxy': patch
'@verdaccio/server': patch

View File

@@ -0,0 +1,28 @@
---
'@verdaccio/api': minor
'@verdaccio/types': minor
'@verdaccio/local-storage': minor
'@verdaccio/server-fastify': minor
'@verdaccio/store': minor
'@verdaccio/test-helper': minor
'@verdaccio/web': minor
---
feat: implement abbreviated manifest
Enable abbreviated manifest data by adding the header:
```
curl -H "Accept: application/vnd.npm.install-v1+json" https://registry.npmjs.org/verdaccio
```
It returns a filtered manifest, additionally includes the [time](https://github.com/pnpm/rfcs/pull/2) field by request.
Current support for packages managers:
- npm: yes
- pnpm: yes
- yarn classic: yes
- yarn modern (+2.x): [no](https://github.com/yarnpkg/berry/pull/3981#issuecomment-1076566096)
https://github.com/npm/registry/blob/master/docs/responses/package-metadata.md#abbreviated-metadata-format

View File

@@ -0,0 +1,11 @@
---
'@verdaccio/api': patch
'@verdaccio/cli': patch
'@verdaccio/core': patch
'@verdaccio/types': patch
'@verdaccio/store': patch
'@verdaccio/test-helper': patch
'@verdaccio/local-publish': patch
---
fix: handle upload scoped tarball

View File

@@ -12,3 +12,5 @@ dist/
docs/
test/functional/store/*
docker-examples/**/lib/**/*.js
test/cli/e2e-yarn4/bin/yarn-4.0.0-rc.14.cjs
yarn.js

View File

@@ -18,8 +18,8 @@ jobs:
name: Prepare build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
- uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
with:
node-version: 16.x
- name: install pnpm
@@ -33,7 +33,7 @@ jobs:
- name: install dependencies
run: pnpm install
- name: Cache .pnpm-store
uses: actions/cache@v3
uses: actions/cache@fd5de65bc895cf536527842281bea11763fefd77 # tag=v3
with:
path: ~/.pnpm-store
key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}
@@ -44,7 +44,7 @@ jobs:
- name: tar packages
run: |
tar -czvf ${{ github.workspace }}/pkg.tar.gz -C ${{ github.workspace }}/packages .
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # tag=v3
with:
name: verdaccio-artifact
path: pkg.tar.gz
@@ -65,11 +65,11 @@ jobs:
name: Benchmark autocannon
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
- uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
with:
node-version: 16.x
- uses: actions/download-artifact@v3
- uses: actions/download-artifact@fb598a63ae348fa914e94cd0ff38f362e927b741 # tag=v3
with:
name: verdaccio-artifact
- name: untar packages
@@ -77,7 +77,7 @@ jobs:
- name: install pnpm
# require fixed version
run: sudo npm i pnpm@latest-6 -g
- uses: actions/cache@v3
- uses: actions/cache@fd5de65bc895cf536527842281bea11763fefd77 # tag=v3
with:
path: ~/.pnpm-store
key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}
@@ -90,7 +90,7 @@ jobs:
shell: bash
env:
DEBUG: metrics*
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # tag=v3
with:
name: verdaccio-metrics-api
path: ./api-results-${{matrix.verdaccioVersion}}-${{matrix.benchmark}}.json
@@ -126,11 +126,11 @@ jobs:
name: Benchmark hyperfine
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
- uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
with:
node-version: 16.x
- uses: actions/download-artifact@v3
- uses: actions/download-artifact@fb598a63ae348fa914e94cd0ff38f362e927b741 # tag=v3
with:
name: verdaccio-artifact
- name: untar packages
@@ -138,7 +138,7 @@ jobs:
- name: install pnpm
# require fixed version
run: sudo npm i pnpm@latest-6 -g
- uses: actions/cache@v3
- uses: actions/cache@fd5de65bc895cf536527842281bea11763fefd77 # tag=v3
with:
path: ~/.pnpm-store
key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}
@@ -156,7 +156,7 @@ jobs:
shell: bash
- name: rename
run: mv ./hyper-results.json ./hyper-results-${{matrix.verdaccioVersion}}-${{matrix.benchmark}}.json
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # tag=v3
with:
name: verdaccio-metrics
path: ./hyper-results-${{matrix.verdaccioVersion}}-${{matrix.benchmark}}.json

View File

@@ -20,12 +20,12 @@ jobs:
if: github.ref == 'refs/heads/master' && github.repository == 'verdaccio/verdaccio'
steps:
- name: checkout code repository
uses: actions/checkout@v3
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
with:
fetch-depth: 0
- name: setup node.js
uses: actions/setup-node@v3
uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
with:
node-version: 14
registry-url: 'https://registry.npmjs.org'
@@ -56,14 +56,16 @@ jobs:
run: pnpm build
- name: create versions
uses: verdaccio/changeset-action@master
uses: changesets/action@master
with:
version: pnpm ci:version
commit: 'chore: update versions'
title: 'chore: update versions'
publish: pnpm ci:publish
createGithubReleases: false
setupGitUser: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.CHANGESET_RELEASE_TOKEN }}
NPM_TOKEN: ${{ secrets.REGISTRY_AUTH_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.REGISTRY_AUTH_TOKEN }}
NPM_CONFIG_REGISTRY: https://registry.npmjs.org

View File

@@ -2,14 +2,12 @@ name: CI
on:
push:
branches:
- master
- 'changeset-release/master'
pull_request:
paths:
- .changeset/**
- .github/workflows/ci.yml
- 'packages/**'
- 'test/**'
- 'docker-examples/**'
- 'jest/**'
- 'package.json'
@@ -27,9 +25,9 @@ jobs:
ports:
- 4873:4873
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
- name: Use Node 16
uses: actions/setup-node@v3
uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
with:
node-version: 16
- name: Install pnpm
@@ -41,7 +39,7 @@ jobs:
- name: Install
run: pnpm recursive install --frozen-lockfile --registry http://localhost:4873
- name: Cache .pnpm-store
uses: actions/cache@v3
uses: actions/cache@fd5de65bc895cf536527842281bea11763fefd77 # tag=v3
with:
path: ~/.pnpm-store
key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}
@@ -52,14 +50,14 @@ jobs:
name: Lint
needs: prepare
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
- name: Use Node 16
uses: actions/setup-node@v3
uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
with:
node-version: 16
- name: Install pnpm
run: npm i pnpm@6.32.15 -g
- uses: actions/cache@v3
- uses: actions/cache@fd5de65bc895cf536527842281bea11763fefd77 # tag=v3
with:
path: ~/.pnpm-store
key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}
@@ -72,14 +70,14 @@ jobs:
name: Format
needs: prepare
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
- name: Use Node 16
uses: actions/setup-node@v3
uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
with:
node-version: 16
- name: Install pnpm
run: npm i pnpm@6.32.15 -g
- uses: actions/cache@v3
- uses: actions/cache@fd5de65bc895cf536527842281bea11763fefd77 # tag=v3
with:
path: ~/.pnpm-store
key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}
@@ -93,19 +91,18 @@ jobs:
fail-fast: true
matrix:
os: [ubuntu-latest, windows-latest]
## Node 16 breaks UI test, jest issue
node_version: [16, 17]
node_version: [16, 18]
name: ${{ matrix.os }} / Node ${{ matrix.node_version }}
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
- name: Use Node ${{ matrix.node_version }}
uses: actions/setup-node@v3
uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
with:
node-version: ${{ matrix.node_version }}
- name: Install pnpm
run: npm i pnpm@6.32.15 -g
- uses: actions/cache@v3
- uses: actions/cache@fd5de65bc895cf536527842281bea11763fefd77 # tag=v3
with:
path: ~/.pnpm-store
key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}
@@ -120,13 +117,36 @@ jobs:
runs-on: ubuntu-latest
name: UI Test E2E Node 16
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
- uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
with:
node-version: 16
- name: Install pnpm
run: npm i pnpm@6.32.15 -g
- uses: actions/cache@v3
- uses: actions/cache@fd5de65bc895cf536527842281bea11763fefd77 # tag=v3
with:
path: ~/.pnpm-store
key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}
- name: Install
run: pnpm recursive install --frozen-lockfile
- name: build
run: pnpm build
- name: Test UI
run: pnpm test:e2e:ui
# env:
# DEBUG: verdaccio:e2e*
ci-e2e-cli:
needs: [format, lint]
runs-on: ubuntu-latest
name: CLI Test E2E Node 16
steps:
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
- uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
with:
node-version: 16
- name: Install pnpm
run: npm i pnpm@6.32.15 -g
- uses: actions/cache@fd5de65bc895cf536527842281bea11763fefd77 # tag=v3
with:
path: ~/.pnpm-store
key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}
@@ -135,50 +155,23 @@ jobs:
run: pnpm recursive install --frozen-lockfile
- name: build
run: pnpm build
- name: Test UI
run: pnpm test:e2e:ui
- name: Test CLI
run: pnpm test:e2e:cli
# env:
# DEBUG: verdaccio:e2e*
# FIXME verify why fails on Node 16 (locally works fine)
# ci-e2e-cli:
# needs: [format, lint]
# runs-on: ubuntu-latest
# # TODO: fails on migrate to node 16, we need to check why
# name: CLI Test E2E Node 16
# steps:
# - uses: actions/checkout@v3
# - uses: actions/setup-node@v3
# with:
# node-version: 16
# - name: Install pnpm
# run: npm i pnpm@latest -g
# - uses: actions/cache@v3
# with:
# path: ~/.pnpm-store
# key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}
# - name: Install
# ## we need scripts, pupetter downloads aditional content
# run: pnpm recursive install --frozen-lockfile
# - name: build
# run: pnpm build
# - name: Test CLI
# run: pnpm test:e2e:cli
# env:
# DEBUG: verdaccio*
# DEBUG: verdaccio*
sync-translations:
# needs: [ci-e2e-cli, ci-e2e-ui]
needs: [ci-e2e-ui]
needs: [ci-e2e-cli, ci-e2e-ui]
runs-on: ubuntu-latest
name: synchronize translations
if: (github.event_name == 'push' && github.ref == 'refs/heads/master') || github.event_name == 'workflow_dispatch'
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
- uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
with:
node-version: 16
- name: Install pnpm
run: npm i pnpm@6.32.15 -g
- uses: actions/cache@v3
- uses: actions/cache@fd5de65bc895cf536527842281bea11763fefd77 # tag=v3
with:
path: ~/.pnpm-store
key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}

View File

@@ -21,7 +21,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
@@ -34,7 +34,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@c7f292ea4f542c473194b33813ccd4c207a6c725 # tag=v2
# Override language selection by uncommenting this and choosing your languages
# with:
@@ -42,7 +42,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
uses: github/codeql-action/autobuild@c7f292ea4f542c473194b33813ccd4c207a6c725 # tag=v2
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -56,4 +56,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@c7f292ea4f542c473194b33813ccd4c207a6c725 # tag=v2

View File

@@ -15,11 +15,11 @@ jobs:
name: Run script
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
with:
persist-credentials: false
fetch-depth: 0
- uses: actions/setup-node@v3
- uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
with:
node-version: 17.x
- name: install pnpm
@@ -39,7 +39,7 @@ jobs:
- name: format
run: pnpm format
- name: Commit & Push changes
uses: actions-js/push@v1.3
uses: actions-js/push@a52398fac807b0c1e5f1492c969b477c8560a0ba # tag=v1.3
with:
github_token: ${{ secrets.TOKEN_VERDACCIOBOT_GITHUB }}
message: "chore: updated contributors list"

View File

@@ -19,8 +19,8 @@ jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: docker/setup-qemu-action@v1
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
- uses: docker/setup-qemu-action@27d0a4f181a40b142cce983c5393082c365d1480 # tag=v1
- uses: docker/setup-buildx-action@v1
with:
driver-opts: network=host

View File

@@ -3,13 +3,12 @@ name: Verdaccio Website CI
on:
workflow_dispatch:
pull_request:
paths:
- 'website/**'
- './.github/workflows/website.yml'
push:
branches:
- 'master'
paths:
- 'website/**'
- 'package.json'
- './.github/workflows/website.yml'
- 'master'
jobs:
build:
@@ -17,15 +16,15 @@ jobs:
env:
NODE_OPTIONS: --max_old_space_size=4096
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
- name: Use Node 16
uses: actions/setup-node@v3
uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
with:
node-version: 16
- name: Cache pnpm modules
uses: actions/cache@v3
uses: actions/cache@fd5de65bc895cf536527842281bea11763fefd77 # tag=v3
env:
cache-name: cache-pnpm-modules
with:
@@ -34,7 +33,7 @@ jobs:
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-${{ matrix.node-version }}-
- uses: pnpm/action-setup@v2.2.2
- uses: pnpm/action-setup@10693b3829bf86eb2572aef5f3571dcf5ca9287d # tag=v2.2.2
with:
version: 6.32.15
run_install: |
@@ -43,7 +42,7 @@ jobs:
- name: Build Plugins
run: pnpm build --filter "docusaurus-plugin-contributors"
- name: Cache Docusaurus Build
uses: actions/cache@v3
uses: actions/cache@fd5de65bc895cf536527842281bea11763fefd77 # tag=v3
with:
path: website/node_modules/.cache/webpack
key: cache/webpack-${{github.ref}}-${{ hashFiles('**/pnpm-lock.yaml') }}
@@ -62,7 +61,7 @@ jobs:
- name: 🔥 Deploy Production Netlify
if: (github.event_name == 'push' && github.ref == 'refs/heads/master') || github.event_name == 'workflow_dispatch'
uses: semoal/action-netlify-deploy@master
uses: semoal/action-netlify-deploy@1a53f098745bf78555d11b436f5ee3af87e6b566
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
netlify-auth-token: ${{ secrets.NETLIFY_AUTH_TOKEN }}
@@ -77,7 +76,7 @@ jobs:
- name: 🤖 Deploy Preview Netlify
if: github.repository == 'verdaccio/verdaccio'
uses: semoal/action-netlify-deploy@master
uses: semoal/action-netlify-deploy@1a53f098745bf78555d11b436f5ee3af87e6b566
id: netlify_preview
with:
draft: true
@@ -92,7 +91,7 @@ jobs:
- name: Audit preview URL with Lighthouse
if: github.repository == 'verdaccio/verdaccio'
id: lighthouse_audit
uses: treosh/lighthouse-ci-action@9.3.0
uses: treosh/lighthouse-ci-action@b4dfae3eb959c5226e2c5c6afd563d493188bfaf # tag=9.3.0
with:
urls: |
${{ steps.netlify_preview.outputs.preview-url }}
@@ -101,7 +100,7 @@ jobs:
- name: Format lighthouse score
id: format_lighthouse_score
uses: actions/github-script@v6
uses: actions/github-script@c713e510dbd7d213d92d41b7a7805a986f4c5c66 # tag=v6
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
@@ -126,7 +125,7 @@ jobs:
- name: Add comment to PR
if: github.repository == 'verdaccio/verdaccio'
id: comment_to_pr
uses: marocchino/sticky-pull-request-comment@v2
uses: marocchino/sticky-pull-request-comment@39c5b5dc7717447d0cba270cd115037d32d28443 # tag=v2
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
number: ${{ github.event.issue.number }}

3
.gitignore vendored
View File

@@ -46,7 +46,8 @@ api-results.json
hyper-results.json
hyper-results*.json
api-results*.json
.clinic/
#docs
./api
packages/core/core/docs
**/docs/**

View File

@@ -31,3 +31,5 @@ api/**
packages/core/local-storage/tests/__fixtures__/test-storage/
packages/plugins/ui-theme/static/
.verdaccio-db.json
test/cli/e2e-yarn4/bin/yarn-4.0.0-rc.14.cjs
yarn.js

78
.vscode/launch.json vendored
View File

@@ -4,88 +4,12 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Attach",
"port": 9229,
"request": "attach",
"skipFiles": [
"<node_internals>/**"
],
"type": "pwa-node"
},
{
"name": "Verdaccio Debug",
"name": "Attach",
"port": 9229,
"request": "attach",
"skipFiles": ["<node_internals>/**"],
"type": "pwa-node"
},
{
"type": "node",
"request": "launch",
"name": "CLI Babel Registry",
"stopOnEntry": false,
"program": "${workspaceFolder}/debug/bootstrap.js",
"args": ["-l", "0.0.0.0:4873"],
"env": {
"BABEL_ENV": "registry"
},
"preLaunchTask": "npm: build:webui",
"console": "integratedTerminal"
},
{
"name": "Unit Tests",
"type": "node",
"request": "launch",
"program": "${workspaceRoot}/node_modules/bin/jest",
"stopOnEntry": false,
"args": ["--debug=true"],
"cwd": "${workspaceRoot}",
"runtimeExecutable": null,
"runtimeArgs": ["--nolazy"],
"env": {
"NODE_ENV": "test",
"TZ": "UTC"
},
"console": "integratedTerminal"
},
{
"name": "Functional Tests",
"type": "node",
"request": "launch",
"program": "${workspaceRoot}/node_modules/.bin/jest",
"stopOnEntry": false,
"args": [
"--config",
"./test/jest.config.functional.js",
"--testPathPattern",
"./test/functional/index*",
"--debug=false",
"--verbose",
"--useStderr",
"--detectOpenHandles"
],
"cwd": "${workspaceRoot}",
"env": {
"BABEL_ENV": "testOldEnv",
"VERDACCIO_DEBUG": "true",
"VERDACCIO_DEBUG_INJECT": "true",
"NODE_DEBUG": "TO_DEBUG_REQUEST_REMOVE_THIS_request"
},
"preLaunchTask": "pre-test",
"console": "integratedTerminal",
"runtimeExecutable": null,
"runtimeArgs": ["--nolazy"]
},
{
"type": "node",
"request": "launch",
"name": "Verdaccio Compiled",
"preLaunchTask": "npm: code:build",
"program": "${workspaceRoot}/bin/verdaccio",
"args": ["-l", "0.0.0.0:4873"],
"console": "integratedTerminal"
}
]
}

21
.vscode/tasks.json vendored
View File

@@ -1,21 +0,0 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"script": "build:webui",
"problemMatcher": []
},
{
"type": "npm",
"script": "code:build",
"problemMatcher": []
},
{
"label": "pre-test",
"dependsOn": ["npm: code:build", "npm: test:clean"]
}
]
}

View File

@@ -183,7 +183,7 @@ a report in our [issue tracker](https://github.com/verdaccio/verdaccio/issues).
- _Features clearly flagged as not supported_
- _Node.js issues installation in any platform_: If you cannot install the
global package (this is considered external issue)
- Any ticket which has beed flagged as an [external issue
- Any ticket which has been flagged as an [external issue
](https://github.com/verdaccio/verdaccio/labels/external-issue)
If you intend to report a **security** issue, please follow our [Security policy
@@ -234,7 +234,7 @@ the project. Adding in context and the use-case will really help!
- A detailed description the advantages of your request
- Whether or not it's compatible with `npm`, `pnpm` and [_yarn classic_
](https://github.com/yarnpkg/yarn) or [_yarn berry_
](https://github.com/yarnpkg/yarn) or [_yarn modern_
](https://github.com/yarnpkg/berry).
- A potential implementation or design
- Whatever else is on your mind! 🤓
@@ -278,7 +278,7 @@ clean git history.
#### Before Commit
Before committing, **you must ensure there are no linting errors and
all tests pass.** To do this, run these commands before create the PR:
all tests pass.** To do this, run these commands before creating the PR:
```bash
pnpm lint
@@ -420,3 +420,25 @@ If you want to develop your own plugin:
3. You are free to host your plugin in your repository
4. Provide a detailed description of your plugin to help users understand how to
use it
## Testing your changes in a local registry
Once you have perform your changes in the code base, the build and tests passes you can publish a local version:
- Ensure you have build all modules (or the one you have modified)
- Run `pnpm local:publish:release` to launch a local registry and publish all packages into it. This command will be alive until server is killed (Control Key + C)
```
pnpm build
pnpm local:publish:release
```
The last step consist on install globally the package from the local registry.
```
npm i -g verdaccio --registry=http://localhost:4873
verdaccio
```
If you perform more changes in the source code, repeat this process, there is not _hot reloading_ support.

View File

@@ -1,10 +1,10 @@
FROM --platform=${BUILDPLATFORM:-linux/amd64} node:16.15.0-alpine as builder
FROM --platform=${BUILDPLATFORM:-linux/amd64} node:16-alpine as builder
ENV NODE_ENV=development \
VERDACCIO_BUILD_REGISTRY=https://registry.verdaccio.org
RUN apk --no-cache add openssl ca-certificates wget && \
apk --no-cache add g++ gcc libgcc libstdc++ linux-headers make python2 && \
apk --no-cache add g++ gcc libgcc libstdc++ linux-headers make python3 && \
wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub && \
wget -q https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.25-r0/glibc-2.25-r0.apk && \
apk add glibc-2.25-r0.apk
@@ -20,7 +20,7 @@ RUN npm -g i pnpm@6.32.15 && \
# FIXME: need to remove devDependencies from the build
# RUN pnpm install --prod --ignore-scripts
FROM node:16.15.0-alpine
FROM node:16-alpine
LABEL maintainer="https://github.com/verdaccio/verdaccio"
ENV VERDACCIO_APPDIR=/opt/verdaccio \

View File

@@ -44,7 +44,19 @@ Google Cloud Storage** or create your own plugin.
Install with npm:
```bash
npm install --global verdaccio@6-next
npm install --location=global verdaccio@6-next
```
With `yarn`
```bash
yarn global add verdaccio@6-next
```
With `pnpm`
```bash
pnpm i -g verdaccio@6-next
```
or
@@ -68,8 +80,8 @@ Furthermore, you can read the [**Debugging Guidelines**](https://github.com/verd
You can develop your own [plugins](https://verdaccio.org/docs/plugins) with the [verdaccio generator](https://github.com/verdaccio/generator-verdaccio-plugin). Installing [Yeoman](https://yeoman.io/) is required.
```
npm install -g yo
npm install -g generator-verdaccio-plugin
npm install --location=global yo
npm install --location=global generator-verdaccio-plugin
```
Learn more [here](https://verdaccio.org/docs/dev-plugins) how to develop plugins. Share your plugins with the community.

View File

@@ -66,6 +66,6 @@ middlewares:
enabled: true
# log settings
logs:
log:
- { type: stdout, format: pretty, level: trace }
#- {type: file, path: verdaccio.log, level: info}

View File

@@ -7,4 +7,9 @@ module.exports = {
collectCoverage: true,
collectCoverageFrom: ['src/**/*.ts', '!**/node_modules/**', '!**/partials/**', '!**/fixture/**'],
coveragePathIgnorePatterns: ['node_modules', 'fixtures'],
coverageThreshold: {
global: {
lines: 90,
},
},
};

View File

@@ -15,110 +15,109 @@
"url": "https://opencollective.com/verdaccio"
},
"devDependencies": {
"@babel/cli": "7.16.8",
"@babel/core": "7.16.12",
"@babel/node": "7.16.8",
"@babel/plugin-proposal-class-properties": "7.16.7",
"@babel/plugin-proposal-decorators": "7.16.7",
"@babel/plugin-proposal-export-namespace-from": "7.16.7",
"@babel/plugin-proposal-function-sent": "7.16.7",
"@babel/plugin-proposal-json-strings": "7.16.7",
"@babel/plugin-proposal-nullish-coalescing-operator": "7.16.7",
"@babel/plugin-proposal-numeric-separator": "7.16.7",
"@babel/plugin-proposal-object-rest-spread": "7.16.7",
"@babel/plugin-proposal-optional-chaining": "7.16.7",
"@babel/plugin-proposal-throw-expressions": "7.16.7",
"@babel/cli": "7.18.10",
"@babel/core": "7.18.13",
"@babel/node": "7.18.10",
"@babel/plugin-proposal-class-properties": "7.18.6",
"@babel/plugin-proposal-decorators": "7.18.10",
"@babel/plugin-proposal-export-namespace-from": "7.18.9",
"@babel/plugin-proposal-function-sent": "7.18.6",
"@babel/plugin-proposal-json-strings": "7.18.6",
"@babel/plugin-proposal-nullish-coalescing-operator": "7.18.6",
"@babel/plugin-proposal-numeric-separator": "7.18.6",
"@babel/plugin-proposal-object-rest-spread": "7.18.9",
"@babel/plugin-proposal-optional-chaining": "7.18.9",
"@babel/plugin-proposal-throw-expressions": "7.18.6",
"@babel/plugin-syntax-dynamic-import": "7.8.3",
"@babel/plugin-syntax-import-meta": "7.10.4",
"@babel/plugin-transform-async-to-generator": "7.16.8",
"@babel/plugin-transform-classes": "7.16.7",
"@babel/plugin-transform-runtime": "7.16.10",
"@babel/preset-env": "7.16.11",
"@babel/preset-react": "7.16.7",
"@babel/preset-typescript": "7.16.7",
"@babel/register": "7.16.9",
"@babel/runtime": "7.16.7",
"@dianmora/contributors": "2.0.2",
"@changesets/changelog-github": "0.4.2",
"@changesets/cli": "2.15.0",
"@changesets/get-dependents-graph": "1.2.4",
"@crowdin/cli": "3.7.7",
"@trivago/prettier-plugin-sort-imports": "3.2.0",
"@types/async": "3.2.12",
"@babel/plugin-transform-async-to-generator": "7.18.6",
"@babel/plugin-transform-classes": "7.18.9",
"@babel/plugin-transform-runtime": "7.18.10",
"@babel/preset-env": "7.18.10",
"@babel/preset-react": "7.18.6",
"@babel/preset-typescript": "7.18.6",
"@babel/register": "7.18.9",
"@babel/runtime": "7.18.9",
"@dianmora/contributors": "5.0.0",
"@changesets/changelog-github": "0.4.6",
"@changesets/cli": "2.24.4",
"@changesets/get-dependents-graph": "1.3.3",
"@crowdin/cli": "3.7.10",
"@trivago/prettier-plugin-sort-imports": "3.3.0",
"@types/async": "3.2.15",
"@types/autocannon": "4.1.1",
"@types/express": "4.17.13",
"@types/http-errors": "1.8.2",
"@types/jest": "27.4.0",
"@types/lodash": "4.14.178",
"@types/jest": "27.5.2",
"@types/lodash": "4.14.184",
"@types/mime": "2.0.3",
"@types/minimatch": "3.0.5",
"@types/node": "16.11.21",
"@types/jsonwebtoken": "8.5.1",
"@types/node": "16.11.56",
"@types/jsonwebtoken": "8.5.9",
"@types/request": "2.48.8",
"@types/semver": "7.3.9",
"@types/semver": "7.3.12",
"@types/node-fetch": "2.6.2",
"@types/supertest": "2.0.12",
"@types/testing-library__jest-dom": "5.14.2",
"@types/validator": "13.7.1",
"@types/testing-library__jest-dom": "5.14.5",
"@types/validator": "13.7.6",
"@types/webpack": "5.28.0",
"@types/webpack-env": "1.16.3",
"@typescript-eslint/eslint-plugin": "5.25.0",
"@typescript-eslint/parser": "5.25.0",
"@types/webpack-env": "1.18.0",
"@typescript-eslint/eslint-plugin": "5.33.1",
"@typescript-eslint/parser": "5.33.1",
"@verdaccio/benchmark": "workspace:*",
"@verdaccio/eslint-config": "workspace:*",
"@verdaccio/types": "workspace:*",
"@verdaccio/ui-theme": "workspace:*",
"autocannon": "7.6.0",
"autocannon": "7.9.0",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "10.1.0",
"babel-jest": "27.4.6",
"babel-jest": "29.0.2",
"babel-plugin-dynamic-import-node": "2.3.3",
"babel-plugin-emotion": "10.2.2",
"codecov": "3.8.3",
"concurrently": "6.5.1",
"core-js": "3.20.3",
"core-js": "3.25.0",
"cross-env": "7.0.3",
"debug": "4.3.4",
"detect-secrets": "1.0.6",
"pretty-format": "27.5.1",
"jest-diff": "27.5.1",
"eslint": "8.15.0",
"fs-extra": "10.0.0",
"jest-diff": "29.0.2",
"eslint": "8.22.0",
"fs-extra": "10.1.0",
"husky": "7.0.4",
"in-publish": "2.0.1",
"jest": "27.4.7",
"jest-environment-jsdom": "27.4.6",
"jest-environment-jsdom-global": "3.0.0",
"jest-environment-node": "27.4.6",
"jest": "29.0.2",
"jest-environment-jsdom": "29.0.2",
"jest-environment-jsdom-global": "3.1.2",
"jest-environment-node": "29.0.2",
"jest-junit": "12.3.0",
"kleur": "3.0.3",
"lint-staged": "11.2.6",
"nock": "12.0.3",
"nock": "13.2.9",
"node-fetch": "cjs",
"nodemon": "2.0.15",
"nodemon": "2.0.19",
"npm-run-all": "4.1.5",
"prettier": "2.6.2",
"prettier": "2.7.1",
"rimraf": "3.0.2",
"selfsigned": "1.10.14",
"supertest": "6.2.2",
"ts-node": "10.4.0",
"typescript": "4.5.5",
"supertest": "6.2.4",
"ts-node": "10.9.1",
"typescript": "4.8.2",
"update-ts-references": "2.4.1",
"verdaccio": "5.5.0",
"verdaccio-audit": "workspace:*",
"verdaccio-auth-memory": "workspace:*",
"verdaccio-htpasswd": "workspace:*",
"verdaccio-memory": "workspace:*"
},
"scripts": {
"prepare": "husky install",
"husky:pre-commit": "lint-staged",
"clean": "pnpm recursive run clean",
"build": "pnpm recursive run build --filter=!@verdaccio/website",
"docker": "docker build -t verdaccio/verdaccio:local . --no-cache",
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,yml,yaml,md}\"",
"format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,json,yml,yaml,md}\"",
"lint": "eslint --max-warnings 46 \"**/*.{js,jsx,ts,tsx}\"",
"lint": "eslint --max-warnings 100 \"**/*.{js,jsx,ts,tsx}\"",
"test": "pnpm recursive test --filter ./packages",
"test:e2e:cli": "pnpm test --filter ...@verdaccio/e2e-cli",
"test:e2e:cli": "pnpm test --filter ...@verdaccio/e2e-* -- --coverage=false",
"test:e2e:ui": "pnpm test --filter ...@verdaccio/e2e-ui",
"start": "concurrently --kill-others \"pnpm _start:server\" \"pnpm _start:web\"",
"benchmark:hyper": "verdaccio-benchmark hyper -r ./hyper-results.json",
@@ -132,7 +131,7 @@
"_debug:reload": "nodemon -d 3 packages/verdaccio/debug/bootstrap.js",
"start:ts": "ts-node packages/verdaccio/src/start.ts -- --listen 8000",
"debug": "node --trace-warnings --trace-uncaught --inspect packages/verdaccio/debug/bootstrap.js",
"debug:fastify": "node --trace-warnings --trace-uncaught --inspect packages/verdaccio/debug/bootstrap.js -- fastify-server",
"debug:fastify": "cross-env VERDACCIO_SERVER=fastify node --trace-warnings --trace-uncaught --inspect packages/verdaccio/debug/bootstrap.js",
"debug:break": "node --trace-warnings --trace-uncaught --inspect-brk packages/verdaccio/debug/bootstrap.js",
"changeset": "changeset",
"changeset:check": "changeset status --since-master",
@@ -145,7 +144,10 @@
"crowdin:upload": "crowdin upload sources --auto-update --config ./crowdin.yaml",
"crowdin:download": "crowdin download --verbose --config ./crowdin.yaml",
"crowdin:sync": "pnpm crowdin:upload && pnpm crowdin:download --verbose",
"postinstall": "husky install"
"postinstall": "husky install",
"local:registry": "pnpm start --filter ...@verdaccio/local-publish",
"local:publish": "cross-env npm_config_registry=http://localhost:4873 pnpm ci:publish",
"local:publish:release": "concurrently \"pnpm local:registry\" \"pnpm local:publish\""
},
"engines": {
"node": ">=16.5",

View File

@@ -1,5 +1,137 @@
# @verdaccio/api
## 6.0.0-6-next.30
### Patch Changes
- @verdaccio/core@6.0.0-6-next.47
- @verdaccio/config@6.0.0-6-next.47
- @verdaccio/auth@6.0.0-6-next.26
- @verdaccio/logger@6.0.0-6-next.15
- @verdaccio/middleware@6.0.0-6-next.26
- @verdaccio/store@6.0.0-6-next.27
- @verdaccio/utils@6.0.0-6-next.15
## 6.0.0-6-next.29
### Patch Changes
- b849128d: fix: handle upload scoped tarball
- Updated dependencies [b849128d]
- @verdaccio/core@6.0.0-6-next.8
- @verdaccio/store@6.0.0-6-next.26
- @verdaccio/auth@6.0.0-6-next.25
- @verdaccio/config@6.0.0-6-next.17
- @verdaccio/logger@6.0.0-6-next.14
- @verdaccio/middleware@6.0.0-6-next.25
- @verdaccio/utils@6.0.0-6-next.14
## 6.0.0-6-next.28
### Patch Changes
- 351aeeaa: fix(deps): @verdaccio/utils should be a prod dep of local-storage
- Updated dependencies [351aeeaa]
- @verdaccio/auth@6.0.0-6-next.24
- @verdaccio/core@6.0.0-6-next.7
- @verdaccio/logger@6.0.0-6-next.13
- @verdaccio/store@6.0.0-6-next.25
- @verdaccio/middleware@6.0.0-6-next.24
- @verdaccio/config@6.0.0-6-next.16
- @verdaccio/utils@6.0.0-6-next.13
## 6.0.0-6-next.27
### Minor Changes
- 37274e4c: feat: implement abbreviated manifest
Enable abbreviated manifest data by adding the header:
```
curl -H "Accept: application/vnd.npm.install-v1+json" https://registry.npmjs.org/verdaccio
```
It returns a filtered manifest, additionally includes the [time](https://github.com/pnpm/rfcs/pull/2) field by request.
Current support for packages managers:
- npm: yes
- pnpm: yes
- yarn classic: yes
- yarn modern (+2.x): [no](https://github.com/yarnpkg/berry/pull/3981#issuecomment-1076566096)
https://github.com/npm/registry/blob/master/docs/responses/package-metadata.md#abbreviated-metadata-format
### Patch Changes
- Updated dependencies [37274e4c]
- @verdaccio/store@6.0.0-6-next.24
- @verdaccio/auth@6.0.0-6-next.23
- @verdaccio/core@6.0.0-6-next.6
- @verdaccio/logger@6.0.0-6-next.12
## 6.0.0-6-next.26
### Major Changes
- 292c0a37: feat!: replace deprecated request dependency by got
This is a big refactoring of the core, fetching dependencies, improve code, more tests and better stability. This is essential for the next release, will take some time but would allow modularize more the core.
## Notes
- Remove deprecated `request` by other `got`, retry improved, custom Agent ( got does not include it built-in)
- Remove `async` dependency from storage (used by core) it was linked with proxy somehow safe to remove now
- Refactor with promises instead callback wherever is possible
- ~Document the API~
- Improve testing, integration tests
- Bugfix
- Clean up old validations
- Improve performance
## 💥 Breaking changes
- Plugin API methods were callbacks based are returning promises, this will break current storage plugins, check documentation for upgrade.
- Write Tarball, Read Tarball methods parameters change, a new set of options like `AbortController` signals are being provided to the `addAbortSignal` can be internally used with Streams when a request is aborted. eg: `addAbortSignal(signal, fs.createReadStream(pathName));`
- `@verdaccio/streams` stream abort support is legacy is being deprecated removed
- Remove AWS and Google Cloud packages for future refactoring [#2574](https://github.com/verdaccio/verdaccio/pull/2574).
### Minor Changes
- 00d1d2a1: chore: env variable for launch fastify
- Update fastify to major release `v4.3.0`
- Update CLI launcher
via CLI
```
VERDACCIO_SERVER=fastify verdaccio
```
with docker
```
docker run -it --rm --name verdaccio \
-e "VERDACCIO_SERVER=8080" -p 8080:8080 \
-e "VERDACCIO_SERVER=fastify" \
verdaccio/verdaccio
```
### Patch Changes
- Updated dependencies [292c0a37]
- Updated dependencies [a3a209b5]
- Updated dependencies [00d1d2a1]
- @verdaccio/auth@6.0.0-6-next.23
- @verdaccio/config@6.0.0-6-next.15
- @verdaccio/core@6.0.0-6-next.6
- @verdaccio/logger@6.0.0-6-next.12
- @verdaccio/middleware@6.0.0-6-next.23
- @verdaccio/store@6.0.0-6-next.23
- @verdaccio/utils@6.0.0-6-next.12
## 6.0.0-6-next.25
### Patch Changes

View File

@@ -1,21 +0,0 @@
const debug = require('debug')('verdaccio:test');
const setup = debug;
const logger = {
child: jest.fn(() => ({
debug,
trace: debug,
warn: debug,
info: debug,
error: debug,
fatal: debug,
})),
debug: debug,
trace: debug,
warn: debug,
info: debug,
error: debug,
fatal: debug,
};
export { setup, logger };

View File

@@ -1,3 +1,10 @@
const config = require('../../jest/config');
module.exports = Object.assign({}, config, {});
module.exports = Object.assign({}, config, {
coverageThreshold: {
global: {
// FIXME: increase to 90
lines: 60,
},
},
});

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/api",
"version": "6.0.0-6-next.25",
"version": "6.0.0-6-next.30",
"description": "loaders logic",
"main": "./build/index.js",
"types": "build/index.d.ts",
@@ -30,7 +30,7 @@
},
"scripts": {
"clean": "rimraf ./build",
"test": "cross-env NODE_ENV=test BABEL_ENV=test jest",
"test": "jest",
"type-check": "tsc --noEmit -p tsconfig.build.json",
"build:types": "tsc --emitDeclarationOnly -p tsconfig.build.json",
"build:js": "babel src/ --out-dir build/ --copy-files --extensions \".ts,.tsx\" --source-maps",
@@ -39,29 +39,30 @@
},
"license": "MIT",
"dependencies": {
"@verdaccio/auth": "workspace:6.0.0-6-next.22",
"@verdaccio/config": "workspace:6.0.0-6-next.14",
"@verdaccio/core": "workspace:6.0.0-6-next.5",
"@verdaccio/hooks": "workspace:6.0.0-6-next.13",
"@verdaccio/logger": "workspace:6.0.0-6-next.11",
"@verdaccio/middleware": "workspace:6.0.0-6-next.22",
"@verdaccio/store": "workspace:6.0.0-6-next.22",
"@verdaccio/utils": "workspace:6.0.0-6-next.11",
"@verdaccio/auth": "workspace:6.0.0-6-next.26",
"@verdaccio/config": "workspace:6.0.0-6-next.47",
"@verdaccio/core": "workspace:6.0.0-6-next.47",
"@verdaccio/logger": "workspace:6.0.0-6-next.15",
"@verdaccio/middleware": "workspace:6.0.0-6-next.26",
"@verdaccio/store": "workspace:6.0.0-6-next.27",
"@verdaccio/utils": "workspace:6.0.0-6-next.15",
"abortcontroller-polyfill": "1.7.3",
"cookies": "0.8.0",
"debug": "4.3.3",
"body-parser": "1.19.1",
"express": "4.17.2",
"debug": "4.3.4",
"body-parser": "1.20.0",
"express": "4.18.1",
"lodash": "4.17.21",
"mime": "2.6.0",
"semver": "7.3.5"
"semver": "7.3.7"
},
"devDependencies": {
"@types/node": "16.11.21",
"@verdaccio/server": "workspace:6.0.0-6-next.31",
"@verdaccio/types": "workspace:11.0.0-6-next.12",
"@verdaccio/test-helper": "workspace:1.1.0-6-next.1",
"supertest": "6.2.2"
"@types/node": "16.11.56",
"@verdaccio/server": "workspace:6.0.0-6-next.36",
"@verdaccio/types": "workspace:11.0.0-6-next.16",
"@verdaccio/test-helper": "workspace:1.1.0-6-next.4",
"supertest": "6.2.4",
"nock": "13.2.9",
"mockdate": "3.0.5"
},
"funding": {
"type": "opencollective",

View File

@@ -3,106 +3,119 @@ import _ from 'lodash';
import mime from 'mime';
import { IAuth } from '@verdaccio/auth';
import { VerdaccioError, constants } from '@verdaccio/core';
import { constants, errorUtils } from '@verdaccio/core';
import { allow, media } from '@verdaccio/middleware';
import { Storage } from '@verdaccio/store';
import { Package } from '@verdaccio/types';
import { $NextFunctionVer, $RequestExtend, $ResponseExtend } from '../types/custom';
export default function (route: Router, auth: IAuth, storage: Storage): void {
const can = allow(auth);
const tag_package_version = function (
const addTagPackageVersionMiddleware = async function (
req: $RequestExtend,
res: $ResponseExtend,
next: $NextFunctionVer
): $NextFunctionVer {
): Promise<$NextFunctionVer> {
if (_.isString(req.body) === false) {
return next('route');
return next(errorUtils.getBadRequest('version is missing'));
}
const tags = {};
tags[req.params.tag] = req.body;
storage.mergeTags(req.params.package, tags, function (err: Error): $NextFunctionVer {
if (err) {
return next(err);
}
try {
await storage.mergeTagsNext(req.params.package, tags);
res.status(constants.HTTP_STATUS.CREATED);
return next({ ok: constants.API_MESSAGE.TAG_ADDED });
});
return next({
ok: constants.API_MESSAGE.TAG_ADDED,
});
} catch (err) {
next(err);
}
};
// tagging a package.
route.put('/:package/:tag', can('publish'), media(mime.getType('json')), tag_package_version);
route.post(
'/-/package/:package/dist-tags/:tag',
route.put(
'/:package/:tag',
can('publish'),
media(mime.getType('json')),
tag_package_version
addTagPackageVersionMiddleware
);
route.put(
'/-/package/:package/dist-tags/:tag',
can('publish'),
media(mime.getType('json')),
tag_package_version
addTagPackageVersionMiddleware
);
route.delete(
'/-/package/:package/dist-tags/:tag',
can('publish'),
function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
async function (
req: $RequestExtend,
res: $ResponseExtend,
next: $NextFunctionVer
): Promise<void> {
const tags = {};
tags[req.params.tag] = null;
storage.mergeTags(req.params.package, tags, function (err: VerdaccioError): $NextFunctionVer {
if (err) {
return next(err);
}
try {
await storage.mergeTagsNext(req.params.package, tags);
res.status(constants.HTTP_STATUS.CREATED);
return next({
ok: constants.API_MESSAGE.TAG_REMOVED,
});
});
} catch (err) {
next(err);
}
}
);
route.get(
'/-/package/:package/dist-tags',
can('access'),
function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
storage.getPackage({
name: req.params.package,
uplinksLook: true,
req,
callback: function (err: VerdaccioError, info: Package): $NextFunctionVer {
if (err) {
return next(err);
}
next(info[constants.DIST_TAGS]);
},
});
async function (
req: $RequestExtend,
res: $ResponseExtend,
next: $NextFunctionVer
): Promise<void> {
const name = req.params.package;
const requestOptions = {
protocol: req.protocol,
headers: req.headers as any,
// FIXME: if we migrate to req.hostname, the port is not longer included.
host: req.host,
remoteAddress: req.socket.remoteAddress,
};
try {
const manifest = await storage.getPackageByOptions({
name,
uplinksLook: true,
requestOptions,
});
next(manifest[constants.DIST_TAGS]);
} catch (err) {
next(err);
}
}
);
route.post(
'/-/package/:package/dist-tags',
can('publish'),
function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
storage.mergeTags(
req.params.package,
req.body,
function (err: VerdaccioError): $NextFunctionVer {
if (err) {
return next(err);
}
res.status(constants.HTTP_STATUS.CREATED);
return next({
ok: constants.API_MESSAGE.TAG_UPDATED,
});
}
);
async function (
req: $RequestExtend,
res: $ResponseExtend,
next: $NextFunctionVer
): Promise<void> {
try {
await storage.mergeTagsNext(req.params.package, req.body);
res.status(constants.HTTP_STATUS.CREATED);
return next({
ok: constants.API_MESSAGE.TAG_UPDATED,
});
} catch (err) {
next(err);
}
}
);
}

View File

@@ -1,6 +1,5 @@
import bodyParser from 'body-parser';
import express, { Router } from 'express';
import semver from 'semver';
import { IAuth } from '@verdaccio/auth';
import {
@@ -25,10 +24,6 @@ import v1Search from './v1/search';
import token from './v1/token';
import whoami from './whoami';
if (semver.lte(process.version, 'v15.0.0')) {
global.AbortController = require('abortcontroller-polyfill/dist/cjs-ponyfill').AbortController;
}
export default function (config: Config, auth: IAuth, storage: Storage): Router {
/* eslint new-cap:off */
const app = express.Router();
@@ -62,7 +57,7 @@ export default function (config: Config, auth: IAuth, storage: Storage): Router
search(app);
user(app, auth, config);
distTags(app, auth, storage);
publish(app, auth, storage, config);
publish(app, auth, storage);
ping(app);
stars(app, storage);
// @ts-ignore

View File

@@ -2,7 +2,7 @@ import buildDebug from 'debug';
import { Router } from 'express';
import { IAuth } from '@verdaccio/auth';
import { HEADERS, errorUtils } from '@verdaccio/core';
import { HEADERS, HEADER_TYPE } from '@verdaccio/core';
import { allow } from '@verdaccio/middleware';
import { Storage } from '@verdaccio/store';
@@ -10,27 +10,6 @@ import { $NextFunctionVer, $RequestExtend, $ResponseExtend } from '../types/cust
const debug = buildDebug('verdaccio:api:package');
const downloadStream = (
packageName: string,
filename: string,
storage: any,
_req: $RequestExtend,
res: $ResponseExtend
): void => {
const stream = storage.getTarball(packageName, filename);
stream.on('content-length', function (content): void {
res.header('Content-Length', content);
});
stream.on('error', function (err): void {
return res.locals.report_error(err);
});
res.header(HEADERS.CONTENT_TYPE, HEADERS.OCTET_STREAM);
stream.pipe(res);
};
export default function (route: Router, auth: IAuth, storage: Storage): void {
const can = allow(auth);
@@ -44,28 +23,24 @@ export default function (route: Router, auth: IAuth, storage: Storage): void {
): Promise<void> {
debug('init package by version');
const name = req.params.package;
let queryVersion = req.params.version;
let version = req.params.version;
const write = req.query.write === 'true';
const abbreviated = req.get('Accept') === Storage.ABBREVIATED_HEADER;
const requestOptions = {
protocol: req.protocol,
headers: req.headers as any,
// FIXME: if we migrate to req.hostname, the port is not longer included.
host: req.host,
remoteAddress: req.socket.remoteAddress,
byPassCache: write,
};
try {
// TODO: this is just temporary while I migrate all plugins to use the new API
// the method will be renamed to getPackage again but Promise Based.
if (!storage.getPackageByOptions) {
throw errorUtils.getInternalError(
'getPackageByOptions not implemented, check pr-2750 for more details'
);
}
const manifest = await storage.getPackageByOptions({
name,
uplinksLook: true,
req,
version: queryVersion,
abbreviated,
version,
requestOptions,
});
next(manifest);
@@ -76,20 +51,39 @@ export default function (route: Router, auth: IAuth, storage: Storage): void {
);
route.get(
'/:scopedPackage/-/:scope/:filename',
'/:pkg/-/:filename',
can('access'),
function (req: $RequestExtend, res: $ResponseExtend): void {
const { scopedPackage, filename } = req.params;
async function (req: $RequestExtend, res: $ResponseExtend, next): Promise<void> {
const { pkg, filename } = req.params;
const abort = new AbortController();
try {
const stream = (await storage.getTarballNext(pkg, filename, {
signal: abort.signal,
// TODO: review why this param
// enableRemote: true,
})) as any;
downloadStream(scopedPackage, filename, storage, req, res);
}
);
stream.on('content-length', (size) => {
res.header(HEADER_TYPE.CONTENT_LENGTH, size);
});
route.get(
'/:package/-/:filename',
can('access'),
function (req: $RequestExtend, res: $ResponseExtend): void {
downloadStream(req.params.package, req.params.filename, storage, req, res);
stream.once('error', (err) => {
res.locals.report_error(err);
next(err);
});
req.on('abort', () => {
debug('request aborted for %o', req.url);
abort.abort();
});
res.header(HEADERS.CONTENT_TYPE, HEADERS.OCTET_STREAM);
stream.pipe(res);
} catch (err: any) {
// console.log('catch API error request', err);
res.locals.report_error(err);
next(err);
}
}
);
}

View File

@@ -1,40 +1,21 @@
import buildDebug from 'debug';
import { Router } from 'express';
import _ from 'lodash';
import mime from 'mime';
import Path from 'path';
import { IAuth } from '@verdaccio/auth';
import {
API_ERROR,
API_MESSAGE,
DIST_TAGS,
HEADERS,
HTTP_STATUS,
errorUtils,
} from '@verdaccio/core';
import { notify } from '@verdaccio/hooks';
import { API_MESSAGE, HTTP_STATUS } from '@verdaccio/core';
import { logger } from '@verdaccio/logger';
import { allow, expectJson, media } from '@verdaccio/middleware';
import { Storage } from '@verdaccio/store';
import { Callback, CallbackAction, Config, MergeTags, Package, Version } from '@verdaccio/types';
import { hasDiffOneKey, isObject, validateMetadata } from '@verdaccio/utils';
import { $NextFunctionVer, $RequestExtend, $ResponseExtend } from '../types/custom';
import star from './star';
import { isPublishablePackage, isRelatedToDeprecation } from './utils';
// import star from './star';
// import { isPublishablePackage, isRelatedToDeprecation } from './utils';
const debug = buildDebug('verdaccio:api:publish');
export default function publish(
router: Router,
auth: IAuth,
storage: Storage,
config: Config
): void {
const can = allow(auth);
/**
/**
* Publish a package / update package / un/start a package
*
* There are multiples scenarios here to be considered:
@@ -73,20 +54,34 @@ export default function publish(
*
* Example flow of unpublish.
*
* npm http fetch GET 200 http://localhost:4873/@scope%2ftest1?write=true 1680ms
* npm http fetch PUT 201 http://localhost:4873/@scope%2ftest1/-rev/14-5d500cfce92f90fd
* 956606ms attempt #2
* npm http fetch GET 200 http://localhost:4873/@scope%2ftest1?write=true 1601ms
* npm http fetch DELETE 201 http://localhost:4873/@scope%2ftest1/-/test1-1.0.3.tgz/-rev/16
* -e11c8db282b2d992 19ms
* There are two possible flows:
*
* - Remove all packages (entirely)
* eg: npm unpublish package-name@* --force
* eg: npm unpublish package-name --force
*
* npm http fetch GET 200 http://localhost:4873/custom-name?write=true 1680ms
* npm http fetch DELETE 201 http://localhost:4873/custom-name/-/test1-1.0.3.tgz/-rev/16-e11c8db282b2d992 19ms
*
* - Remove a specific version
* eg: npm unpublish package-name@1.0.0 --force
*
* Get fresh manifest
* npm http fetch GET 200 http://localhost:4873/custom-name?write=true 1680ms
* Update manifest without the version to be unpublished
* npm http fetch PUT 201 http://localhost:4873/custom-name/-rev/14-5d500cfce92f90fd 956606ms
* Get fresh manifest (revision should be different)
* npm http fetch GET 200 http://localhost:4873/custom-name?write=true 1601ms
* Remove the tarball
* npm http fetch DELETE 201 http://localhost:4873/custom-name/-/test1-1.0.3.tgz/-rev/16-e11c8db282b2d992 19ms
*
* 3. Star a package
*
* Permissions: start a package depends of the publish and unpublish permissions, there is no
* specific flag for star or un start.
* The URL for star is similar to the unpublish (change package format)
*
* npm has no enpoint for star a package, rather mutate the metadata and acts as, the difference
* npm has no endpoint for star a package, rather mutate the metadata and acts as, the difference
* is the users property which is part of the payload and the body only includes
*
* {
@@ -98,12 +93,24 @@ export default function publish(
}
*
*/
export default function publish(router: Router, auth: IAuth, storage: Storage): void {
const can = allow(auth);
// publish (update manifest) v6
router.put(
'/:package/:_rev?/:revision?',
'/:package',
can('publish'),
media(mime.getType('json')),
expectJson,
publishPackage(storage, config, auth)
publishPackageNext(storage)
);
// unpublish a pacakge v6
router.put(
'/:package/-rev/:revision',
can('unpublish'),
media(mime.getType('json')),
expectJson,
publishPackageNext(storage)
);
/**
@@ -111,330 +118,101 @@ export default function publish(
*
* This scenario happens when the first call detect there is only one version remaining
* in the metadata, then the client decides to DELETE the resource
* npm http fetch GET 304 http://localhost:4873/@scope%2ftest1?write=true 1076ms (from cache)
npm http fetch DELETE 201 http://localhost:4873/@scope%2ftest1/-rev/18-d8ebe3020bd4ac9c 22ms
* npm http fetch GET 304 http://localhost:4873/package-name?write=true 1076ms (from cache)
* npm http fetch DELETE 201 http://localhost:4873/package-name/-rev/18-d8ebe3020bd4ac9c 22ms
*/
router.delete('/:package/-rev/*', can('unpublish'), unPublishPackage(storage));
// v6
router.delete(
'/:package/-rev/:revision',
can('unpublish'),
async function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
const packageName = req.params.package;
const rev = req.params.revision;
// removing a tarball
logger.debug({ packageName }, `unpublishing @{packageName}`);
try {
await storage.removePackage(packageName, rev);
debug('package %s unpublished', packageName);
res.status(HTTP_STATUS.CREATED);
return next({ ok: API_MESSAGE.PKG_REMOVED });
} catch (err) {
return next(err);
}
}
);
/*
Remove a tarball, this happens when npm unpublish a package unique version.
npm http fetch DELETE 201 http://localhost:4873/package-name/-rev/18-d8ebe3020bd4ac9c 22ms
*/
router.delete(
'/:package/-/:filename/-rev/:revision',
can('unpublish'),
can('publish'),
removeTarball(storage)
);
// uploading package tarball
router.put(
'/:package/-/:filename/*',
can('publish'),
media(HEADERS.OCTET_STREAM),
uploadPackageTarball(storage)
);
// adding a version
router.put(
'/:package/:version/-tag/:tag',
can('publish'),
media(mime.getType('json')),
expectJson,
addVersion(storage)
);
}
/**
* Publish a package
*/
export function publishPackage(storage: Storage, config: Config, auth: IAuth): any {
const starApi = star(storage);
return function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
const packageName = req.params.package;
debug('publishing or updating a new version for %o', packageName);
/**
* Write tarball of stream data from package clients.
*/
const createTarball = function (filename: string, data, cb: Callback): void {
const stream = storage.addTarball(packageName, filename);
stream.on('error', function (err) {
debug(
'error on stream a tarball %o for %o with error %o',
filename,
packageName,
err.message
);
cb(err);
});
stream.on('success', function () {
debug('success on stream a tarball %o for %o', filename, packageName);
cb();
});
// this is dumb and memory-consuming, but what choices do we have?
// flow: we need first refactor this file before decides which type use here
stream.end(Buffer.from(data.data, 'base64'));
stream.done();
};
/**
* Add new package version in storage
*/
const createVersion = function (version: string, metadata: Version, cb: CallbackAction): void {
debug('add a new package version %o to storage %o', version, metadata);
storage.addVersion(packageName, version, metadata, null, cb);
};
/**
* Add new tags in storage
*/
const addTags = function (tags: MergeTags, cb: CallbackAction): void {
debug('add new tag %o to storage', packageName);
storage.mergeTags(packageName, tags, cb);
};
const afterChange = function (error, okMessage, metadata: Package): void {
const metadataCopy: Package = { ...metadata };
debug('after change metadata %o', metadata);
const { _attachments, versions } = metadataCopy;
// `npm star` wouldn't have attachments
// and `npm deprecate` would have attachments as a empty object, i.e {}
if (_.isNil(_attachments) || JSON.stringify(_attachments) === '{}') {
debug('no attachments detected');
if (error) {
debug('no_attachments: after change error with %o', error.message);
return next(error);
}
debug('no_attachments: after change success');
res.status(HTTP_STATUS.CREATED);
return next({
ok: okMessage,
success: true,
});
}
/**
* npm-registry-client 0.3+ embeds tarball into the json upload
* issue https://github.com/rlidwka/sinopia/issues/31, dealing with it here:
*/
const isInvalidBodyFormat =
isObject(_attachments) === false ||
hasDiffOneKey(_attachments) ||
isObject(versions) === false ||
hasDiffOneKey(versions);
if (isInvalidBodyFormat) {
// npm is doing something strange again
// if this happens in normal circumstances, report it as a bug
debug('invalid body format');
logger.info({ packageName }, `wrong package format on publish a package @{packageName}`);
return next(errorUtils.getBadRequest(API_ERROR.UNSUPORTED_REGISTRY_CALL));
}
if (error && error.status !== HTTP_STATUS.CONFLICT) {
debug('error on change or update a package with %o', error.message);
return next(error);
}
// at this point document is either created or existed before
const [firstAttachmentKey] = Object.keys(_attachments);
createTarball(
Path.basename(firstAttachmentKey),
_attachments[firstAttachmentKey],
function (error) {
debug('creating a tarball %o', firstAttachmentKey);
if (error) {
debug('error on create a tarball for %o with error %o', packageName, error.message);
return next(error);
}
const versionToPublish = Object.keys(versions)[0];
versions[versionToPublish].readme =
_.isNil(metadataCopy.readme) === false ? String(metadataCopy.readme) : '';
createVersion(versionToPublish, versions[versionToPublish], function (error) {
if (error) {
debug('error on create a version for %o with error %o', packageName, error.message);
return next(error);
}
addTags(metadataCopy[DIST_TAGS], async function (error) {
if (error) {
debug('error on create a tag for %o with error %o', packageName, error.message);
return next(error);
}
try {
await notify(
metadataCopy,
config,
req.remote_user,
`${metadataCopy.name}@${versionToPublish}`
);
} catch (error: any) {
debug(
'error on notify add a new tag %o',
`${metadataCopy.name}@${versionToPublish}`
);
logger.error({ error }, 'notify batch service has failed: @{error}');
}
debug('add a tag succesfully for %o', `${metadataCopy.name}@${versionToPublish}`);
res.status(HTTP_STATUS.CREATED);
return next({ ok: okMessage, success: true });
});
});
}
);
};
if (isPublishablePackage(req.body) === false && isObject(req.body.users)) {
debug('starting star a package');
return starApi(req, res, next);
}
try {
debug('pre validation metadata to publish %o', req.body);
const metadata = validateMetadata(req.body, packageName);
debug('post validation metadata to publish %o', metadata);
// treating deprecation as updating a package
if (req.params._rev || isRelatedToDeprecation(req.body)) {
debug('updating a new version for %o', packageName);
// we check unpublish permissions, an update is basically remove versions
const remote = req.remote_user;
auth.allow_unpublish({ packageName }, remote, (error) => {
debug('allowed to unpublish a package %o', packageName);
if (error) {
debug('not allowed to unpublish a version for %o', packageName);
return next(error);
}
debug('update a package');
storage.changePackage(packageName, metadata, req.params.revision, function (error) {
afterChange(error, API_MESSAGE.PKG_CHANGED, metadata);
});
});
} else {
debug('adding a new version for the package %o', packageName);
storage.addPackage(packageName, metadata, function (error) {
debug('package metadata updated %o', metadata);
afterChange(error, API_MESSAGE.PKG_CREATED, metadata);
});
}
} catch (error: any) {
debug('error on publish, bad package format %o', packageName);
logger.error({ packageName }, 'error on publish, bad package data for @{packageName}');
return next(errorUtils.getBadData(API_ERROR.BAD_PACKAGE_DATA));
}
};
}
/**
* un-publish a package
*/
export function unPublishPackage(storage: Storage) {
return async function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
const packageName = req.params.package;
logger.debug({ packageName }, `unpublishing @{packageName}`);
try {
await storage.removePackage(packageName);
} catch (err) {
if (err) {
return next(err);
}
}
res.status(HTTP_STATUS.CREATED);
return next({ ok: API_MESSAGE.PKG_REMOVED });
};
}
/**
* Delete tarball
*/
export function removeTarball(storage: Storage) {
return function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
const packageName = req.params.package;
const { filename, revision } = req.params;
logger.debug(
{ packageName, filename, revision },
`removing a tarball for @{packageName}-@{tarballName}-@{revision}`
);
storage.removeTarball(packageName, filename, revision, function (err) {
if (err) {
return next(err);
}
res.status(HTTP_STATUS.CREATED);
async function (
req: $RequestExtend,
res: $ResponseExtend,
next: $NextFunctionVer
): Promise<void> {
const packageName = req.params.package;
const { filename, revision } = req.params;
logger.debug(
{ packageName, filename, revision },
`success remove tarball for @{packageName}-@{tarballName}-@{revision}`
`removing a tarball for @{packageName}-@{tarballName}-@{revision}`
);
return next({ ok: API_MESSAGE.TARBALL_REMOVED });
});
};
}
/**
* Adds a new version
*/
export function addVersion(storage: Storage) {
return function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
const { version, tag } = req.params;
const packageName = req.params.package;
debug('add a new version %o and tag %o for %o', version, tag, packageName);
try {
await storage.removeTarball(packageName, filename, revision);
res.status(HTTP_STATUS.CREATED);
storage.addVersion(packageName, version, req.body, tag, function (error) {
if (error) {
debug('error on add new version');
return next(error);
logger.debug(
{ packageName, filename, revision },
`success remove tarball for @{packageName}-@{tarballName}-@{revision}`
);
return next({ ok: API_MESSAGE.TARBALL_REMOVED });
} catch (err) {
return next(err);
}
debug('success on add new version');
res.status(HTTP_STATUS.CREATED);
return next({
ok: API_MESSAGE.PKG_PUBLISHED,
});
});
};
}
);
}
/**
* uploadPackageTarball
*/
export function uploadPackageTarball(storage: Storage) {
return function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
export function publishPackageNext(storage: Storage): any {
return async function (
req: $RequestExtend,
_res: $ResponseExtend,
next: $NextFunctionVer
): Promise<void> {
const ac = new AbortController();
const packageName = req.params.package;
const stream = storage.addTarball(packageName, req.params.filename);
req.pipe(stream);
const { revision } = req.params;
const metadata = req.body;
// checking if end event came before closing
let complete = false;
req.on('end', function () {
complete = true;
stream.done();
});
req.on('close', function () {
if (!complete) {
stream.abort();
}
});
stream.on('error', function (err) {
return res.locals.report_error(err);
});
stream.on('success', function () {
res.status(HTTP_STATUS.CREATED);
return next({
ok: API_MESSAGE.TARBALL_UPLOADED,
try {
debug('publishing %s', packageName);
await storage.updateManifest(metadata, {
name: packageName,
revision,
signal: ac.signal,
requestOptions: {
host: req.hostname,
protocol: req.protocol,
// @ts-ignore
headers: req.headers,
},
});
});
_res.status(HTTP_STATUS.CREATED);
return next({
// TODO: this could be also Package Updated based on the
// action, deprecate, star, publish new version, or create a package
// the message some return from the method
ok: API_MESSAGE.PKG_CREATED,
success: true,
});
} catch (err: any) {
// TODO: review if we need the abort controller here
next(err);
}
};
}

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import buildDebug from 'debug';
import { Response } from 'express';
import _ from 'lodash';
@@ -27,61 +28,61 @@ export default function (
return (req: $RequestExtend, res: Response, next: $NextFunctionVer): void => {
const name = req.params.package;
debug('starring a package for %o', name);
const afterChangePackage = function (err?: Error) {
if (err) {
debug('error on update package for %o', name);
return next(err);
}
// const afterChangePackage = function (err?: Error) {
// if (err) {
// debug('error on update package for %o', name);
// return next(err);
// }
debug('succes update package for %o', name);
res.status(HTTP_STATUS.OK);
next({
success: true,
});
};
// debug('succes update package for %o', name);
// res.status(HTTP_STATUS.OK);
// next({
// success: true,
// });
// };
debug('get package info package for %o', name);
// @ts-ignore
storage.getPackage({
name,
req,
callback: function (err, info) {
if (err) {
debug('error on get package info package for %o', name);
return next(err);
}
const newStarUser = req.body[USERS];
const remoteUsername = req.remote_user.name;
const localStarUsers = info[USERS];
// Check is star or unstar
const isStar = Object.keys(newStarUser).includes(remoteUsername);
debug('is start? %o', isStar);
if (
_.isNil(localStarUsers) === false &&
validateInputs(newStarUser, localStarUsers, remoteUsername, isStar)
) {
return afterChangePackage();
}
const users = isStar
? {
...localStarUsers,
[remoteUsername]: true,
}
: _.reduce(
localStarUsers,
(users, value, key) => {
if (key !== remoteUsername) {
users[key] = value;
}
return users;
},
{}
);
debug('update package for %o', name);
storage.changePackage(name, { ...info, users }, req.body._rev, function (err) {
afterChangePackage(err);
});
},
});
// storage.getPackage({
// name,
// req,
// callback: function (err, info) {
// if (err) {
// debug('error on get package info package for %o', name);
// return next(err);
// }
// const newStarUser = req.body[USERS];
// const remoteUsername = req.remote_user.name;
// const localStarUsers = info[USERS];
// // Check is star or unstar
// const isStar = Object.keys(newStarUser).includes(remoteUsername);
// debug('is start? %o', isStar);
// if (
// _.isNil(localStarUsers) === false &&
// validateInputs(newStarUser, localStarUsers, remoteUsername, isStar)
// ) {
// return afterChangePackage();
// }
// const users = isStar
// ? {
// ...localStarUsers,
// [remoteUsername]: true,
// }
// : _.reduce(
// localStarUsers,
// (users, value, key) => {
// if (key !== remoteUsername) {
// users[key] = value;
// }
// return users;
// },
// {}
// );
// debug('update package for %o', name);
// storage.changePackage(name, { ...info, users }, req.body._rev, function (err) {
// afterChangePackage(err);
// });
// },
// });
};
}

View File

@@ -3,34 +3,32 @@ import _ from 'lodash';
import { HTTP_STATUS, USERS } from '@verdaccio/core';
import { Storage } from '@verdaccio/store';
import { Package } from '@verdaccio/types';
import { Version } from '@verdaccio/types';
import { $NextFunctionVer, $RequestExtend } from '../types/custom';
type Packages = Package[];
export default function (route: Router, storage: Storage): void {
route.get(
'/-/_view/starredByUser',
(req: $RequestExtend, res: Response, next: $NextFunctionVer): void => {
async (req: $RequestExtend, res: Response, next: $NextFunctionVer): Promise<void> => {
const remoteUsername = req.remote_user.name;
storage.getLocalDatabase((err, localPackages: Packages) => {
if (err) {
return next(err);
}
try {
const localPackages: Version[] = await storage.getLocalDatabaseNext();
const filteredPackages: Packages = localPackages.filter((localPackage: Package) =>
const filteredPackages: Version[] = localPackages.filter((localPackage: Version) =>
_.keys(localPackage[USERS]).includes(remoteUsername)
);
res.status(HTTP_STATUS.OK);
next({
rows: filteredPackages.map((filteredPackage: Package) => ({
rows: filteredPackages.map((filteredPackage: Version) => ({
value: filteredPackage.name,
})),
});
});
} catch (err: any) {
return next(err);
}
}
);
}

View File

@@ -8,7 +8,7 @@ import { createRemoteUser } from '@verdaccio/config';
import { API_ERROR, API_MESSAGE, HTTP_STATUS, errorUtils } from '@verdaccio/core';
import { logger } from '@verdaccio/logger';
import { Config, RemoteUser } from '@verdaccio/types';
import { getAuthenticatedMessage, validatePassword } from '@verdaccio/utils';
import { getAuthenticatedMessage, mask, validatePassword } from '@verdaccio/utils';
import { $NextFunctionVer, $RequestExtend } from '../types/custom';
@@ -28,6 +28,23 @@ export default function (route: Router, auth: IAuth, config: Config): void {
}
);
/**
*
* body example
* req.body = {
_id: "org.couchdb.user:jjjj",
name: "jjjj",
password: "jjjj",
type: "user",
roles: [],
date: "2022-07-08T15:51:04.002Z",
}
*
* @export
* @param {Router} route
* @param {IAuth} auth
* @param {Config} config
*/
route.put(
'/-/user/:org_couchdb_user/:_rev?/:revision?',
function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void {
@@ -92,7 +109,7 @@ export default function (route: Router, auth: IAuth, config: Config): void {
const token =
name && password ? await getApiToken(auth, config, user, password) : undefined;
debug('adduser: new token %o', token);
debug('adduser: new token %o', mask(token as string, 4));
if (!token) {
return next(errorUtils.getUnauthorized());
}

View File

@@ -1,25 +0,0 @@
import _ from 'lodash';
import { Package } from '@verdaccio/types';
/**
* Check whether the package metadta has enough data to be published
* @param pkg metadata
*/
export function isPublishablePackage(pkg: Package): boolean {
// TODO: we can do better, no need get keys
const keys: string[] = Object.keys(pkg);
return _.includes(keys, 'versions');
}
export function isRelatedToDeprecation(pkgInfo: Package): boolean {
const { versions } = pkgInfo;
for (const version in versions) {
if (Object.prototype.hasOwnProperty.call(versions[version], 'deprecated')) {
return true;
}
}
return false;
}

View File

@@ -5,7 +5,7 @@ import { IAuth } from '@verdaccio/auth';
import { HTTP_STATUS, searchUtils } from '@verdaccio/core';
import { logger } from '@verdaccio/logger';
import { Storage } from '@verdaccio/store';
import { Package } from '@verdaccio/types';
import { Manifest } from '@verdaccio/types';
const debug = buildDebug('verdaccio:api:search');
@@ -16,7 +16,7 @@ const debug = buildDebug('verdaccio:api:search');
* req: 'GET /-/v1/search?text=react&size=20&frpom=0&quality=0.65&popularity=0.98&maintenance=0.5'
*/
export default function (route, auth: IAuth, storage: Storage): void {
function checkAccess(pkg: any, auth: any, remoteUser): Promise<Package | null> {
function checkAccess(pkg: any, auth: any, remoteUser): Promise<Manifest | null> {
return new Promise((resolve, reject) => {
auth.allow_access({ packageName: pkg?.package?.name }, remoteUser, function (err, allowed) {
if (err) {
@@ -49,7 +49,7 @@ export default function (route, auth: IAuth, storage: Storage): void {
from = parseInt(from, 10) || 0;
try {
data = await storage.searchManager?.search({
data = await storage.search({
query,
url,
abort,

View File

@@ -1,36 +1,20 @@
import buildDebug from 'debug';
import { Response, Router } from 'express';
import { errorUtils } from '@verdaccio/core';
import { $NextFunctionVer, $RequestExtend } from '../types/custom';
const debug = buildDebug('verdaccio:api:user');
export default function (route: Router): void {
route.get('/whoami', (req: $RequestExtend, res: Response, next: $NextFunctionVer): void => {
debug('whoami: reditect');
if (req.headers.referer === 'whoami') {
const username = req.remote_user.name;
// FIXME: this service should return 401 if user missing
// if (!username) {
// debug('whoami: user not found');
// return next(getUnauthorized('Unauthorized'));
// }
debug('whoami: logged by user');
return next({ username: username });
} else {
debug('whoami: redirect next route');
// redirect to the route below
return next('route');
route.get('/-/whoami', (req: $RequestExtend, _res: Response, next: $NextFunctionVer): any => {
// remote_user is set by the auth middleware
const username = req?.remote_user?.name;
if (!username) {
debug('whoami: user not found');
return next(errorUtils.getUnauthorized('Unauthorized'));
}
});
route.get('/-/whoami', (req: $RequestExtend, res: Response, next: $NextFunctionVer): any => {
const username = req.remote_user.name;
// FIXME: this service should return 401 if user missing
// if (!username) {
// debug('whoami: user not found');
// return next(getUnauthorized('Unauthorized'));
// }
debug('whoami: response %o', username);
return next({ username: username });

View File

@@ -1,83 +1,126 @@
import bodyParser from 'body-parser';
import express, { Application } from 'express';
import { Application } from 'express';
import _ from 'lodash';
import path from 'path';
import supertest from 'supertest';
import { Auth, IAuth } from '@verdaccio/auth';
import { Config, parseConfigFile } from '@verdaccio/config';
import { HEADERS, HEADER_TYPE, HTTP_STATUS } from '@verdaccio/core';
import { errorReportingMiddleware, final, handleError } from '@verdaccio/middleware';
import { parseConfigFile } from '@verdaccio/config';
import { HEADERS, HEADER_TYPE, HTTP_STATUS, TOKEN_BEARER } from '@verdaccio/core';
import { setup } from '@verdaccio/logger';
import { Storage } from '@verdaccio/store';
import { generatePackageMetadata } from '@verdaccio/test-helper';
import {
generatePackageMetadata,
initializeServer as initializeServerHelper,
} from '@verdaccio/test-helper';
import { GenericBody } from '@verdaccio/types';
import { buildToken, generateRandomHexString } from '@verdaccio/utils';
import apiEndpoints from '../../src';
import apiMiddleware from '../../src';
const getConf = (conf) => {
setup();
export const getConf = (conf) => {
const configPath = path.join(__dirname, 'config', conf);
return parseConfigFile(configPath);
const config = parseConfigFile(configPath);
// custom config to avoid conflict with other tests
config.auth.htpasswd.file = `${config.auth.htpasswd.file}-${generateRandomHexString()}`;
return config;
};
// TODO: replace by @verdaccio/test-helper
export async function initializeServer(configName): Promise<Application> {
const app = express();
const config = new Config(getConf(configName));
const storage = new Storage(config);
await storage.init(config, []);
const auth: IAuth = new Auth(config);
// TODO: this might not be need it, used in apiEndpoints
app.use(bodyParser.json({ strict: false, limit: '10mb' }));
// @ts-ignore
app.use(errorReportingMiddleware);
// @ts-ignore
app.use(apiEndpoints(config, auth, storage));
// @ts-ignore
app.use(handleError);
// @ts-ignore
app.use(final);
app.use(function (request, response) {
response.status(590);
console.log('respo', response);
response.json({ error: 'cannot handle this' });
});
return app;
return initializeServerHelper(getConf(configName), [apiMiddleware], Storage);
}
export function publishVersion(app, _configFile, pkgName, version): supertest.Test {
const pkgMetadata = generatePackageMetadata(pkgName, version);
export function createUser(app, name: string, password: string): supertest.Test {
return supertest(app)
.put(`/-/user/org.couchdb.user:${name}`)
.send({
name: name,
password: password,
})
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.CREATED);
}
export async function getNewToken(app: any, credentials: any): Promise<string> {
const response = await createUser(app, credentials.name, credentials.password);
const { token, ok } = response.body;
expect(ok).toBeDefined();
expect(token).toBeDefined();
expect(typeof token).toBe('string');
return token;
}
export async function generateTokenCLI(app, token, payload): Promise<any> {
return supertest(app)
.post('/-/npm/v1/tokens')
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.send(JSON.stringify(payload))
.set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token))
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET);
}
export async function deleteTokenCLI(app, token, tokenToDelete): Promise<any> {
return supertest(app)
.delete(`/-/npm/v1/tokens/token/${tokenToDelete}`)
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token))
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.OK);
}
export function publishVersionWithToken(
app,
pkgName: string,
version: string,
token: string,
distTags?: GenericBody
): supertest.Test {
const pkgMetadata = generatePackageMetadata(pkgName, version, distTags);
return supertest(app)
.put(`/${encodeURIComponent(pkgName)}`)
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token))
.send(JSON.stringify(pkgMetadata))
.set('accept', HEADERS.GZIP)
.set(HEADER_TYPE.ACCEPT_ENCODING, HEADERS.JSON);
}
export function publishVersion(
app,
pkgName: string,
version: string,
distTags?: GenericBody
): supertest.Test {
const pkgMetadata = generatePackageMetadata(pkgName, version, distTags);
return supertest(app)
.put(`/${encodeURIComponent(pkgName)}`)
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.send(JSON.stringify(pkgMetadata))
.set('accept', HEADERS.GZIP)
.set(HEADER_TYPE.ACCEPT_ENCODING, HEADERS.JSON)
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON);
.set(HEADER_TYPE.ACCEPT_ENCODING, HEADERS.JSON);
}
export async function publishTaggedVersion(
app,
configFile,
pkgName: string,
version: string,
tag: string
) {
const pkgMetadata = generatePackageMetadata(pkgName, version, {
[tag]: version,
});
export function getDisTags(app, pkgName) {
return supertest(app)
.put(
`/${encodeURIComponent(pkgName)}/${encodeURIComponent(version)}/-tag/${encodeURIComponent(
tag
)}`
)
.get(`/-/package/${encodeURIComponent(pkgName)}/dist-tags`)
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.send(JSON.stringify(pkgMetadata))
.expect(HTTP_STATUS.CREATED)
.set('accept', HEADERS.GZIP)
.set(HEADER_TYPE.ACCEPT_ENCODING, HEADERS.JSON)
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON);
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.OK);
}
export function getPackage(
app: any,
token: string,
pkgName: string,
statusCode: number = HTTP_STATUS.OK
): supertest.Test {
const test = supertest(app).get(`/${pkgName}`);
if (_.isNil(token) === false || _.isEmpty(token) === false) {
test.set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token));
}
return test.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET).expect(statusCode);
}

View File

@@ -0,0 +1,25 @@
storage: ./storage
auth:
htpasswd:
file: ./htpasswd-distTag
web:
enable: true
title: verdaccio
publish:
allow_offline: false
uplinks:
log: { type: stdout, format: pretty, level: trace }
packages:
'@*/*':
access: $anonymous
publish: $anonymous
'**':
access: $anonymous
publish: $anonymous
_debug: true

View File

@@ -1,13 +1,8 @@
store:
memory:
limit: 1000
storage: ./storage
auth:
auth-memory:
users:
test:
name: test
password: test
htpasswd:
file: ./htpasswd-package
web:
enable: true

View File

@@ -1,10 +1,6 @@
store:
memory:
limit: 10
auth:
auth-memory:
users:
htpasswd:
file: ./htpasswd-ping
web:
enable: true
title: verdaccio

View File

@@ -0,0 +1,26 @@
auth:
htpasswd:
file: ./htpasswd-publish-proxy
web:
enable: true
title: verdaccio
uplinks:
npmjs:
url: https://registry.npmjs.org/
log: { type: stdout, format: pretty, level: trace }
packages:
'@*/*':
access: $all
publish: $anonymous
unpublish: $anonymous
proxy: npmjs
'**':
access: $all
publish: $anonymous
unpublish: $anonymous
proxy: npmjs
_debug: true

View File

@@ -1,14 +1,6 @@
store:
memory:
limit: 1000
auth:
auth-memory:
users:
test:
name: test
password: test
htpasswd:
file: ./htpasswd-publish
web:
enable: true
title: verdaccio
@@ -24,7 +16,9 @@ packages:
'@*/*':
access: $anonymous
publish: $anonymous
unpublish: $anonymous
'**':
access: $anonymous
publish: $anonymous
unpublish: $anonymous
_debug: true

View File

@@ -0,0 +1,29 @@
storage: ./storage
auth:
htpasswd:
file: ./htpasswd-search
web:
enable: true
title: verdaccio
uplinks:
log: { type: stdout, format: pretty, level: trace }
packages:
'private-*':
access: $all
publish: jota
'@private/*':
access: $all
publish: jota
'@*/*':
access: $all
publish: $authenticated
'**':
access: $all
publish: $authenticated
_debug: true

View File

@@ -1,6 +1,3 @@
storage: ./storage
plugins: ./plugins
security:
api:
jwt:
@@ -9,6 +6,8 @@ security:
# to avoid invalid verification token, more info on JWT page
notBefore: 0
storage: ./storage
auth:
htpasswd:
file: ./htpasswd
@@ -20,7 +19,9 @@ packages:
'only-you-can-publish':
access: $authenticated
publish: $authenticated
log: { type: stdout, format: pretty, level: warn }
log: { type: stdout, format: pretty, level: debug }
## enable token for testing
flags:
## enable token for testing
token: true

View File

@@ -0,0 +1,19 @@
storage: ./storage
auth:
htpasswd:
file: ./htpasswd
packages:
'@token/*':
access: $authenticated
publish: $authenticated
'only-you-can-publish':
access: $authenticated
publish: $authenticated
log: { type: stdout, format: pretty, level: debug }
## enable token for testing
flags:
token: true

View File

@@ -8,6 +8,10 @@ auth:
htpasswd:
file: ./htpasswd
uplinks:
ver:
url: https://registry.verdaccio.org
security:
api:
jwt:
@@ -18,18 +22,16 @@ packages:
'@*/*':
access: $all
publish: $authenticated
proxy: remote
'vue':
access: $authenticated
publish: $authenticated
proxy: remote
proxy: ver
'**':
access: $all
publish: $authenticated
proxy: remote
middlewares:
audit:
enabled: true
log: { type: stdout, format: pretty, level: warn }
log: { type: stdout, format: pretty, level: info }

View File

@@ -1,21 +1,13 @@
store:
memory:
limit: 1000
auth:
auth-memory:
users:
test:
name: test
password: test
htpasswd:
file: ./htpasswd-user
web:
enable: true
title: verdaccio
uplinks:
npmjs:
url: https://registry.npmjs.org/
ver:
url: https://registry.verdaccio.org
log: { type: stdout, format: pretty, level: trace }
@@ -24,13 +16,15 @@ packages:
access: $all
publish: $all
unpublish: $all
proxy: npmjs
'verdaccio':
access: $all
publish: $all
'vue':
access: $authenticated
publish: $authenticated
proxy: ver
'**':
access: $all
publish: $all
unpublish: $all
proxy: npmjs
_debug: true

View File

@@ -1,14 +1,3 @@
store:
memory:
limit: 1000
auth:
auth-memory:
users:
test:
name: test
password: test
web:
enable: true
title: verdaccio
@@ -19,6 +8,10 @@ uplinks:
log: { type: stdout, format: pretty, level: trace }
auth:
htpasswd:
file: ./htpasswd-whoami
packages:
'@*/*':
access: $all

View File

@@ -0,0 +1,76 @@
import supertest from 'supertest';
import { API_MESSAGE, HEADERS, HEADER_TYPE, HTTP_STATUS } from '@verdaccio/core';
import { getDisTags, initializeServer, publishVersion } from './_helper';
describe('package', () => {
let app;
beforeEach(async () => {
app = await initializeServer('distTag.yaml');
});
test.each([['foo'], ['@scope/foo']])('should display dist-tag (npm dist-tag ls)', async (pkg) => {
await publishVersion(app, pkg, '1.0.0');
await publishVersion(app, pkg, '1.0.1');
const response = await getDisTags(app, pkg);
expect(response.body).toEqual({ latest: '1.0.1' });
});
test('should add a version to a tag (npm dist-tag add)', async () => {
await publishVersion(app, encodeURIComponent('foo'), '1.0.0');
await publishVersion(app, encodeURIComponent('foo'), '1.0.1');
const response = await supertest(app)
.put(`/${encodeURIComponent('foo')}/test`)
.set(HEADERS.ACCEPT, HEADERS.GZIP)
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.send(JSON.stringify('1.0.1'))
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.CREATED);
expect(response.body.ok).toEqual(API_MESSAGE.TAG_ADDED);
const response2 = await getDisTags(app, 'foo');
expect(response2.body).toEqual({ latest: '1.0.1', test: '1.0.1' });
});
test('should fails if a version is missing (npm dist-tag add)', async () => {
await publishVersion(app, encodeURIComponent('foo'), '1.0.0');
await publishVersion(app, encodeURIComponent('foo'), '1.0.1');
await supertest(app)
.put(`/${encodeURIComponent('foo')}/test`)
.set(HEADERS.ACCEPT, HEADERS.GZIP)
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.send(JSON.stringify({}))
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.BAD_REQUEST);
});
test('should delete a previous added tag (npm dist-tag rm)', async () => {
await publishVersion(app, encodeURIComponent('foo'), '1.0.0');
await publishVersion(app, encodeURIComponent('foo'), '1.0.1');
const response = await supertest(app)
.put(`/${encodeURIComponent('foo')}/beta`)
.set(HEADERS.ACCEPT, HEADERS.GZIP)
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.send(JSON.stringify('1.0.1'))
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.CREATED);
expect(response.body.ok).toEqual(API_MESSAGE.TAG_ADDED);
const response2 = await getDisTags(app, 'foo');
expect(response2.body).toEqual({ latest: '1.0.1', beta: '1.0.1' });
const response3 = await supertest(app)
.delete(`/-/package/${encodeURIComponent('foo')}/dist-tags/beta`)
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.CREATED);
expect(response3.body.ok).toEqual(API_MESSAGE.TAG_REMOVED);
const response4 = await getDisTags(app, 'foo');
expect(response4.body).toEqual({ latest: '1.0.1' });
});
});

View File

@@ -1,91 +1,105 @@
import supertest from 'supertest';
import { HEADERS, HEADER_TYPE, HTTP_STATUS } from '@verdaccio/core';
import { DIST_TAGS, HEADERS, HEADER_TYPE, HTTP_STATUS } from '@verdaccio/core';
import { Storage } from '@verdaccio/store';
import { $RequestExtend, $ResponseExtend } from '../../types/custom';
import { initializeServer, publishTaggedVersion, publishVersion } from './_helper';
const mockApiJWTmiddleware = jest.fn(
() =>
(req: $RequestExtend, res: $ResponseExtend, _next): void => {
req.remote_user = { name: 'foo', groups: [], real_groups: [] };
_next();
}
);
jest.mock('@verdaccio/auth', () => ({
Auth: class {
apiJWTmiddleware() {
return mockApiJWTmiddleware();
}
allow_access(_d, _f, cb) {
// always allow access
cb(null, true);
}
allow_publish(_d, _f, cb) {
// always allow publish
cb(null, true);
}
},
}));
import { initializeServer, publishVersion } from './_helper';
describe('package', () => {
let app;
beforeEach(async () => {
app = await initializeServer('package.yaml');
});
test('should return a package', async () => {
await publishVersion(app, 'package.yaml', 'foo', '1.0.0');
return new Promise((resolve) => {
supertest(app)
.get('/foo')
.set('Accept', HEADERS.JSON)
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.OK)
.then((response) => {
expect(response.body.name).toEqual('foo');
resolve(response);
});
describe('get tarball', () => {
let app;
beforeEach(async () => {
app = await initializeServer('package.yaml');
});
});
test('should return a package by version', async () => {
await publishVersion(app, 'package.yaml', 'foo2', '1.0.0');
return new Promise((resolve) => {
supertest(app)
.get('/foo2/1.0.0')
.set('Accept', HEADERS.JSON)
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.OK)
.then((response) => {
expect(response.body.name).toEqual('foo2');
resolve(response);
});
test.each([
['foo', 'foo-1.0.0.tgz'],
['@scope/foo', 'foo-1.0.0.tgz'],
])('should return a file tarball', async (pkg, fileName) => {
await publishVersion(app, pkg, '1.0.0');
const response = await supertest(app)
.get(`/${pkg}/-/${fileName}`)
.set(HEADERS.ACCEPT, HEADERS.JSON)
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.OCTET_STREAM)
.expect(HTTP_STATUS.OK);
expect(Buffer.from(response.body).toString('utf8')).toBeDefined();
});
test.each([
['foo', 'foo-1.0.0.tgz'],
['@scope/foo', 'foo-1.0.0.tgz'],
])('should fails if tarball does not exist', async (pkg, fileName) => {
await publishVersion(app, pkg, '1.0.1');
return await supertest(app)
.get(`/${pkg}/-/${fileName}`)
.set(HEADERS.ACCEPT, HEADERS.JSON)
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.OCTET_STREAM)
.expect(HTTP_STATUS.NOT_FOUND);
});
test.todo('check content length file header');
test.todo('fails on file was aborted');
});
// FIXME: investigate the 404
test.skip('should return a package by dist-tag', async (done) => {
// await publishVersion(app, 'package.yaml', 'foo3', '1.0.0');
await publishVersion(app, 'package.yaml', 'foo-tagged', '1.0.0');
await publishTaggedVersion(app, 'package.yaml', 'foo-tagged', '1.0.1', 'test');
return supertest(app)
.get('/foo-tagged/1.0.1')
.set('Accept', HEADERS.JSON)
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.CREATED)
.then((response) => {
expect(response.body.name).toEqual('foo3');
done();
});
});
describe('get package', () => {
let app;
beforeEach(async () => {
app = await initializeServer('package.yaml');
});
test('should return 404', async () => {
return supertest(app)
.get('/404-not-found')
.set('Accept', HEADERS.JSON)
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.NOT_FOUND);
test.each([['foo'], ['@scope/foo']])('should return a foo private package', async (pkg) => {
await publishVersion(app, pkg, '1.0.0');
const response = await supertest(app)
.get(`/${pkg}`)
.set(HEADERS.ACCEPT, HEADERS.JSON)
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.OK);
expect(response.body.name).toEqual(pkg);
});
test.each([['foo'], ['@scope/foo']])(
'should return a foo private package by version',
async (pkg) => {
await publishVersion(app, pkg, '1.0.0');
const response = await supertest(app)
.get(`/${pkg}`)
.set(HEADERS.ACCEPT, HEADERS.JSON)
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.OK);
expect(response.body.name).toEqual(pkg);
}
);
test.each([['foo'], ['@scope/foo']])(
'should return a foo private package by version',
async (pkg) => {
await publishVersion(app, pkg, '1.0.0');
const response = await supertest(app)
.get(`/${pkg}`)
.set(HEADERS.ACCEPT, HEADERS.JSON)
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.OK);
expect(response.body.name).toEqual(pkg);
}
);
test.each([['foo-abbreviated'], ['@scope/foo-abbreviated']])(
'should return abbreviated local manifest',
async (pkg) => {
await publishVersion(app, pkg, '1.0.0');
const response = await supertest(app)
.get(`/${pkg}`)
.set(HEADERS.ACCEPT, HEADERS.JSON)
.set(HEADERS.ACCEPT, Storage.ABBREVIATED_HEADER)
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.OK);
expect(response.body.name).toEqual(pkg);
expect(response.body.time).toBeDefined();
expect(response.body.modified).toBeDefined();
expect(response.body[DIST_TAGS]).toEqual({ latest: '1.0.0' });
expect(response.body.readme).not.toBeDefined();
expect(response.body._rev).not.toBeDefined();
expect(response.body.users).not.toBeDefined();
}
);
});
});

View File

@@ -6,11 +6,12 @@ import { initializeServer } from './_helper';
describe('ping', () => {
test('should return the reply the ping', async () => {
return supertest(await initializeServer('ping.yaml'))
const app = await initializeServer('ping.yaml');
const response = await supertest(app)
.get('/-/ping')
.set('Accept', HEADERS.JSON)
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.OK)
.then((response) => expect(response.body).toEqual({}));
.expect(HTTP_STATUS.OK);
expect(response.body).toEqual({});
});
});

View File

@@ -1,11 +1,13 @@
import nock from 'nock';
import { basename } from 'path';
import supertest from 'supertest';
import { HTTP_STATUS } from '@verdaccio/core';
import { API_ERROR, API_MESSAGE, HEADERS, HEADER_TYPE } from '@verdaccio/core';
import { generatePackageMetadata } from '@verdaccio/test-helper';
import { generatePackageMetadata, generateRemotePackageMetadata } from '@verdaccio/test-helper';
import { $RequestExtend, $ResponseExtend } from '../../types/custom';
import { initializeServer, publishVersion } from './_helper';
import { getPackage, initializeServer, publishVersion } from './_helper';
const mockApiJWTmiddleware = jest.fn(
() =>
@@ -33,36 +35,13 @@ jest.mock('@verdaccio/auth', () => ({
},
}));
// const mockStorage = jest.fn(() => {
// const { Storage } = jest.requireActual('@verdaccio/store');
// return {
// Storage: class extends Storage {
// addPackage(name, metadata, cb) {
// super.addPackage(name, metadata, cb);
// }
// }
// };
// });
// jest.mock('@verdaccio/store', () => {
// const { Storage } = jest.requireActual('@verdaccio/store');
// return ({
// Storage: class extends Storage {
// addPackage(name, metadata, cb) {
// // super.addPackage(name, metadata, cb);
// return mockStorage(name, metadata, cb);
// }
// }
// })
// });
describe('publish', () => {
describe('handle invalid publish formats', () => {
describe('handle errors', () => {
const pkgName = 'test';
const pkgMetadata = generatePackageMetadata(pkgName, '1.0.0');
test.skip('should fail on publish a bad _attachments package', async (done) => {
test('should fail on publish a bad _attachments package', async () => {
const app = await initializeServer('publish.yaml');
return supertest(app)
const response = await supertest(app)
.put(`/${encodeURIComponent(pkgName)}`)
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.send(
@@ -73,12 +52,8 @@ describe('publish', () => {
)
)
.set('accept', HEADERS.GZIP)
.expect(HTTP_STATUS.BAD_REQUEST)
.then((response) => {
console.log('response.body', response.body);
expect(response.body.error).toEqual(API_ERROR.UNSUPORTED_REGISTRY_CALL);
done();
});
.expect(HTTP_STATUS.BAD_REQUEST);
expect(response.body.error).toEqual(API_ERROR.UNSUPORTED_REGISTRY_CALL);
});
test('should fail on publish a bad versions package', async () => {
@@ -97,7 +72,6 @@ describe('publish', () => {
.set('accept', HEADERS.GZIP)
.expect(HTTP_STATUS.BAD_REQUEST)
.then((response) => {
console.log('response.body', response.body);
expect(response.body.error).toEqual(API_ERROR.UNSUPORTED_REGISTRY_CALL);
resolve(response);
});
@@ -106,94 +80,179 @@ describe('publish', () => {
});
describe('publish a package', () => {
test('should publish a package', async () => {
const app = await initializeServer('publish.yaml');
return new Promise((resolve) => {
publishVersion(app, 'publish.yaml', 'foo', '1.0.0')
.expect(HTTP_STATUS.CREATED)
.then((response) => {
expect(response.body.ok).toEqual(API_MESSAGE.PKG_CREATED);
resolve(response);
});
});
});
test('should publish a new package', async () => {
const pkgName = 'test';
const pkgMetadata = generatePackageMetadata(pkgName, '1.0.0');
const app = await initializeServer('publish.yaml');
return new Promise((resolve) => {
supertest(app)
.put(`/${encodeURIComponent(pkgName)}`)
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.send(
JSON.stringify(
Object.assign({}, pkgMetadata, {
_attachments: null,
})
)
)
.set('accept', HEADERS.GZIP)
.expect(HTTP_STATUS.CREATED)
.then((response) => {
expect(response.body.ok).toEqual(API_MESSAGE.PKG_CREATED);
resolve(response);
});
});
});
test('should publish a new package with no readme', async () => {
const pkgName = 'test';
const pkgMetadata = generatePackageMetadata(pkgName, '1.0.0');
const app = await initializeServer('publish.yaml');
return new Promise((resolve) => {
supertest(app)
.put(`/${encodeURIComponent(pkgName)}`)
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.send(
JSON.stringify(
Object.assign({}, pkgMetadata, {
versions: {
['1.0.0']: {
readme: null,
},
},
})
)
)
.set('accept', HEADERS.GZIP)
.expect(HTTP_STATUS.CREATED)
.then((response) => {
expect(response.body.ok).toEqual(API_MESSAGE.PKG_CREATED);
resolve(response);
});
});
});
});
test('should fails on publish a duplicated package', async () => {
const app = await initializeServer('publish.yaml');
await publishVersion(app, 'publish.yaml', 'foo', '1.0.0');
return new Promise((resolve) => {
publishVersion(app, 'publish.yaml', 'foo', '1.0.0')
.expect(HTTP_STATUS.CONFLICT)
.then((response) => {
console.log('response.body', response.body);
expect(response.body.error).toEqual(API_ERROR.PACKAGE_EXIST);
resolve(response);
describe('no proxies setup', () => {
test.each([['foo', '@scope/foo']])('should publish a package', async (pkgName) => {
const app = await initializeServer('publish.yaml');
return new Promise((resolve) => {
publishVersion(app, pkgName, '1.0.0')
.expect(HTTP_STATUS.CREATED)
.then((response) => {
expect(response.body.ok).toEqual(API_MESSAGE.PKG_CREATED);
resolve(response);
});
});
});
test.each([['foo', '@scope/foo']])('should publish a new package', async (pkgName) => {
const pkgMetadata = generatePackageMetadata(pkgName, '1.0.0');
const app = await initializeServer('publish.yaml');
return new Promise((resolve) => {
supertest(app)
.put(`/${encodeURIComponent(pkgName)}`)
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.send(JSON.stringify(Object.assign({}, pkgMetadata)))
.set('accept', HEADERS.GZIP)
.expect(HTTP_STATUS.CREATED)
.then((response) => {
expect(response.body.ok).toEqual(API_MESSAGE.PKG_CREATED);
resolve(response);
});
});
});
test('should publish a new package with no readme', async () => {
const pkgName = 'test';
const pkgMetadata = generatePackageMetadata(pkgName, '1.0.0');
const app = await initializeServer('publish.yaml');
return new Promise((resolve) => {
supertest(app)
.put(`/${encodeURIComponent(pkgName)}`)
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.send(
JSON.stringify(
Object.assign({}, pkgMetadata, {
versions: {
['1.0.0']: {
readme: null,
},
},
})
)
)
.set('accept', HEADERS.GZIP)
.expect(HTTP_STATUS.CREATED)
.then((response) => {
expect(response.body.ok).toEqual(API_MESSAGE.PKG_CREATED);
resolve(response);
});
});
});
});
describe('proxies setup', () => {
test.each([['foo', '@scope%2Ffoo']])(
'should publish a a patch package that already exist on a remote',
async (pkgName) => {
const upstreamManifest = generateRemotePackageMetadata(
pkgName,
'1.0.0',
'https://registry.npmjs.org',
['1.0.1', '1.0.2', '1.0.3']
);
nock('https://registry.npmjs.org').get(`/${pkgName}`).reply(200, upstreamManifest);
const app = await initializeServer('publish-proxy.yaml');
const manifest = await getPackage(app, '', decodeURIComponent(pkgName));
expect(manifest.body.name).toEqual(decodeURIComponent(pkgName));
const response = await publishVersion(
app,
decodeURIComponent(pkgName),
'1.0.1-patch'
).expect(HTTP_STATUS.CREATED);
expect(response.body.ok).toEqual(API_MESSAGE.PKG_CREATED);
const response2 = await publishVersion(
app,
decodeURIComponent(pkgName),
'1.0.2-patch'
).expect(HTTP_STATUS.CREATED);
expect(response2.body.ok).toEqual(API_MESSAGE.PKG_CREATED);
}
);
});
});
test.each([['foo', '@scope/foo']])(
'should fails on publish a duplicated package',
async (pkgName) => {
const app = await initializeServer('publish.yaml');
await publishVersion(app, pkgName, '1.0.0');
return new Promise((resolve) => {
publishVersion(app, pkgName, '1.0.0')
.expect(HTTP_STATUS.CONFLICT)
.then((response) => {
expect(response.body.error).toEqual(API_ERROR.PACKAGE_EXIST);
resolve(response);
});
});
}
);
describe('unpublish a package', () => {
let app;
beforeEach(async () => {
app = await initializeServer('publish.yaml');
await publishVersion(app, 'publish.yaml', 'foo', '1.0.0');
test.each([['foo', '@scope/foo']])('should unpublish entirely a package', async (pkgName) => {
const app = await initializeServer('publish.yaml');
await publishVersion(app, pkgName, '1.0.0');
const response = await supertest(app)
// FIXME: should be filtered by revision to avoid
// conflicts
.delete(`/${encodeURIComponent(pkgName)}/-rev/xxx`)
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.expect(HTTP_STATUS.CREATED);
expect(response.body.ok).toEqual(API_MESSAGE.PKG_REMOVED);
// package should be completely un published
await supertest(app)
.get(`/${pkgName}`)
.set('Accept', HEADERS.JSON)
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.NOT_FOUND);
});
test('should unpublish a package', () => {});
test.each([['foo', '@scope/foo']])(
'should fails unpublish entirely a package',
async (pkgName) => {
const app = await initializeServer('publish.yaml');
const response = await supertest(app)
.delete(`/${encodeURIComponent(pkgName)}/-rev/1cf3-fe3`)
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.expect(HTTP_STATUS.NOT_FOUND);
expect(response.body.error).toEqual(API_ERROR.NO_PACKAGE);
}
);
test.each([['foo', '@scope/foo']])(
'should fails remove a tarball of a package does not exist',
async (pkgName) => {
const app = await initializeServer('publish.yaml');
const response = await supertest(app)
.delete(`/${pkgName}/-/${basename(pkgName)}-1.0.3.tgz/-rev/revision`)
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.expect(HTTP_STATUS.NOT_FOUND);
expect(response.body.error).toEqual(API_ERROR.NO_PACKAGE);
}
);
test.each([['foo', '@scope/foo']])(
'should fails on try remove a tarball does not exist',
async (pkgName) => {
const app = await initializeServer('publish.yaml');
await publishVersion(app, pkgName, '1.0.0');
const response = await supertest(app)
.delete(`/${pkgName}/-/${basename(pkgName)}-1.0.3.tgz/-rev/revision`)
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.expect(HTTP_STATUS.NOT_FOUND);
expect(response.body.error).toEqual(API_ERROR.NO_SUCH_FILE);
}
);
test.each([['foo', '@scope/foo']])(
'should remove a tarball that does exist',
async (pkgName) => {
const app = await initializeServer('publish.yaml');
await publishVersion(app, pkgName, '1.0.0');
const response = await supertest(app)
.delete(`/${pkgName}/-/${basename(pkgName)}-1.0.0.tgz/-rev/revision`)
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.expect(HTTP_STATUS.CREATED);
expect(response.body.ok).toEqual(API_MESSAGE.TARBALL_REMOVED);
}
);
});
describe('star a package', () => {});

View File

@@ -0,0 +1,126 @@
import MockDate from 'mockdate';
import supertest from 'supertest';
import { HEADERS, HEADER_TYPE, HTTP_STATUS } from '@verdaccio/core';
import { createUser, initializeServer, publishVersionWithToken } from './_helper';
describe('search', () => {
let app;
beforeEach(async () => {
app = await initializeServer('search.yaml');
});
describe('search authenticated', () => {
test.each([['foo']])('should return a foo private package', async (pkg) => {
const mockDate = '2018-01-14T11:17:40.712Z';
MockDate.set(mockDate);
const res = await createUser(app, 'test', 'test');
await publishVersionWithToken(app, pkg, '1.0.0', res.body.token);
// this should not be displayed as part of the search
await publishVersionWithToken(app, 'private-auth', '1.0.0', res.body.token);
const response = await supertest(app)
.get(
`/-/v1/search?text=${encodeURIComponent(
pkg
)}&size=2000&from=0&quality=1&popularity=0.1&maintenance=0.1`
)
.set(HEADERS.ACCEPT, HEADERS.JSON)
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.expect(HEADERS.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.OK);
expect(response.body).toEqual({
objects: [
{
package: {
author: {
email: 'user@domain.com',
name: 'User NPM',
},
date: mockDate,
description: 'package generated',
keywords: [],
links: {
npm: '',
},
name: pkg,
publisher: {},
scope: '',
version: '1.0.0',
},
score: {
detail: {
maintenance: 0,
popularity: 1,
quality: 1,
},
final: 1,
},
searchScore: 1,
verdaccioPkgCached: false,
verdaccioPrivate: true,
},
],
time: 'Sun, 14 Jan 2018 11:17:40 GMT',
total: 1,
});
});
test.each([['@scope/foo']])('should return a scoped foo private package', async (pkg) => {
const mockDate = '2018-01-14T11:17:40.712Z';
MockDate.set(mockDate);
const res = await createUser(app, 'test', 'test');
await publishVersionWithToken(app, pkg, '1.0.0', res.body.token);
// this should not be displayed as part of the search
await publishVersionWithToken(app, '@private/auth', '1.0.0', res.body.token);
const response = await supertest(app)
.get(
`/-/v1/search?text=${encodeURIComponent(
pkg
)}&size=2000&from=0&quality=1&popularity=0.1&maintenance=0.1`
)
.set(HEADERS.ACCEPT, HEADERS.JSON)
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.expect(HEADERS.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.OK);
expect(response.body).toEqual({
objects: [
{
package: {
author: {
email: 'user@domain.com',
name: 'User NPM',
},
date: mockDate,
description: 'package generated',
keywords: [],
links: {
npm: '',
},
name: pkg,
publisher: {},
scope: '@scope',
version: '1.0.0',
},
score: {
detail: {
maintenance: 0,
popularity: 1,
quality: 1,
},
final: 1,
},
searchScore: 1,
verdaccioPkgCached: false,
verdaccioPrivate: true,
},
],
time: 'Sun, 14 Jan 2018 11:17:40 GMT',
total: 1,
});
});
});
describe('error handling', () => {
test.todo('should able to abort the request');
});
});

View File

@@ -0,0 +1,124 @@
import _ from 'lodash';
import supertest from 'supertest';
import {
API_ERROR,
HEADERS,
HEADER_TYPE,
HTTP_STATUS,
SUPPORT_ERRORS,
TOKEN_BEARER,
} from '@verdaccio/core';
import { buildToken } from '@verdaccio/utils';
import { deleteTokenCLI, generateTokenCLI, getNewToken, initializeServer } from './_helper';
describe('token', () => {
describe('basics', () => {
test.each([['token.yaml'], ['token.jwt.yaml']])('should list empty tokens', async (conf) => {
const app = await initializeServer(conf);
const token = await getNewToken(app, { name: 'jota_token', password: 'secretPass' });
const response = await supertest(app)
.get('/-/npm/v1/tokens')
.set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token))
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.OK);
expect(response.body.objects).toHaveLength(0);
});
test.each([['token.yaml'], ['token.jwt.yaml']])('should generate one token', async (conf) => {
const app = await initializeServer(conf);
const credentials = { name: 'jota_token', password: 'secretPass' };
const token = await getNewToken(app, credentials);
await generateTokenCLI(app, token, {
password: credentials.password,
readonly: false,
cidr_whitelist: [],
});
const response = await supertest(app)
.get('/-/npm/v1/tokens')
.set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token))
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.OK);
const { objects, urls } = response.body;
expect(objects).toHaveLength(1);
const [tokenGenerated] = objects;
expect(tokenGenerated.user).toEqual(credentials.name);
expect(tokenGenerated.readonly).toBeFalsy();
expect(tokenGenerated.token).toMatch(/.../);
expect(_.isString(tokenGenerated.created)).toBeTruthy();
// we don't support pagination yet
expect(urls.next).toEqual('');
});
test.each([['token.yaml'], ['token.jwt.yaml']])('should delete a token', async (conf) => {
const app = await initializeServer(conf);
const credentials = { name: 'jota_token', password: 'secretPass' };
const token = await getNewToken(app, credentials);
const response = await generateTokenCLI(app, token, {
password: credentials.password,
readonly: false,
cidr_whitelist: [],
});
const key = response.body.key;
await deleteTokenCLI(app, token, key);
const response2 = await supertest(app)
.get('/-/npm/v1/tokens')
.set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token))
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.OK);
const { objects } = response2.body;
expect(objects).toHaveLength(0);
});
});
describe('handle errors', () => {
test.each([['token.yaml'], ['token.jwt.yaml']])('should delete a token', async (conf) => {
const app = await initializeServer(conf);
const credentials = { name: 'jota_token', password: 'secretPass' };
const token = await getNewToken(app, credentials);
const resp = await generateTokenCLI(app, token, {
password: 'wrongPassword',
readonly: false,
cidr_whitelist: [],
});
expect(resp.body.error).toEqual(API_ERROR.BAD_USERNAME_PASSWORD);
});
test.each([['token.yaml'], ['token.jwt.yaml']])(
'should fail if readonly is missing',
async (conf) => {
const app = await initializeServer(conf);
const credentials = { name: 'jota_token', password: 'secretPass' };
const token = await getNewToken(app, credentials);
const resp = await generateTokenCLI(app, token, {
password: credentials.password,
cidr_whitelist: [],
});
expect(resp.body.error).toEqual(SUPPORT_ERRORS.PARAMETERS_NOT_VALID);
}
);
});
test.each([['token.yaml'], ['token.jwt.yaml']])(
'should fail if cidr_whitelist is missing',
async (conf) => {
const app = await initializeServer(conf);
const credentials = { name: 'jota_token', password: 'secretPass' };
const token = await getNewToken(app, credentials);
const resp = await generateTokenCLI(app, token, {
password: credentials.password,
readonly: false,
});
expect(resp.body.error).toEqual(SUPPORT_ERRORS.PARAMETERS_NOT_VALID);
}
);
test.todo('handle failure if delete token');
test.todo('handle failure if getApiToken fails');
test.todo('handle failure if token creating fails');
test.todo('handle failure if token list fails');
});

View File

@@ -0,0 +1,78 @@
import supertest from 'supertest';
import { API_ERROR, HEADERS, HEADER_TYPE, HTTP_STATUS, TOKEN_BEARER } from '@verdaccio/core';
import { buildToken } from '@verdaccio/utils';
import { createUser, getPackage, initializeServer } from './_helper';
const FORBIDDEN_VUE = 'authorization required to access package vue';
describe('token', () => {
describe('basics', () => {
const FAKE_TOKEN: string = buildToken(TOKEN_BEARER, 'fake');
test.each([['user.yaml'], ['user.jwt.yaml']])('should test add a new user', async (conf) => {
const app = await initializeServer(conf);
const credentials = { name: 'JotaJWT', password: 'secretPass' };
const response = await createUser(app, credentials.name, credentials.password);
expect(response.body.ok).toMatch(`user '${credentials.name}' created`);
const vueResponse = await getPackage(app, response.body.token, 'vue');
expect(vueResponse.body).toBeDefined();
expect(vueResponse.body.name).toMatch('vue');
const vueFailResp = await getPackage(app, FAKE_TOKEN, 'vue', HTTP_STATUS.UNAUTHORIZED);
expect(vueFailResp.body.error).toMatch(FORBIDDEN_VUE);
});
test.each([['user.yaml'], ['user.jwt.yaml']])('should test add a new user', async (conf) => {
const app = await initializeServer(conf);
const credentials = { name: 'JotaJWT', password: 'secretPass' };
const response = await createUser(app, credentials.name, credentials.password);
expect(response.body.ok).toMatch(`user '${credentials.name}' created`);
const response2 = await supertest(app)
.put(`/-/user/org.couchdb.user:${credentials.name}`)
.send({
name: credentials.name,
password: credentials.password,
})
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.CONFLICT);
expect(response2.body.error).toBe(API_ERROR.USERNAME_ALREADY_REGISTERED);
});
test.each([['user.yaml'], ['user.jwt.yaml']])(
'should fails on login if user credentials are invalid even if jwt',
async (conf) => {
const app = await initializeServer(conf);
const credentials = { name: 'newFailsUser', password: 'secretPass' };
const response = await createUser(app, credentials.name, credentials.password);
expect(response.body.ok).toMatch(`user '${credentials.name}' created`);
const response2 = await supertest(app)
.put(`/-/user/org.couchdb.user:${credentials.name}`)
.send({
name: credentials.name,
password: 'BAD_PASSWORD',
})
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.UNAUTHORIZED);
expect(response2.body.error).toBe(API_ERROR.UNAUTHORIZED_ACCESS);
}
);
test.each([['user.yaml'], ['user.jwt.yaml']])(
'should verify if user is logged',
async (conf) => {
const app = await initializeServer(conf);
const credentials = { name: 'jota', password: 'secretPass' };
const response = await createUser(app, credentials.name, credentials.password);
expect(response.body.ok).toMatch(`user '${credentials.name}' created`);
const response2 = await supertest(app)
.get(`/-/user/org.couchdb.user:${credentials.name}`)
.set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, response.body.token))
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.OK);
expect(response2.body.ok).toBe(`you are authenticated as '${credentials.name}'`);
}
);
});
});

View File

@@ -47,6 +47,7 @@ jest.mock('@verdaccio/auth', () => ({
},
}));
// FIXME: This might be covered with user.jwt.spec
describe('user', () => {
const credentials = { name: 'test', password: 'test' };

View File

@@ -1,53 +1,35 @@
import supertest from 'supertest';
import { HEADERS, HTTP_STATUS } from '@verdaccio/core';
import { HEADERS, HTTP_STATUS, TOKEN_BEARER } from '@verdaccio/core';
import { buildToken } from '@verdaccio/utils';
import { $RequestExtend, $ResponseExtend } from '../../types/custom';
import { initializeServer } from './_helper';
const mockApiJWTmiddleware = jest.fn(
() =>
(req: $RequestExtend, res: $ResponseExtend, _next): void => {
req.remote_user = { name: 'foo', groups: [], real_groups: [] };
_next();
}
);
jest.mock('@verdaccio/auth', () => ({
Auth: class {
apiJWTmiddleware() {
return mockApiJWTmiddleware();
}
allow_access(_d, f_, cb) {
cb(null, true);
}
},
}));
import { createUser, initializeServer } from './_helper';
describe('whoami', () => {
test.skip('should test referer /whoami endpoint', async (done) => {
return supertest(await initializeServer('whoami.yaml'))
.get('/whoami')
.set('referer', 'whoami')
.expect(HTTP_STATUS.OK)
.end(done);
});
test.skip('should test no referer /whoami endpoint', async (done) => {
return supertest(await initializeServer('whoami.yaml'))
.get('/whoami')
.expect(HTTP_STATUS.NOT_FOUND)
.end(done);
});
test('should return the logged username', async () => {
return supertest(await initializeServer('whoami.yaml'))
const app = await initializeServer('whoami.yaml');
// @ts-expect-error internal property
const { _body } = await createUser(app, 'test', 'test');
return supertest(app)
.get('/-/whoami')
.set('Accept', HEADERS.JSON)
.set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, _body.token))
.expect('Content-Type', HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.OK)
.then((response) => {
expect(response.body.username).toEqual('foo');
expect(response.body.username).toEqual('test');
});
});
test('should fails with 401 if is not logged in', async () => {
const app = await initializeServer('whoami.yaml');
// @ts-expect-error internal property
const { _body } = await createUser(app, 'test', 'test');
return supertest(app)
.get('/-/whoami')
.set('Accept', HEADERS.JSON)
.set(HEADERS.AUTHORIZATION, buildToken('invalid-token', _body.token))
.expect('Content-Type', HEADERS.JSON_CHARSET)
.expect(HTTP_STATUS.UNAUTHORIZED);
});
});

View File

@@ -1,49 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Publish endpoints - publish package should change the existing package 1`] = `[MockFunction]`;
exports[`Publish endpoints - publish package should publish a new a new package 1`] = `
[MockFunction] {
"calls": Array [
Array [
"verdaccio",
Object {
"dist-tags": Object {},
"name": "verdaccio",
"time": Object {},
"versions": Object {},
},
[Function],
],
],
"results": Array [
Object {
"type": "return",
"value": undefined,
},
],
}
`;
exports[`Publish endpoints - publish package test start should star a package 1`] = `
[MockFunction] {
"calls": Array [
Array [
"verdaccio",
Object {
"users": Object {
"verdaccio": true,
},
},
"15-e53a77096b0ee33e",
[Function],
],
],
"results": Array [
Object {
"type": "return",
"value": undefined,
},
],
}
`;

View File

@@ -0,0 +1,252 @@
// import { API_ERROR, HTTP_STATUS, errorUtils } from '@verdaccio/core';
// import { addVersion, publishPackage, removeTarball, unPublishPackage } from '../../src/publish';
// const REVISION_MOCK = '15-e53a77096b0ee33e';
// require('@verdaccio/logger').setup([{ type: 'stdout', format: 'pretty', level: 'info' }]);
// describe('Publish endpoints - add a tag', () => {
// let req;
// let res;
// let next;
// beforeEach(() => {
// req = {
// params: {
// version: '1.0.0',
// tag: 'tag',
// package: 'verdaccio',
// },
// body: '',
// };
// res = {
// status: jest.fn(),
// };
// next = jest.fn();
// });
// test('should add a version', (done) => {
// const storage = {
// addVersion: (packageName, version, body, tag, cb) => {
// expect(packageName).toEqual(req.params.package);
// expect(version).toEqual(req.params.version);
// expect(body).toEqual(req.body);
// expect(tag).toEqual(req.params.tag);
// cb();
// done();
// },
// };
// // @ts-ignore
// addVersion(storage)(req, res, next);
// expect(res.status).toHaveBeenLastCalledWith(HTTP_STATUS.CREATED);
// expect(next).toHaveBeenLastCalledWith({ ok: 'package published' });
// });
// test('when failed to add a version', (done) => {
// const storage = {
// addVersion: (packageName, version, body, tag, cb) => {
// const error = {
// message: 'failure',
// };
// cb(error);
// done();
// },
// };
// // @ts-ignore
// addVersion(storage)(req, res, next);
// expect(next).toHaveBeenLastCalledWith({ message: 'failure' });
// });
// });
// /**
// * Delete tarball: '/:package/-/:filename/-rev/:revision'
// */
// describe('Publish endpoints - delete tarball', () => {
// let req;
// let res;
// let next;
// beforeEach(() => {
// req = {
// params: {
// filename: 'verdaccio.gzip',
// package: 'verdaccio',
// revision: REVISION_MOCK,
// },
// };
// res = { status: jest.fn() };
// next = jest.fn();
// });
// test('should delete tarball successfully', (done) => {
// const storage = {
// removeTarball(packageName, filename, revision, cb) {
// expect(packageName).toEqual(req.params.package);
// expect(filename).toEqual(req.params.filename);
// expect(revision).toEqual(req.params.revision);
// cb();
// done();
// },
// };
// // @ts-ignore
// removeTarball(storage)(req, res, next);
// expect(res.status).toHaveBeenCalledWith(HTTP_STATUS.CREATED);
// expect(next).toHaveBeenCalledWith({ ok: 'tarball removed' });
// });
// test('failed while deleting the tarball', (done) => {
// const error = {
// message: 'deletion failed',
// };
// const storage = {
// removeTarball(packageName, filename, revision, cb) {
// cb(error);
// done();
// },
// };
// // @ts-ignore
// removeTarball(storage)(req, res, next);
// expect(next).toHaveBeenCalledWith(error);
// });
// });
// /**
// * Un-publish package: '/:package/-rev/*'
// */
// describe('Publish endpoints - un-publish package', () => {
// let req;
// let res;
// let next;
// beforeEach(() => {
// req = {
// params: {
// package: 'verdaccio',
// },
// };
// res = { status: jest.fn() };
// next = jest.fn();
// });
// test('should un-publish package successfully', async () => {
// const storage = {
// removePackage(packageName) {
// expect(packageName).toEqual(req.params.package);
// return Promise.resolve();
// },
// };
// // @ts-ignore
// await unPublishPackage(storage)(req, res, next);
// expect(res.status).toHaveBeenCalledWith(HTTP_STATUS.CREATED);
// expect(next).toHaveBeenCalledWith({ ok: 'package removed' });
// });
// test('un-publish failed', async () => {
// const storage = {
// removePackage(packageName) {
// expect(packageName).toEqual(req.params.package);
// return Promise.reject(errorUtils.getInternalError());
// },
// };
// // @ts-ignore
// await unPublishPackage(storage)(req, res, next);
// expect(next).toHaveBeenCalledWith(errorUtils.getInternalError());
// });
// });
// /**
// * Publish package: '/:package/:_rev?/:revision?'
// */
// describe('Publish endpoints - publish package', () => {
// let req;
// let res;
// let next;
// beforeEach(() => {
// req = {
// body: {
// name: 'verdaccio',
// },
// params: {
// package: 'verdaccio',
// },
// };
// res = { status: jest.fn() };
// next = jest.fn();
// });
// test('should change the existing package', () => {
// const storage = {
// changePackage: jest.fn(),
// };
// req.params._rev = REVISION_MOCK;
// // @ts-ignore
// publishPackage(storage)(req, res, next);
// expect(storage.changePackage).toMatchSnapshot();
// });
// test('should publish a new a new package', () => {
// const storage = {
// addPackage: jest.fn(),
// };
// // @ts-ignore
// publishPackage(storage)(req, res, next);
// expect(storage.addPackage).toMatchSnapshot();
// });
// test('should throw an error while publishing package', () => {
// const storage = {
// addPackage() {
// throw new Error();
// },
// };
// // @ts-ignore
// publishPackage(storage)(req, res, next);
// expect(next).toHaveBeenCalledWith(new Error(API_ERROR.BAD_PACKAGE_DATA));
// });
// describe('test start', () => {
// test('should star a package', () => {
// const storage = {
// changePackage: jest.fn(),
// getPackage({ callback }) {
// callback(null, {
// users: {},
// });
// },
// };
// req = {
// params: {
// package: 'verdaccio',
// },
// body: {
// _rev: REVISION_MOCK,
// users: {
// verdaccio: true,
// },
// },
// remote_user: {
// name: 'verdaccio',
// },
// };
// // @ts-ignore
// publishPackage(storage)(req, res, next);
// expect(storage.changePackage).toMatchSnapshot();
// });
// });
// });

View File

@@ -1,300 +0,0 @@
import { API_ERROR, HTTP_STATUS, errorUtils } from '@verdaccio/core';
import {
addVersion,
publishPackage,
removeTarball,
unPublishPackage,
uploadPackageTarball,
} from '../../src/publish';
const REVISION_MOCK = '15-e53a77096b0ee33e';
require('@verdaccio/logger').setup([{ type: 'stdout', format: 'pretty', level: 'info' }]);
describe('Publish endpoints - add a tag', () => {
let req;
let res;
let next;
beforeEach(() => {
req = {
params: {
version: '1.0.0',
tag: 'tag',
package: 'verdaccio',
},
body: '',
};
res = {
status: jest.fn(),
};
next = jest.fn();
});
test('should add a version', (done) => {
const storage = {
addVersion: (packageName, version, body, tag, cb) => {
expect(packageName).toEqual(req.params.package);
expect(version).toEqual(req.params.version);
expect(body).toEqual(req.body);
expect(tag).toEqual(req.params.tag);
cb();
done();
},
};
// @ts-ignore
addVersion(storage)(req, res, next);
expect(res.status).toHaveBeenLastCalledWith(HTTP_STATUS.CREATED);
expect(next).toHaveBeenLastCalledWith({ ok: 'package published' });
});
test('when failed to add a version', (done) => {
const storage = {
addVersion: (packageName, version, body, tag, cb) => {
const error = {
message: 'failure',
};
cb(error);
done();
},
};
// @ts-ignore
addVersion(storage)(req, res, next);
expect(next).toHaveBeenLastCalledWith({ message: 'failure' });
});
});
/**
* upload package: '/:package/-/:filename/*'
*/
describe('Publish endpoints - upload package tarball', () => {
let req;
let res;
let next;
beforeEach(() => {
req = {
params: {
filename: 'verdaccio.gzip',
package: 'verdaccio',
},
pipe: jest.fn(),
on: jest.fn(),
};
res = { status: jest.fn(), locals: { report_error: jest.fn() } };
next = jest.fn();
});
test('should upload package tarball successfully', () => {
const stream = {
done: jest.fn(),
abort: jest.fn(),
on: jest.fn(() => (status, cb) => cb()),
};
const storage = {
addTarball(packageName, filename) {
expect(packageName).toEqual(req.params.package);
expect(filename).toEqual(req.params.filename);
return stream;
},
};
// @ts-ignore
uploadPackageTarball(storage)(req, res, next);
expect(req.pipe).toHaveBeenCalled();
expect(req.on).toHaveBeenCalled();
});
});
/**
* Delete tarball: '/:package/-/:filename/-rev/:revision'
*/
describe('Publish endpoints - delete tarball', () => {
let req;
let res;
let next;
beforeEach(() => {
req = {
params: {
filename: 'verdaccio.gzip',
package: 'verdaccio',
revision: REVISION_MOCK,
},
};
res = { status: jest.fn() };
next = jest.fn();
});
test('should delete tarball successfully', (done) => {
const storage = {
removeTarball(packageName, filename, revision, cb) {
expect(packageName).toEqual(req.params.package);
expect(filename).toEqual(req.params.filename);
expect(revision).toEqual(req.params.revision);
cb();
done();
},
};
// @ts-ignore
removeTarball(storage)(req, res, next);
expect(res.status).toHaveBeenCalledWith(HTTP_STATUS.CREATED);
expect(next).toHaveBeenCalledWith({ ok: 'tarball removed' });
});
test('failed while deleting the tarball', (done) => {
const error = {
message: 'deletion failed',
};
const storage = {
removeTarball(packageName, filename, revision, cb) {
cb(error);
done();
},
};
// @ts-ignore
removeTarball(storage)(req, res, next);
expect(next).toHaveBeenCalledWith(error);
});
});
/**
* Un-publish package: '/:package/-rev/*'
*/
describe('Publish endpoints - un-publish package', () => {
let req;
let res;
let next;
beforeEach(() => {
req = {
params: {
package: 'verdaccio',
},
};
res = { status: jest.fn() };
next = jest.fn();
});
test('should un-publish package successfully', async () => {
const storage = {
removePackage(packageName) {
expect(packageName).toEqual(req.params.package);
return Promise.resolve();
},
};
// @ts-ignore
await unPublishPackage(storage)(req, res, next);
expect(res.status).toHaveBeenCalledWith(HTTP_STATUS.CREATED);
expect(next).toHaveBeenCalledWith({ ok: 'package removed' });
});
test('un-publish failed', async () => {
const storage = {
removePackage(packageName) {
expect(packageName).toEqual(req.params.package);
return Promise.reject(errorUtils.getInternalError());
},
};
// @ts-ignore
await unPublishPackage(storage)(req, res, next);
expect(next).toHaveBeenCalledWith(errorUtils.getInternalError());
});
});
/**
* Publish package: '/:package/:_rev?/:revision?'
*/
describe('Publish endpoints - publish package', () => {
let req;
let res;
let next;
beforeEach(() => {
req = {
body: {
name: 'verdaccio',
},
params: {
package: 'verdaccio',
},
};
res = { status: jest.fn() };
next = jest.fn();
});
test('should change the existing package', () => {
const storage = {
changePackage: jest.fn(),
};
req.params._rev = REVISION_MOCK;
// @ts-ignore
publishPackage(storage)(req, res, next);
expect(storage.changePackage).toMatchSnapshot();
});
test('should publish a new a new package', () => {
const storage = {
addPackage: jest.fn(),
};
// @ts-ignore
publishPackage(storage)(req, res, next);
expect(storage.addPackage).toMatchSnapshot();
});
test('should throw an error while publishing package', () => {
const storage = {
addPackage() {
throw new Error();
},
};
// @ts-ignore
publishPackage(storage)(req, res, next);
expect(next).toHaveBeenCalledWith(new Error(API_ERROR.BAD_PACKAGE_DATA));
});
describe('test start', () => {
test('should star a package', () => {
const storage = {
changePackage: jest.fn(),
getPackage({ callback }) {
callback(null, {
users: {},
});
},
};
req = {
params: {
package: 'verdaccio',
},
body: {
_rev: REVISION_MOCK,
users: {
verdaccio: true,
},
},
remote_user: {
name: 'verdaccio',
},
};
// @ts-ignore
publishPackage(storage)(req, res, next);
expect(storage.changePackage).toMatchSnapshot();
});
});
});

View File

@@ -29,7 +29,7 @@
"path": "../middleware"
},
{
"path": "../server"
"path": "../server/express"
},
{
"path": "../store"

View File

@@ -1,5 +1,79 @@
# @verdaccio/auth
## 6.0.0-6-next.26
### Patch Changes
- @verdaccio/core@6.0.0-6-next.47
- @verdaccio/config@6.0.0-6-next.47
- @verdaccio/loaders@6.0.0-6-next.16
- @verdaccio/logger@6.0.0-6-next.15
- verdaccio-htpasswd@11.0.0-6-next.17
- @verdaccio/utils@6.0.0-6-next.15
## 6.0.0-6-next.25
### Patch Changes
- Updated dependencies [b849128d]
- @verdaccio/core@6.0.0-6-next.8
- @verdaccio/config@6.0.0-6-next.17
- @verdaccio/loaders@6.0.0-6-next.15
- @verdaccio/logger@6.0.0-6-next.14
- verdaccio-htpasswd@11.0.0-6-next.16
- @verdaccio/utils@6.0.0-6-next.14
## 6.0.0-6-next.24
### Patch Changes
- 351aeeaa: fix(deps): @verdaccio/utils should be a prod dep of local-storage
- Updated dependencies [351aeeaa]
- @verdaccio/core@6.0.0-6-next.7
- @verdaccio/loaders@6.0.0-6-next.14
- @verdaccio/logger@6.0.0-6-next.13
- verdaccio-htpasswd@11.0.0-6-next.15
- @verdaccio/config@6.0.0-6-next.16
- @verdaccio/utils@6.0.0-6-next.13
## 6.0.0-6-next.23
### Major Changes
- 292c0a37: feat!: replace deprecated request dependency by got
This is a big refactoring of the core, fetching dependencies, improve code, more tests and better stability. This is essential for the next release, will take some time but would allow modularize more the core.
## Notes
- Remove deprecated `request` by other `got`, retry improved, custom Agent ( got does not include it built-in)
- Remove `async` dependency from storage (used by core) it was linked with proxy somehow safe to remove now
- Refactor with promises instead callback wherever is possible
- ~Document the API~
- Improve testing, integration tests
- Bugfix
- Clean up old validations
- Improve performance
## 💥 Breaking changes
- Plugin API methods were callbacks based are returning promises, this will break current storage plugins, check documentation for upgrade.
- Write Tarball, Read Tarball methods parameters change, a new set of options like `AbortController` signals are being provided to the `addAbortSignal` can be internally used with Streams when a request is aborted. eg: `addAbortSignal(signal, fs.createReadStream(pathName));`
- `@verdaccio/streams` stream abort support is legacy is being deprecated removed
- Remove AWS and Google Cloud packages for future refactoring [#2574](https://github.com/verdaccio/verdaccio/pull/2574).
### Patch Changes
- Updated dependencies [292c0a37]
- Updated dependencies [a3a209b5]
- Updated dependencies [00d1d2a1]
- @verdaccio/config@6.0.0-6-next.15
- @verdaccio/core@6.0.0-6-next.6
- @verdaccio/loaders@6.0.0-6-next.13
- @verdaccio/logger@6.0.0-6-next.12
- verdaccio-htpasswd@11.0.0-6-next.14
- @verdaccio/utils@6.0.0-6-next.12
## 6.0.0-6-next.22
### Patch Changes

View File

@@ -1,3 +1,10 @@
const config = require('../../jest/config');
module.exports = Object.assign({}, config, {});
module.exports = Object.assign({}, config, {
coverageThreshold: {
global: {
// FIXME: increase to 90
lines: 42,
},
},
});

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/auth",
"version": "6.0.0-6-next.22",
"version": "6.0.0-6-next.26",
"description": "logger",
"main": "./build/index.js",
"types": "build/index.d.ts",
@@ -30,7 +30,7 @@
},
"scripts": {
"clean": "rimraf ./build",
"test": "cross-env NODE_ENV=test BABEL_ENV=test jest",
"test": "jest",
"type-check": "tsc --noEmit -p tsconfig.build.json",
"build:types": "tsc --emitDeclarationOnly -p tsconfig.build.json",
"build:js": "babel src/ --out-dir build/ --copy-files --extensions \".ts,.tsx\" --source-maps",
@@ -39,20 +39,19 @@
},
"license": "MIT",
"dependencies": {
"@verdaccio/core": "workspace:6.0.0-6-next.5",
"@verdaccio/config": "workspace:6.0.0-6-next.14",
"@verdaccio/loaders": "workspace:6.0.0-6-next.12",
"@verdaccio/logger": "workspace:6.0.0-6-next.11",
"@verdaccio/utils": "workspace:6.0.0-6-next.11",
"debug": "4.3.3",
"express": "4.17.2",
"@verdaccio/core": "workspace:6.0.0-6-next.47",
"@verdaccio/config": "workspace:6.0.0-6-next.47",
"@verdaccio/loaders": "workspace:6.0.0-6-next.16",
"@verdaccio/logger": "workspace:6.0.0-6-next.15",
"@verdaccio/utils": "workspace:6.0.0-6-next.15",
"debug": "4.3.4",
"express": "4.18.1",
"jsonwebtoken": "8.5.1",
"lodash": "4.17.21",
"verdaccio-htpasswd": "workspace:11.0.0-6-next.13"
"verdaccio-htpasswd": "workspace:11.0.0-6-next.17"
},
"devDependencies": {
"@verdaccio/mock": "workspace:6.0.0-6-next.15",
"@verdaccio/types": "workspace:11.0.0-6-next.12"
"@verdaccio/types": "workspace:11.0.0-6-next.16"
},
"funding": {
"type": "opencollective",

View File

@@ -497,10 +497,10 @@ class Auth implements IAuth {
next: Function
): void {
debug('handle legacy api middleware');
debug('api middleware secret %o', secret);
debug('api middleware authorization %o', authorization);
debug('api middleware secret %o', typeof secret === 'string');
debug('api middleware authorization %o', typeof authorization === 'string');
const credentials: any = getMiddlewareCredentials(security, secret, authorization);
debug('api middleware credentials %o', credentials);
debug('api middleware credentials %o', credentials?.name);
if (credentials) {
const { user, password } = credentials;
debug('authenticating %o', user);

View File

@@ -8,6 +8,7 @@ import {
createRemoteUser,
parseConfigFile,
} from '@verdaccio/config';
import { getDefaultConfig } from '@verdaccio/config';
import {
API_ERROR,
CHARACTER_ENCODING,
@@ -16,14 +17,9 @@ import {
errorUtils,
} from '@verdaccio/core';
import { setup } from '@verdaccio/logger';
import { configExample } from '@verdaccio/mock';
import { Config, RemoteUser, Security } from '@verdaccio/types';
import {
AllowActionCallbackResponse,
buildToken,
buildUserBuffer,
getAuthenticatedMessage,
} from '@verdaccio/utils';
import { buildToken, buildUserBuffer, getAuthenticatedMessage } from '@verdaccio/utils';
import type { AllowActionCallbackResponse } from '@verdaccio/utils';
import {
ActionsAllowed,
@@ -58,7 +54,7 @@ describe('Auth utilities', () => {
function getConfig(configFileName: string, secret: string) {
const conf = parseConfigFile(parseConfigurationSecurityFile(configFileName));
// @ts-ignore
const secConf = _.merge(configExample(), conf);
const secConf = _.merge(getDefaultConfig(), conf);
secConf.secret = secret;
const config: Config = new AppConfig(secConf);

View File

@@ -51,7 +51,7 @@ describe('AuthTest', () => {
});
test('should be a fail on login', () => {
const config: Config = new AppConfig(_.cloneDeep(authPluginFailureConf));
const config: Config = new AppConfig(authPluginFailureConf);
config.checkSecretKey('12345');
const auth: IAuth = new Auth(config);

View File

@@ -1,21 +1,24 @@
import path from 'path';
import { configExample as config } from '@verdaccio/mock';
import { getDefaultConfig } from '@verdaccio/config';
export const authProfileConf = config({
export const authProfileConf = {
...getDefaultConfig(),
auth: {
[`${path.join(__dirname, '../partials/plugin/authenticate.success')}`]: {},
},
});
};
export const authPluginFailureConf = config({
export const authPluginFailureConf = {
...getDefaultConfig(),
auth: {
[`${path.join(__dirname, '../partials/plugin/authenticate.fail')}`]: {},
[`${path.join(__dirname, '../partials/plugin/authenticate.fail.js')}`]: {},
},
});
};
export const authPluginPassThrougConf = config({
export const authPluginPassThrougConf = {
...getDefaultConfig(),
auth: {
[`${path.join(__dirname, '../partials/plugin/authenticate.passthroug')}`]: {},
},
});
};

View File

@@ -1,11 +1,11 @@
import { getInternalError } from '@verdaccio/commons-api';
import { errorUtils } from '@verdaccio/core';
module.exports = function () {
return {
authenticate(user, pass, callback) {
// we return an 500 error, the second argument must be false.
// https://verdaccio.org/docs/en/dev-plugins#onerror
callback(getInternalError(), false);
callback(errorUtils.getInternalError(), false);
},
};
};

View File

@@ -1,5 +1,105 @@
# @verdaccio/cli
## 6.0.0-6-next.47
### Patch Changes
- 020ede43: fix: version with breakline
- @verdaccio/core@6.0.0-6-next.47
- @verdaccio/config@6.0.0-6-next.47
- @verdaccio/node-api@6.0.0-6-next.47
- @verdaccio/logger@6.0.0-6-next.15
## 6.0.0-6-next.38
### Patch Changes
- b849128d: fix: handle upload scoped tarball
- Updated dependencies [b849128d]
- @verdaccio/core@6.0.0-6-next.8
- @verdaccio/config@6.0.0-6-next.17
- @verdaccio/logger@6.0.0-6-next.14
- @verdaccio/node-api@6.0.0-6-next.36
## 6.0.0-6-next.37
### Patch Changes
- 351aeeaa: fix(deps): @verdaccio/utils should be a prod dep of local-storage
- Updated dependencies [351aeeaa]
- @verdaccio/core@6.0.0-6-next.7
- @verdaccio/logger@6.0.0-6-next.13
- @verdaccio/node-api@6.0.0-6-next.35
- @verdaccio/config@6.0.0-6-next.16
## 6.0.0-6-next.36
### Patch Changes
- @verdaccio/core@6.0.0-6-next.6
- @verdaccio/logger@6.0.0-6-next.12
- @verdaccio/node-api@6.0.0-6-next.34
## 6.0.0-6-next.35
### Major Changes
- 292c0a37: feat!: replace deprecated request dependency by got
This is a big refactoring of the core, fetching dependencies, improve code, more tests and better stability. This is essential for the next release, will take some time but would allow modularize more the core.
## Notes
- Remove deprecated `request` by other `got`, retry improved, custom Agent ( got does not include it built-in)
- Remove `async` dependency from storage (used by core) it was linked with proxy somehow safe to remove now
- Refactor with promises instead callback wherever is possible
- ~Document the API~
- Improve testing, integration tests
- Bugfix
- Clean up old validations
- Improve performance
## 💥 Breaking changes
- Plugin API methods were callbacks based are returning promises, this will break current storage plugins, check documentation for upgrade.
- Write Tarball, Read Tarball methods parameters change, a new set of options like `AbortController` signals are being provided to the `addAbortSignal` can be internally used with Streams when a request is aborted. eg: `addAbortSignal(signal, fs.createReadStream(pathName));`
- `@verdaccio/streams` stream abort support is legacy is being deprecated removed
- Remove AWS and Google Cloud packages for future refactoring [#2574](https://github.com/verdaccio/verdaccio/pull/2574).
- a3a209b5: feat: migrate to pino.js 8
### Minor Changes
- 00d1d2a1: chore: env variable for launch fastify
- Update fastify to major release `v4.3.0`
- Update CLI launcher
via CLI
```
VERDACCIO_SERVER=fastify verdaccio
```
with docker
```
docker run -it --rm --name verdaccio \
-e "VERDACCIO_SERVER=8080" -p 8080:8080 \
-e "VERDACCIO_SERVER=fastify" \
verdaccio/verdaccio
```
### Patch Changes
- Updated dependencies [292c0a37]
- Updated dependencies [a3a209b5]
- Updated dependencies [00d1d2a1]
- @verdaccio/config@6.0.0-6-next.15
- @verdaccio/core@6.0.0-6-next.6
- @verdaccio/logger@6.0.0-6-next.12
- @verdaccio/node-api@6.0.0-6-next.33
## 6.0.0-6-next.34
### Patch Changes
@@ -13,7 +113,7 @@
- Updated dependencies [d43894e8]
- Updated dependencies [d08fe29d]
- @verdaccio/config@6.0.0-6-next.14
- @verdaccio/fastify-migration@6.0.0-6-next.23
- @verdaccio/server-fastify@6.0.0-6-next.23
- @verdaccio/node-api@6.0.0-6-next.31
- @verdaccio/core@6.0.0-6-next.5
- @verdaccio/logger@6.0.0-6-next.11
@@ -59,20 +159,20 @@
- @verdaccio/core@6.0.0-6-next.5
- @verdaccio/logger@6.0.0-6-next.11
- @verdaccio/node-api@6.0.0-6-next.30
- @verdaccio/fastify-migration@6.0.0-6-next.22
- @verdaccio/server-fastify@6.0.0-6-next.22
## 6.0.0-6-next.30
### Patch Changes
- @verdaccio/fastify-migration@6.0.0-6-next.21
- @verdaccio/server-fastify@6.0.0-6-next.21
- @verdaccio/node-api@6.0.0-6-next.29
## 6.0.0-6-next.29
### Patch Changes
- @verdaccio/fastify-migration@6.0.0-6-next.20
- @verdaccio/server-fastify@6.0.0-6-next.20
- @verdaccio/node-api@6.0.0-6-next.28
## 6.0.0-6-next.28
@@ -81,7 +181,7 @@
- Updated dependencies [b78f3525]
- @verdaccio/logger@6.0.0-6-next.10
- @verdaccio/fastify-migration@6.0.0-6-next.19
- @verdaccio/server-fastify@6.0.0-6-next.19
- @verdaccio/node-api@6.0.0-6-next.27
## 6.0.0-6-next.27
@@ -91,7 +191,7 @@
- Updated dependencies [730b5d8c]
- @verdaccio/logger@6.0.0-6-next.9
- @verdaccio/node-api@6.0.0-6-next.26
- @verdaccio/fastify-migration@6.0.0-6-next.18
- @verdaccio/server-fastify@6.0.0-6-next.18
## 6.0.0-6-next.26
@@ -100,7 +200,7 @@
- Updated dependencies [a828271d]
- Updated dependencies [24b9be02]
- Updated dependencies [e75c0a3b]
- @verdaccio/fastify-migration@6.0.0-6-next.17
- @verdaccio/server-fastify@6.0.0-6-next.17
- @verdaccio/core@6.0.0-6-next.4
- @verdaccio/logger@6.0.0-6-next.8
- @verdaccio/node-api@6.0.0-6-next.25
@@ -112,7 +212,7 @@
- Updated dependencies [f86c31ed]
- Updated dependencies [20c9e43e]
- @verdaccio/fastify-migration@6.0.0-6-next.16
- @verdaccio/server-fastify@6.0.0-6-next.16
- @verdaccio/config@6.0.0-6-next.11
- @verdaccio/node-api@6.0.0-6-next.24
@@ -129,7 +229,7 @@
- @verdaccio/logger@6.0.0-6-next.7
- @verdaccio/node-api@6.0.0-6-next.23
- @verdaccio/config@6.0.0-6-next.10
- @verdaccio/fastify-migration@6.0.0-6-next.15
- @verdaccio/server-fastify@6.0.0-6-next.15
## 6.0.0-6-next.23
@@ -149,7 +249,7 @@
- Updated dependencies [b702ea36]
- Updated dependencies [154b2ecd]
- @verdaccio/config@6.0.0-6-next.9
- @verdaccio/fastify-migration@6.0.0-6-next.14
- @verdaccio/server-fastify@6.0.0-6-next.14
- @verdaccio/logger@6.0.0-6-next.6
- @verdaccio/node-api@6.0.0-6-next.22
@@ -159,7 +259,7 @@
- Updated dependencies [2c594910]
- @verdaccio/logger@6.0.0-6-next.5
- @verdaccio/fastify-migration@6.0.0-6-next.13
- @verdaccio/server-fastify@6.0.0-6-next.13
- @verdaccio/node-api@6.0.0-6-next.21
## 6.0.0-6-next.21
@@ -203,7 +303,7 @@
- Updated dependencies [459b6fa7]
- @verdaccio/config@6.0.0-6-next.8
- @verdaccio/fastify-migration@6.0.0-6-next.12
- @verdaccio/server-fastify@6.0.0-6-next.12
- @verdaccio/node-api@6.0.0-6-next.20
- @verdaccio/logger@6.0.0-6-next.4
@@ -212,7 +312,7 @@
### Patch Changes
- Updated dependencies [df0da3d6]
- @verdaccio/fastify-migration@6.0.0-6-next.11
- @verdaccio/server-fastify@6.0.0-6-next.11
- @verdaccio/node-api@6.0.0-6-next.19
## 6.0.0-6-next.19
@@ -236,7 +336,7 @@
### Patch Changes
- Updated dependencies [55ee3fdd]
- @verdaccio/fastify-migration@6.0.0-6-next.10
- @verdaccio/server-fastify@6.0.0-6-next.10
- @verdaccio/config@6.0.0-6-next.7
- @verdaccio/node-api@6.0.0-6-next.17
@@ -250,7 +350,7 @@
### Patch Changes
- @verdaccio/fastify-migration@6.0.0-6-next.9
- @verdaccio/server-fastify@6.0.0-6-next.9
- @verdaccio/logger@6.0.0-6-next.4
- @verdaccio/node-api@6.0.0-6-next.15
@@ -258,7 +358,7 @@
### Patch Changes
- @verdaccio/fastify-migration@6.0.0-6-next.9
- @verdaccio/server-fastify@6.0.0-6-next.9
- @verdaccio/logger@6.0.0-6-next.4
- @verdaccio/node-api@6.0.0-6-next.14
@@ -291,7 +391,7 @@
- Updated dependencies [19d272d1]
- @verdaccio/node-api@6.0.0-6-next.12
- @verdaccio/fastify-migration@6.0.0-6-next.9
- @verdaccio/server-fastify@6.0.0-6-next.9
- @verdaccio/logger@6.0.0-6-next.4
## 6.0.0-6-next.11

View File

@@ -1 +1,10 @@
module.exports = require('../../jest/config');
const config = require('../../jest/config');
module.exports = Object.assign({}, config, {
coverageThreshold: {
global: {
// FIXME: increase to 90
lines: 4,
},
},
});

View File

@@ -1,6 +1,6 @@
{
"name": "@verdaccio/cli",
"version": "6.0.0-6-next.34",
"version": "6.0.0-6-next.47",
"author": {
"name": "Juan Picado",
"email": "juanpicado19@gmail.com"
@@ -35,7 +35,7 @@
"types": "build/index.d.ts",
"scripts": {
"clean": "rimraf ./build",
"test": "cross-env NODE_ENV=test BABEL_ENV=test jest",
"test": "jest",
"type-check": "tsc --noEmit -p tsconfig.build.json",
"build:types": "tsc --emitDeclarationOnly -p tsconfig.build.json",
"build:js": "babel src/ --out-dir build/ --copy-files --extensions \".ts,.tsx\" --source-maps",
@@ -44,18 +44,17 @@
"start": "ts-node src/index.ts"
},
"dependencies": {
"@verdaccio/core": "workspace:6.0.0-6-next.5",
"@verdaccio/config": "workspace:6.0.0-6-next.14",
"@verdaccio/logger": "workspace:6.0.0-6-next.11",
"@verdaccio/node-api": "workspace:6.0.0-6-next.32",
"@verdaccio/fastify-migration": "workspace:6.0.0-6-next.23",
"@verdaccio/core": "workspace:6.0.0-6-next.47",
"@verdaccio/config": "workspace:6.0.0-6-next.47",
"@verdaccio/logger": "workspace:6.0.0-6-next.15",
"@verdaccio/node-api": "workspace:6.0.0-6-next.47",
"clipanion": "3.1.0",
"envinfo": "7.8.1",
"kleur": "3.0.3",
"semver": "7.3.5"
"semver": "7.3.7"
},
"devDependencies": {
"ts-node": "10.4.0"
"ts-node": "10.9.1"
},
"funding": {
"type": "opencollective",

View File

@@ -2,7 +2,6 @@ import { Cli } from 'clipanion';
import { warningUtils } from '@verdaccio/core';
import { FastifyServer } from './commands/FastifyServer';
import { InfoCommand } from './commands/info';
import { InitCommand } from './commands/init';
import { VersionCommand } from './commands/version';
@@ -30,7 +29,6 @@ const cli = new Cli({
cli.register(InfoCommand);
cli.register(InitCommand);
cli.register(VersionCommand);
cli.register(FastifyServer);
cli.runExit(args, Cli.defaultContext);
process.on('uncaughtException', function (err) {

View File

@@ -1,58 +0,0 @@
import { Command, Option } from 'clipanion';
import { findConfigFile, parseConfigFile } from '@verdaccio/config';
import server from '@verdaccio/fastify-migration';
import { logger, setup } from '@verdaccio/logger';
import { ConfigRuntime } from '@verdaccio/types';
export const DEFAULT_PROCESS_NAME: string = 'verdaccio';
/**
* This command is intended to run the server with Fastify
* as a migration step.
* More info: https://github.com/verdaccio/verdaccio/discussions/2155
* To try out.
* pnpm debug:fastify
*/
export class FastifyServer extends Command {
public static paths = [['fastify-server']];
private port = Option.String('-l,-p,--listen,--port', {
description: 'host:port number to listen on (default: localhost:4873)',
});
private config = Option.String('-c,--config', {
description: 'use this configuration file (default: ./config.yaml)',
});
private initLogger(logConfig: ConfigRuntime) {
try {
if (logConfig.log) {
throw Error('logger as array not longer supported');
}
// FUTURE: remove fallback when is ready
setup(logConfig.log);
} catch (err: any) {
throw new Error(err);
}
}
public async execute() {
try {
const configPathLocation = findConfigFile(this.config as string);
const configParsed = parseConfigFile(configPathLocation);
const { web } = configParsed;
this.initLogger(configParsed);
process.title = web?.title || DEFAULT_PROCESS_NAME;
// FIXME: need a way to get version of the package.
// const { version, name } = require('../../package.json');
const ser = await server({ logger, config: configParsed });
// FIXME: harcoded, this would need to come from the configuration and the --listen flag.
await ser.listen(process.env.PORT || 4873);
} catch (err: any) {
console.error(err);
process.exit(1);
}
}
}

Some files were not shown because too many files have changed in this diff Show More