mirror of
https://github.com/SomboChea/ui
synced 2026-01-13 06:35:44 +07:00
Compare commits
44 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8365b9654 | ||
|
|
bd7329f807 | ||
|
|
023b1159f7 | ||
|
|
e81cb308ea | ||
|
|
937d15947b | ||
|
|
01da082c06 | ||
|
|
980dac5b2f | ||
|
|
233ba196a0 | ||
|
|
c9fb3c4c50 | ||
|
|
3d752e079c | ||
|
|
7f07a322f4 | ||
|
|
9ffa6290cc | ||
|
|
47b98c5550 | ||
|
|
da4ac7e851 | ||
|
|
c960fa76db | ||
|
|
5e43ac0d49 | ||
|
|
4e899a8574 | ||
|
|
01daf73bbf | ||
|
|
a89f363115 | ||
|
|
c3eac3d27b | ||
|
|
9d7be476ad | ||
|
|
1070e5c3aa | ||
|
|
11f50919ef | ||
|
|
ea1ebde2f1 | ||
|
|
c4cb559137 | ||
|
|
e8fd59696e | ||
|
|
fc114298ad | ||
|
|
86bda48b79 | ||
|
|
d6a8f5519f | ||
|
|
eda98b817e | ||
|
|
12da966254 | ||
|
|
4ee6c2dfe4 | ||
|
|
13d999369d | ||
|
|
cc30d0b249 | ||
|
|
6f108370ce | ||
|
|
f9da05744b | ||
|
|
414aaa3d84 | ||
|
|
4a459df463 | ||
|
|
96b65d969a | ||
|
|
f000438b86 | ||
|
|
7bde18c8d9 | ||
|
|
3a63fba339 | ||
|
|
6fcb415091 | ||
|
|
dc5b14821b |
@@ -2,16 +2,16 @@ version: 2
|
||||
|
||||
aliases:
|
||||
- &defaults
|
||||
working_directory: ~/verdaccio
|
||||
working_directory: ~/ui-theme
|
||||
- &node11_executor
|
||||
docker:
|
||||
- image: circleci/node:11.10.1
|
||||
- &node8_executor
|
||||
docker:
|
||||
- image: circleci/node:8
|
||||
- &node10_executor
|
||||
docker:
|
||||
- image: circleci/node:10
|
||||
- &node11_executor
|
||||
docker:
|
||||
- image: circleci/node:11.10.1
|
||||
- &default_executor
|
||||
<<: *node10_executor
|
||||
- &repo_key
|
||||
@@ -23,21 +23,20 @@ aliases:
|
||||
- &yarn_cache_key
|
||||
yarn-sha-{{ checksum "yarn.lock" }}
|
||||
- &restore_repo
|
||||
attach_workspace:
|
||||
at: ~/verdaccio
|
||||
restore_cache:
|
||||
keys:
|
||||
- *repo_key
|
||||
- &ignore_non_dev_branches
|
||||
filters:
|
||||
tags:
|
||||
only: /.*/
|
||||
branches:
|
||||
ignore:
|
||||
- gh-pages
|
||||
- l10n_master
|
||||
- /release\/.*/
|
||||
- &execute_on_release
|
||||
filters:
|
||||
tags:
|
||||
only: /v?[0-9]+(\.[0-9]+)+([-+\.][0-9a-zA-Z]+)*/
|
||||
only: /(v)?[0-9]+(\.[0-9]+)*/
|
||||
branches:
|
||||
ignore:
|
||||
- /.*/
|
||||
@@ -47,43 +46,45 @@ jobs:
|
||||
<<: *defaults
|
||||
<<: *default_executor
|
||||
steps:
|
||||
- *restore_repo
|
||||
- checkout
|
||||
- restore_cache:
|
||||
key: *base_config_key
|
||||
- run:
|
||||
name: 'Base environment setup'
|
||||
command: |
|
||||
git config --global user.email "verdacciobot@users.noreply.github.com"
|
||||
git config --global user.name "Verdaccio bot for Deployments"
|
||||
echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
|
||||
echo "machine github.com login verdacciobot password $GITHUB_TOKEN" > ~/.netrc
|
||||
command: echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
|
||||
- save_cache:
|
||||
key: *base_config_key
|
||||
paths:
|
||||
- ~/.npmrc
|
||||
- ~/.gitconfig
|
||||
- ~/.netrc
|
||||
- restore_cache:
|
||||
key: *yarn_cache_key
|
||||
- run:
|
||||
name: Install Js dependencies
|
||||
command: yarn install --no-progress --registry https://registry.verdaccio.org
|
||||
- run:
|
||||
name: Prepare CI
|
||||
command: yarn lint
|
||||
command: yarn install --no-progress --registry https://registry.verdaccio.org --no-lockfile
|
||||
- run:
|
||||
name: Build project
|
||||
command: yarn build
|
||||
command: yarn run build
|
||||
- save_cache:
|
||||
key: *yarn_cache_key
|
||||
paths:
|
||||
- ~/.yarn
|
||||
- ~/.cache/yarn
|
||||
- node_modules
|
||||
- persist_to_workspace:
|
||||
root: ~/verdaccio
|
||||
- save_cache:
|
||||
key: *repo_key
|
||||
paths:
|
||||
- ./*
|
||||
- ~/ui-theme
|
||||
|
||||
test_node11:
|
||||
<<: *defaults
|
||||
<<: *node11_executor
|
||||
steps:
|
||||
- *restore_repo
|
||||
- run:
|
||||
name: Test with Node 11
|
||||
command: yarn run test
|
||||
|
||||
test_node8:
|
||||
<<: *defaults
|
||||
@@ -92,8 +93,8 @@ jobs:
|
||||
- *restore_repo
|
||||
- run:
|
||||
name: Test with Node 8
|
||||
command: |
|
||||
yarn test
|
||||
command: yarn test
|
||||
|
||||
test_node10:
|
||||
<<: *defaults
|
||||
<<: *node10_executor
|
||||
@@ -101,18 +102,12 @@ jobs:
|
||||
- *restore_repo
|
||||
- run:
|
||||
name: Test with Node 10
|
||||
command: |
|
||||
yarn test
|
||||
command: yarn run test
|
||||
- save_cache:
|
||||
key: *coverage_key
|
||||
paths:
|
||||
- coverage
|
||||
|
||||
test_node11:
|
||||
<<: *defaults
|
||||
<<: *node11_executor
|
||||
steps:
|
||||
- *restore_repo
|
||||
- run:
|
||||
name: Test with Node 11
|
||||
command: |
|
||||
yarn run test
|
||||
coverage:
|
||||
<<: *defaults
|
||||
<<: *default_executor
|
||||
@@ -141,7 +136,7 @@ jobs:
|
||||
key: *base_config_key
|
||||
- run:
|
||||
name: Publish
|
||||
command: scripts/publish.sh
|
||||
command: yarn publish
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
@@ -149,6 +144,10 @@ workflows:
|
||||
jobs:
|
||||
- prepare:
|
||||
<<: *ignore_non_dev_branches
|
||||
- test_node11:
|
||||
requires:
|
||||
- prepare
|
||||
<<: *ignore_non_dev_branches
|
||||
- test_node8:
|
||||
requires:
|
||||
- prepare
|
||||
@@ -157,15 +156,11 @@ workflows:
|
||||
requires:
|
||||
- prepare
|
||||
<<: *ignore_non_dev_branches
|
||||
- test_node11:
|
||||
requires:
|
||||
- prepare
|
||||
<<: *ignore_non_dev_branches
|
||||
- coverage:
|
||||
requires:
|
||||
- test_node11
|
||||
- test_node8
|
||||
- test_node10
|
||||
- test_node11
|
||||
<<: *ignore_non_dev_branches
|
||||
- publish_package:
|
||||
requires:
|
||||
|
||||
37
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
Normal file
37
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Docker || Kubernetes (please complete the following information):**
|
||||
- Docker verdaccio tag: [e.g. verdaccio:beta]
|
||||
- Docker commands [e.g. docker pull ...]
|
||||
- Docker Version [e.g. v18.05.0-ce-rc1]
|
||||
|
||||
**Configuration File (cat ~/.config/verdaccio/config.yaml)**
|
||||
|
||||
**Debugging output**
|
||||
- `$ NODE_DEBUG=request verdaccio` display request calls (verdaccio <--> uplinks)
|
||||
- `$ DEBUG=express:* verdaccio` enable extreme verdaccio debug mode (verdaccio api)
|
||||
- `$ npm -ddd` prints:
|
||||
- `$ npm config get registry` prints:
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
17
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
Normal file
17
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
32
.github/issue_template.md
vendored
Normal file
32
.github/issue_template.md
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
<!--
|
||||
First of all, please read this section
|
||||
|
||||
https://github.com/verdaccio/verdaccio/blob/master/CONTRIBUTING.md#reporting-a-bug
|
||||
|
||||
Some advices before file an issue
|
||||
* Give a brief explanation of the issue, suggestion or feature to request.
|
||||
* If the issue is a question, provide as much information you have available.
|
||||
* How can I do in order to reproduce it? What environment?
|
||||
* Define which version the issue happens and whether previous version the behavior is correct.
|
||||
* Provide your config file is really helpful. Please be aware to hide sensitive data (passwords, server IP, etc) before post.
|
||||
-->
|
||||
|
||||
#### My reason:
|
||||
#### Steps to reproduce:
|
||||
#### App Version:
|
||||
#### Config file:
|
||||
#### Additional information:
|
||||
|
||||
- `$ NODE_DEBUG=request verdaccio` display request calls (verdaccio <--> uplinks)
|
||||
- `$ DEBUG=express:* verdaccio` enable extreme verdaccio debug mode (verdaccio api)
|
||||
- `$ npm -ddd` prints:
|
||||
- `$ npm config get registry` prints:
|
||||
- Verdaccio terminal output
|
||||
- Which (Windows, OS X/macOS, or Linux) environment are you running verdaccio?:
|
||||
- Verdaccio configuration file, eg: `cat ~/.config/verdaccio/config.yaml`
|
||||
- Container Options:
|
||||
- Docker?:
|
||||
- Kubernetes?:
|
||||
|
||||
#### Additional verbose log:
|
||||
|
||||
230
.github/main.workflow
vendored
Normal file
230
.github/main.workflow
vendored
Normal file
@@ -0,0 +1,230 @@
|
||||
################################################
|
||||
# Workflow for a branch push
|
||||
################################################
|
||||
workflow "build and test on branch" {
|
||||
resolves = [
|
||||
"branch.lint.node.10",
|
||||
"branch.test.node.10",
|
||||
"branch.test.node.8",
|
||||
# "branch.test.node.12"
|
||||
]
|
||||
on = "push"
|
||||
}
|
||||
|
||||
# node 10
|
||||
action "branch.filter" {
|
||||
uses = "actions/bin/filter@master"
|
||||
args = "branch"
|
||||
}
|
||||
|
||||
action "branch.install.node.10" {
|
||||
needs = ["branch.filter"]
|
||||
uses = "docker://node:10"
|
||||
args = "yarn install"
|
||||
}
|
||||
|
||||
action "branch.build.node.10" {
|
||||
uses = "docker://node:10"
|
||||
needs = ["branch.install.node.10"]
|
||||
args = "yarn run build"
|
||||
}
|
||||
|
||||
action "branch.lint.node.10" {
|
||||
uses = "docker://node:10"
|
||||
needs = ["branch.install.node.10"]
|
||||
args = "yarn run lint"
|
||||
}
|
||||
|
||||
action "branch.test.node.10" {
|
||||
uses = "docker://node:10"
|
||||
needs = ["branch.build.node.10"]
|
||||
args = "yarn run test"
|
||||
}
|
||||
|
||||
# node 8
|
||||
action "branch.install.node.8" {
|
||||
needs = ["branch.filter"]
|
||||
uses = "docker://node:8"
|
||||
args = "yarn install"
|
||||
}
|
||||
|
||||
action "branch.build.node.8" {
|
||||
uses = "docker://node:8"
|
||||
needs = ["branch.install.node.8"]
|
||||
args = "yarn run build"
|
||||
}
|
||||
|
||||
action "branch.test.node.8" {
|
||||
uses = "docker://node:8"
|
||||
needs = ["branch.build.node.8"]
|
||||
args = "yarn run test"
|
||||
}
|
||||
|
||||
# @todo node 12
|
||||
# action "branch.install.node.12" {
|
||||
# needs = ["branch.filter"]
|
||||
# uses = "docker://node:12"
|
||||
# args = "yarn install"
|
||||
# }
|
||||
|
||||
# action "branch.build.node.12" {
|
||||
# uses = "docker://node:12"
|
||||
# needs = ["branch.install.node.12"]
|
||||
# args = "yarn run build"
|
||||
# }
|
||||
|
||||
# action "branch.test.node.12" {
|
||||
# uses = "docker://node:12"
|
||||
# needs = ["branch.build.node.12"]
|
||||
# args = "yarn run test"
|
||||
# }
|
||||
|
||||
################################################
|
||||
# Workflow for a Pull request
|
||||
################################################
|
||||
workflow "build and test on PR" {
|
||||
resolves = [
|
||||
"pr.lint.node.10",
|
||||
"pr.test.node.10",
|
||||
"pr.test.node.8",
|
||||
# "pr.test.node.12"
|
||||
]
|
||||
on = "pull_request"
|
||||
}
|
||||
|
||||
# node 10
|
||||
action "pr.filter" {
|
||||
uses = "actions/bin/filter@master"
|
||||
args = "action 'opened|synchronize|reopened'"
|
||||
}
|
||||
|
||||
action "pr.install.node.10" {
|
||||
needs = ["pr.filter"]
|
||||
uses = "docker://node:10"
|
||||
args = "yarn install"
|
||||
}
|
||||
|
||||
action "pr.build.node.10" {
|
||||
uses = "docker://node:10"
|
||||
needs = ["pr.install.node.10"]
|
||||
args = "yarn run build"
|
||||
}
|
||||
|
||||
action "pr.lint.node.10" {
|
||||
uses = "docker://node:10"
|
||||
needs = ["pr.install.node.10"]
|
||||
args = "yarn run lint"
|
||||
}
|
||||
|
||||
action "pr.test.node.10" {
|
||||
uses = "docker://node:10"
|
||||
needs = ["pr.build.node.10"]
|
||||
args = "yarn run test"
|
||||
}
|
||||
|
||||
# node 8
|
||||
action "pr.install.node.8" {
|
||||
needs = ["pr.filter"]
|
||||
uses = "docker://node:8"
|
||||
args = "yarn install"
|
||||
}
|
||||
|
||||
action "pr.build.node.8" {
|
||||
uses = "docker://node:8"
|
||||
needs = ["pr.install.node.8"]
|
||||
args = "yarn run build"
|
||||
}
|
||||
|
||||
action "pr.test.node.8" {
|
||||
uses = "docker://node:8"
|
||||
needs = ["pr.build.node.8"]
|
||||
args = "yarn run test"
|
||||
}
|
||||
|
||||
# @todo node 12
|
||||
# action "pr.install.node.12" {
|
||||
# needs = ["pr.filter"]
|
||||
# uses = "docker://node:12"
|
||||
# args = "yarn install"
|
||||
# }
|
||||
|
||||
# action "pr.build.node.12" {
|
||||
# uses = "docker://node:12"
|
||||
# needs = ["pr.install.node.12"]
|
||||
# args = "yarn run build"
|
||||
# }
|
||||
|
||||
# action "pr.test.node.12" {
|
||||
# uses = "docker://node:12"
|
||||
# needs = ["pr.build.node.12"]
|
||||
# args = "yarn run test"
|
||||
# }
|
||||
|
||||
|
||||
################################################
|
||||
# Workflow for a github release when a tag is
|
||||
# pushed
|
||||
################################################
|
||||
workflow "github release" {
|
||||
resolves = [
|
||||
"release.github",
|
||||
"release.lint",
|
||||
]
|
||||
on = "push"
|
||||
}
|
||||
|
||||
action "release.filter" {
|
||||
uses = "actions/bin/filter@master"
|
||||
args = "tag v*"
|
||||
}
|
||||
|
||||
action "release.install" {
|
||||
uses = "docker://node:10"
|
||||
needs = ["release.filter"]
|
||||
args = "yarn install"
|
||||
}
|
||||
|
||||
action "release.build" {
|
||||
uses = "docker://node:10"
|
||||
needs = ["release.install"]
|
||||
args = "yarn run build"
|
||||
}
|
||||
|
||||
action "release.lint" {
|
||||
uses = "docker://node:10"
|
||||
needs = ["release.install"]
|
||||
args = "yarn run lint"
|
||||
}
|
||||
|
||||
action "release.test" {
|
||||
uses = "docker://node:10"
|
||||
needs = ["release.build"]
|
||||
args = "yarn run test"
|
||||
}
|
||||
|
||||
action "release.auth" {
|
||||
needs = ["release.test"]
|
||||
uses = "actions/bin/filter@master"
|
||||
args = ["actor", "octocat", "torvalds"]
|
||||
}
|
||||
|
||||
action "release.npm.publish" {
|
||||
needs = ["release.auth"]
|
||||
uses = "docker://node:10"
|
||||
args = "sh scripts/publish.sh"
|
||||
secrets = [
|
||||
"REGISTRY_AUTH_TOKEN",
|
||||
]
|
||||
env = {
|
||||
REGISTRY_URL = "registry.npmjs.org"
|
||||
}
|
||||
}
|
||||
|
||||
action "release.github" {
|
||||
needs = ["release.npm.publish"]
|
||||
uses = "docker://node:10"
|
||||
args = "sh scripts/github-release.sh"
|
||||
secrets = [
|
||||
"GITHUB_TOKEN",
|
||||
]
|
||||
}
|
||||
27
.github/pull_request_template.md
vendored
Normal file
27
.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<!--
|
||||
|
||||
Before Pull Request check whether your commits follow this convention
|
||||
|
||||
https://github.com/verdaccio/verdaccio/blob/master/CONTRIBUTING.md#git-commit-guidelines
|
||||
|
||||
* If your PR fix an issue don't forget to update the unit test and documentation in /docs folder
|
||||
* If your PR delivers a new feature, please, provide examples and why such feature should be considered.
|
||||
* Document your changes /docs
|
||||
* Add unit test
|
||||
* Follow the commit guidelines in order to get a quick approval
|
||||
|
||||
Pick one/multiple type, if none apply please suggest one, we might be included it by default
|
||||
|
||||
eg: bug / feature / documentation / unit test / build
|
||||
|
||||
-->
|
||||
**Type:**
|
||||
|
||||
The following has been addressed in the PR:
|
||||
|
||||
* There is a related issue?
|
||||
* Unit or Functional tests are included in the PR
|
||||
|
||||
**Description:**
|
||||
|
||||
<!-- Resolves #??? -->
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -16,4 +16,4 @@ __tests__
|
||||
# Compiled script
|
||||
static/*
|
||||
coverage/
|
||||
|
||||
stats.json
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
|
||||
## npm
|
||||
/*
|
||||
!/static/*
|
||||
!/static/**/*
|
||||
!index.js
|
||||
!README.md
|
||||
|
||||
|
||||
97
CHANGELOG.md
97
CHANGELOG.md
@@ -2,5 +2,102 @@
|
||||
|
||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||
|
||||
<a name="0.1.10"></a>
|
||||
## [0.1.10](https://github.com/verdaccio/ui/compare/v0.1.9...v0.1.10) (2019-05-17)
|
||||
|
||||
|
||||
|
||||
<a name="0.1.9"></a>
|
||||
## [0.1.9](https://github.com/verdaccio/ui/compare/v0.1.8...v0.1.9) (2019-05-16)
|
||||
|
||||
|
||||
|
||||
<a name="0.1.8"></a>
|
||||
## [0.1.8](https://github.com/verdaccio/ui/compare/v0.1.7...v0.1.8) (2019-05-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* use auto for overflow-y ([#57](https://github.com/verdaccio/ui/issues/57)) ([01da082](https://github.com/verdaccio/ui/commit/01da082))
|
||||
* verify validation url and email ([#60](https://github.com/verdaccio/ui/issues/60)) ([980dac5](https://github.com/verdaccio/ui/commit/980dac5))
|
||||
|
||||
|
||||
|
||||
<a name="0.1.7"></a>
|
||||
## [0.1.7](https://github.com/verdaccio/ui/compare/v0.1.6...v0.1.7) (2019-05-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* search suggestion container height ([#54](https://github.com/verdaccio/ui/issues/54)) ([c9fb3c4](https://github.com/verdaccio/ui/commit/c9fb3c4))
|
||||
|
||||
|
||||
|
||||
<a name="0.1.6"></a>
|
||||
## [0.1.6](https://github.com/verdaccio/ui/compare/v0.1.5...v0.1.6) (2019-05-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* pattern allow yarn to add all files on pack ([#50](https://github.com/verdaccio/ui/issues/50)) ([9ffa629](https://github.com/verdaccio/ui/commit/9ffa629))
|
||||
|
||||
|
||||
|
||||
<a name="0.1.5"></a>
|
||||
## [0.1.5](https://github.com/verdaccio/ui/compare/v0.1.4...v0.1.5) (2019-05-04)
|
||||
|
||||
|
||||
|
||||
<a name="0.1.4"></a>
|
||||
## [0.1.4](https://github.com/verdaccio/ui/compare/v0.1.3...v0.1.4) (2019-05-04)
|
||||
|
||||
|
||||
|
||||
<a name="0.1.3"></a>
|
||||
## [0.1.3](https://github.com/verdaccio/ui/compare/v0.1.2...v0.1.3) (2019-05-04)
|
||||
|
||||
|
||||
|
||||
<a name="0.1.2"></a>
|
||||
## [0.1.2](https://github.com/verdaccio/ui/compare/v0.1.1...v0.1.2) (2019-04-28)
|
||||
|
||||
|
||||
|
||||
<a name="0.1.1"></a>
|
||||
## [0.1.1](https://github.com/verdaccio/ui/compare/v0.1.0...v0.1.1) (2019-04-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* version rendering issue. ([#38](https://github.com/verdaccio/ui/issues/38)) ([e8fd596](https://github.com/verdaccio/ui/commit/e8fd596))
|
||||
|
||||
|
||||
|
||||
<a name="0.1.0"></a>
|
||||
# [0.1.0](https://github.com/verdaccio/ui/compare/v0.0.13...v0.1.0) (2019-04-26)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* accept primary color to be configured ([#36](https://github.com/verdaccio/ui/issues/36)) ([d6a8f55](https://github.com/verdaccio/ui/commit/d6a8f55))
|
||||
|
||||
|
||||
|
||||
<a name="0.0.13"></a>
|
||||
## [0.0.13](https://github.com/verdaccio/ui/compare/v0.0.4...v0.0.13) (2019-04-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* takes the app version from verdaccio ([6f10837](https://github.com/verdaccio/ui/commit/6f10837))
|
||||
* there can be no spaces between scope and registry ([#34](https://github.com/verdaccio/ui/issues/34)) ([cc30d0b](https://github.com/verdaccio/ui/commit/cc30d0b))
|
||||
|
||||
|
||||
|
||||
<a name="0.0.4"></a>
|
||||
## [0.0.4](https://github.com/verdaccio/ui/compare/v0.0.3...v0.0.4) (2019-04-04)
|
||||
|
||||
|
||||
|
||||
<a name="0.0.3"></a>
|
||||
## 0.0.3 (2019-04-04)
|
||||
|
||||
43
README.md
43
README.md
@@ -3,26 +3,15 @@
|
||||
|
||||
# Version 4 UI Theme
|
||||
|
||||
[Verdaccio](https://verdaccio.org/) is a simple, **zero-config-required local private npm registry**.
|
||||
No need for an entire database just to get started! Verdaccio comes out of the box with
|
||||
**its own tiny database**, and the ability to proxy other registries (eg. npmjs.org),
|
||||
caching the downloaded modules along the way.
|
||||
For those looking to extend their storage capabilities, Verdaccio
|
||||
**supports various community-made plugins to hook into services such as Amazon's s3,
|
||||
Google Cloud Storage** or create your own plugin.
|
||||
[Verdaccio](https://verdaccio.org/) UI is a [theme plugin](https://verdaccio.org/docs/en/dev-plugins#theme-plugin) build in React, Flow and Emotion. It uses Jest and Enzyme for Unit testing.
|
||||
|
||||
|
||||
[](https://www.npmjs.com/package/verdaccio)
|
||||
[](https://www.npmjs.com/package/verdaccio)
|
||||
[](https://www.npmjs.com/package/verdaccio)
|
||||
[](https://www.npmjs.com/package/verdaccio)
|
||||
[](https://verdaccio.org/docs/en/docker.html)
|
||||
[](https://opencollective.com/verdaccio)
|
||||
[](https://stackshare.io/verdaccio)
|
||||
|
||||

|
||||
[](https://codecov.io/gh/verdaccio/verdaccio)
|
||||
[](http://chat.verdaccio.org/)
|
||||
[](https://www.npmjs.com/package/verdaccio)
|
||||
[](https://www.npmjs.com/package/verdaccio)
|
||||

|
||||
[](https://crowdin.com/project/verdaccio)
|
||||
|
||||
@@ -30,11 +19,27 @@ Google Cloud Storage** or create your own plugin.
|
||||
[](https://twitter.com/verdaccio_npm)
|
||||
[](https://github.com/verdaccio/verdaccio/stargazers)
|
||||
|
||||
đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§
|
||||
## Contributing
|
||||
|
||||
**This is a maintenance branch, only bug fixing, minor changes or security updates**.
|
||||
We use `>=yarn@1.13.0`, keep on mind we use lock file.
|
||||
|
||||
For development run the following command, it will execute `webpack` and `verdaccio` to
|
||||
|
||||
```
|
||||
yarn dev
|
||||
```
|
||||
The configuration file is located on `tools/_config.yaml`.
|
||||
|
||||
Run linting tooling and test to check your code is clean before commit.
|
||||
|
||||
```
|
||||
yarn lint && yarn test
|
||||
```
|
||||
|
||||
Remember we follow the [the Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0-beta.4/).
|
||||
|
||||
🤓 Feel free to participate in code reviews, let us know if you want to participate in this plugin.
|
||||
|
||||
đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§đźš§
|
||||
|
||||
## Open Collective Sponsors
|
||||
|
||||
@@ -63,7 +68,7 @@ This project exists thanks to all the people who contribute. [[Contribute](CONTR
|
||||
|
||||
[](../../graphs/contributors)
|
||||
|
||||
### FAQ / Contact / Troubleshoot
|
||||
### FAQ / Contact / Troubleshoot
|
||||
|
||||
If you have any issue you can try the following options, do no desist to ask or check our issues database, perhaps someone has asked already what you are looking for.
|
||||
|
||||
@@ -79,4 +84,4 @@ If you have any issue you can try the following options, do no desist to ask or
|
||||
|
||||
### License
|
||||
|
||||
Verdaccio is [MIT licensed](https://github.com/verdaccio/verdaccio/blob/master/LICENSE)
|
||||
Verdaccio is [MIT licensed](https://github.com/verdaccio/verdaccio/blob/master/LICENSE)
|
||||
|
||||
@@ -6,7 +6,7 @@ module.exports = {
|
||||
collectCoverage: true,
|
||||
testEnvironment: 'jest-environment-jsdom-global',
|
||||
testURL: 'http://localhost',
|
||||
testRegex: '(test/unit/webui/.*\\.spec)\\.js',
|
||||
testRegex: '(test/unit/.*\\.spec)\\.js',
|
||||
setupFiles: [
|
||||
'./test/unit/setup.js'
|
||||
],
|
||||
@@ -35,6 +35,7 @@ module.exports = {
|
||||
'<rootDir>/build',
|
||||
],
|
||||
snapshotSerializers: [
|
||||
'enzyme-to-json/serializer',
|
||||
"jest-emotion"
|
||||
],
|
||||
coveragePathIgnorePatterns: [
|
||||
|
||||
24
package.json
24
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@verdaccio/ui-theme",
|
||||
"version": "0.0.3",
|
||||
"version": "0.1.10",
|
||||
"description": "Verdaccio User Interface",
|
||||
"author": {
|
||||
"name": "Verdaccio Core Team"
|
||||
@@ -15,17 +15,20 @@
|
||||
"@commitlint/config-conventional": "7.5.0",
|
||||
"@material-ui/core": "3.9.0",
|
||||
"@material-ui/icons": "3.0.2",
|
||||
"@octokit/rest": "16.23.2",
|
||||
"@verdaccio/babel-preset": "0.1.0",
|
||||
"@verdaccio/types": "5.0.0-beta.4",
|
||||
"autosuggest-highlight": "3.1.1",
|
||||
"bundlesize": "0.17.1",
|
||||
"codecov": "3.2.0",
|
||||
"concurrently": "4.1.0",
|
||||
"cross-env": "5.2.0",
|
||||
"css-loader": "0.28.10",
|
||||
"date-fns": "1.30.1",
|
||||
"emotion": "9.2.12",
|
||||
"enzyme": "3.9.0",
|
||||
"enzyme-adapter-react-16": "1.10.0",
|
||||
"enzyme-to-json": "3.3.5",
|
||||
"eslint": "5.14.1",
|
||||
"eslint-config-google": "0.12.0",
|
||||
"eslint-config-prettier": "4.1.0",
|
||||
@@ -42,6 +45,7 @@
|
||||
"flow-bin": "0.81.0",
|
||||
"flow-runtime": "0.17.0",
|
||||
"friendly-errors-webpack-plugin": "1.7.0",
|
||||
"get-stdin": "6.0.0",
|
||||
"github-markdown-css": "2.10.0",
|
||||
"html-webpack-plugin": "3.2.0",
|
||||
"husky": "0.15.0-rc.8",
|
||||
@@ -52,6 +56,7 @@
|
||||
"jest-environment-jsdom": "24.0.0",
|
||||
"jest-environment-jsdom-global": "1.1.1",
|
||||
"jest-environment-node": "24.0.0",
|
||||
"js-yaml": "3.13.1",
|
||||
"localstorage-memory": "1.0.3",
|
||||
"mini-css-extract-plugin": "0.5.0",
|
||||
"node-mocks-http": "1.7.3",
|
||||
@@ -85,10 +90,13 @@
|
||||
"supertest": "3.4.2",
|
||||
"typeface-roboto": "0.0.54",
|
||||
"url-loader": "1.1.2",
|
||||
"validator": "10.11.0",
|
||||
"verdaccio": "next",
|
||||
"verdaccio-auth-memory": "0.0.4",
|
||||
"verdaccio-memory": "2.0.0",
|
||||
"webpack": "4.20.2",
|
||||
"webpack-bundle-analyzer": "3.0.4",
|
||||
"webpack-bundle-size-analyzer": "3.0.0",
|
||||
"webpack-cli": "3.2.3",
|
||||
"webpack-dev-server": "3.2.1",
|
||||
"webpack-merge": "4.2.1",
|
||||
@@ -104,19 +112,23 @@
|
||||
"flow": "flow check",
|
||||
"release": "standard-version -a -s",
|
||||
"test:clean": "npx jest --clearCache",
|
||||
"test": "cross-env NODE_ENV=test BABEL_ENV=test TZ=UTC FORCE_COLOR=1 jest --config ./jest.config.js --maxWorkers 2 --passWithNoTests",
|
||||
"test": "cross-env NODE_ENV=test BABEL_ENV=test TZ=UTC jest --config ./jest.config.js --maxWorkers 2 --passWithNoTests",
|
||||
"test:size": "bundlesize",
|
||||
"lint": "npm run flow && npm run lint:js && npm run lint:css",
|
||||
"lint:js": "eslint .",
|
||||
"coverage:publish": "codecov",
|
||||
"lint:css": "stylelint 'src/webui/**/styles.js'",
|
||||
"pre:webpack": "rimraf static/*",
|
||||
"dev": "cross-env BABEL_ENV=ui babel-node tools/dev.server.js",
|
||||
"build": "npm run pre:webpack && cross-env BABEL_ENV=ui webpack --config tools/webpack.prod.config.babel.js"
|
||||
"dev:web": "cross-env BABEL_ENV=ui babel-node tools/dev.server.js",
|
||||
"verdaccio:server": "node tools/verdaccio.js",
|
||||
"build": "npm run pre:webpack && cross-env BABEL_ENV=ui webpack --config tools/webpack.prod.config.babel.js",
|
||||
"build:stats": "cross-env BABEL_ENV=ui webpack --config tools/webpack.prod.config.babel.js --json > stats.json",
|
||||
"build:size": "cross-env BABEL_ENV=ui webpack --config tools/webpack.prod.config.babel.js --json | webpack-bundle-size-analyzer",
|
||||
"dev": "concurrently --kill-others \"npm run dev:web\" \"npm run verdaccio:server\""
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.12.0",
|
||||
"npm": ">=3"
|
||||
"node": ">=8",
|
||||
"npm": ">=5"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
|
||||
13
scripts/gh_publish.sh
Executable file
13
scripts/gh_publish.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Get the last tag from GitHub
|
||||
lastTag=$(git describe --tags $(git rev-list --tags --max-count=1))
|
||||
|
||||
# Print it to the console for verification
|
||||
echo "Bumping version to new tag: ${lastTag}"
|
||||
|
||||
# creating .npmrc
|
||||
echo "//$REGISTRY_URL/:_authToken=$REGISTRY_AUTH_TOKEN" > .npmrc
|
||||
|
||||
# Publish to NPM
|
||||
npm publish --registry https://$REGISTRY_URL/
|
||||
8
scripts/github-release.sh
Normal file
8
scripts/github-release.sh
Normal file
@@ -0,0 +1,8 @@
|
||||
# Get the last tag from GitHub
|
||||
lastTag=$(git describe --tags $(git rev-list --tags --max-count=1))
|
||||
|
||||
changelog=$(git show $GITHUB_SHA --unified=0 CHANGELOG.md | tail +12 | sed -e 's/^\+//')
|
||||
|
||||
echo "$changelog"
|
||||
|
||||
echo "$changelog" | node scripts/trigger-release.js $lastTag
|
||||
@@ -7,4 +7,4 @@ lastTag=$(git describe --tags $(git rev-list --tags --max-count=1))
|
||||
echo "Bumping version to new tag: ${lastTag}"
|
||||
|
||||
# Publish to NPM
|
||||
npm publish --registry https://registry.npmjs.org/
|
||||
npm publish
|
||||
|
||||
26
scripts/trigger-release.js
Normal file
26
scripts/trigger-release.js
Normal file
@@ -0,0 +1,26 @@
|
||||
"use strict";
|
||||
|
||||
const [ /* node */, /* file */, tag] = process.argv;
|
||||
|
||||
const getStdin = require("get-stdin");
|
||||
const Octokit = require('@octokit/rest');
|
||||
const octokit = new Octokit({
|
||||
auth: `token ${process.env.GITHUB_TOKEN}`,
|
||||
});
|
||||
|
||||
|
||||
const [repoOwner, repoName] = process.env.GITHUB_REPOSITORY.split("/");
|
||||
|
||||
getStdin()
|
||||
.then(changelog => octokit.repos.createRelease({
|
||||
owner: repoOwner,
|
||||
repo: repoName,
|
||||
tag_name: tag,
|
||||
body: changelog,
|
||||
draft: true,
|
||||
}))
|
||||
.catch(err => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -4,155 +4,12 @@
|
||||
|
||||
// @flow
|
||||
|
||||
export const DEFAULT_PORT: string = '4873';
|
||||
export const DEFAULT_PROTOCOL: string = 'http';
|
||||
export const DEFAULT_DOMAIN: string = 'localhost';
|
||||
export const TIME_EXPIRATION_24H: string = '24h';
|
||||
export const TIME_EXPIRATION_7D: string = '7d';
|
||||
export const DIST_TAGS = 'dist-tags';
|
||||
export const USERS = 'users';
|
||||
export const DEFAULT_MIN_LIMIT_PASSWORD: number = 3;
|
||||
export const DEFAULT_USER = 'Anonymous';
|
||||
|
||||
export const keyPem = 'verdaccio-key.pem';
|
||||
export const certPem = 'verdaccio-cert.pem';
|
||||
export const csrPem = 'verdaccio-csr.pem';
|
||||
|
||||
export const HEADERS = {
|
||||
JSON: 'application/json',
|
||||
CONTENT_TYPE: 'Content-type',
|
||||
TEXT_PLAIN: 'text/plain',
|
||||
FORWARDED_PROTO: 'X-Forwarded-Proto',
|
||||
ETAG: 'ETag',
|
||||
JSON_CHARSET: 'application/json; charset=utf-8',
|
||||
OCTET_STREAM: 'application/octet-stream; charset=utf-8',
|
||||
TEXT_CHARSET: 'text/plain; charset=utf-8',
|
||||
WWW_AUTH: 'WWW-Authenticate',
|
||||
GZIP: 'gzip',
|
||||
};
|
||||
|
||||
export const CHARACTER_ENCODING = {
|
||||
UTF8: 'utf8',
|
||||
};
|
||||
|
||||
export const HEADER_TYPE = {
|
||||
CONTENT_ENCODING: 'content-encoding',
|
||||
CONTENT_TYPE: 'content-type',
|
||||
CONTENT_LENGTH: 'content-length',
|
||||
ACCEPT_ENCODING: 'accept-encoding',
|
||||
};
|
||||
|
||||
export const ERROR_CODE = {
|
||||
token_required: 'token is required',
|
||||
};
|
||||
|
||||
export const TOKEN_BASIC = 'Basic';
|
||||
export const TOKEN_BEARER = 'Bearer';
|
||||
export const DEFAULT_REGISTRY = 'https://registry.npmjs.org';
|
||||
export const DEFAULT_UPLINK = 'npmjs';
|
||||
|
||||
export const ROLES = {
|
||||
$ALL: '$all',
|
||||
ALL: 'all',
|
||||
$AUTH: '$authenticated',
|
||||
$ANONYMOUS: '$anonymous',
|
||||
DEPRECATED_ALL: '@all',
|
||||
DEPRECATED_AUTH: '@authenticated',
|
||||
DEPRECATED_ANONYMOUS: '@anonymous',
|
||||
};
|
||||
|
||||
export const HTTP_STATUS = {
|
||||
OK: 200,
|
||||
CREATED: 201,
|
||||
MULTIPLE_CHOICES: 300,
|
||||
NOT_MODIFIED: 304,
|
||||
BAD_REQUEST: 400,
|
||||
UNAUTHORIZED: 401,
|
||||
FORBIDDEN: 403,
|
||||
NOT_FOUND: 404,
|
||||
CONFLICT: 409,
|
||||
UNSUPPORTED_MEDIA: 415,
|
||||
BAD_DATA: 422,
|
||||
INTERNAL_ERROR: 500,
|
||||
SERVICE_UNAVAILABLE: 503,
|
||||
LOOP_DETECTED: 508,
|
||||
};
|
||||
|
||||
export const API_MESSAGE = {
|
||||
PKG_CREATED: 'created new package',
|
||||
PKG_CHANGED: 'package changed',
|
||||
PKG_REMOVED: 'package removed',
|
||||
PKG_PUBLISHED: 'package published',
|
||||
TARBALL_UPLOADED: 'tarball uploaded successfully',
|
||||
TARBALL_REMOVED: 'tarball removed',
|
||||
TAG_UPDATED: 'tags updated',
|
||||
TAG_REMOVED: 'tag removed',
|
||||
TAG_ADDED: 'package tagged',
|
||||
LOGGED_OUT: 'Logged out',
|
||||
};
|
||||
|
||||
export const SUPPORT_ERRORS = {
|
||||
PLUGIN_MISSING_INTERFACE: 'the plugin does not provide implementation of the requested feature',
|
||||
TFA_DISABLED: 'the two-factor authentication is not yet supported',
|
||||
};
|
||||
|
||||
export const API_ERROR = {
|
||||
PASSWORD_SHORT: (passLength: number = DEFAULT_MIN_LIMIT_PASSWORD) =>
|
||||
`The provided password is too short. Please pick a password longer than ${passLength} characters.`,
|
||||
MUST_BE_LOGGED: 'You must be logged in to publish packages.',
|
||||
PLUGIN_ERROR: 'bug in the auth plugin system',
|
||||
CONFIG_BAD_FORMAT: 'config file must be an object',
|
||||
BAD_USERNAME_PASSWORD: 'bad username/password, access denied',
|
||||
NO_PACKAGE: 'no such package available',
|
||||
PACKAGE_CANNOT_BE_ADDED: 'this package cannot be added',
|
||||
BAD_DATA: 'bad data',
|
||||
NOT_ALLOWED: 'not allowed to access package',
|
||||
NOT_ALLOWED_PUBLISH: 'not allowed to publish package',
|
||||
INTERNAL_SERVER_ERROR: 'internal server error',
|
||||
UNKNOWN_ERROR: 'unknown error',
|
||||
NOT_PACKAGE_UPLINK: 'package does not exist on uplink',
|
||||
UPLINK_OFFLINE_PUBLISH: 'one of the uplinks is down, refuse to publish',
|
||||
UPLINK_OFFLINE: 'uplink is offline',
|
||||
CONTENT_MISMATCH: 'content length mismatch',
|
||||
NOT_FILE_UPLINK: "file doesn't exist on uplink",
|
||||
MAX_USERS_REACHED: 'maximum amount of users reached',
|
||||
VERSION_NOT_EXIST: "this version doesn't exist",
|
||||
FILE_NOT_FOUND: 'File not found',
|
||||
BAD_STATUS_CODE: 'bad status code',
|
||||
PACKAGE_EXIST: 'this package is already present',
|
||||
BAD_AUTH_HEADER: 'bad authorization header',
|
||||
WEB_DISABLED: 'Web interface is disabled in the config file',
|
||||
DEPRECATED_BASIC_HEADER: 'basic authentication is deprecated, please use JWT instead',
|
||||
BAD_FORMAT_USER_GROUP: 'user groups is different than an array',
|
||||
RESOURCE_UNAVAILABLE: 'resource unavailable',
|
||||
BAD_PACKAGE_DATA: 'bad incoming package data',
|
||||
USERNAME_PASSWORD_REQUIRED: 'username and password is required',
|
||||
USERNAME_ALREADY_REGISTERED: 'username is already registered',
|
||||
};
|
||||
|
||||
export const APP_ERROR = {
|
||||
CONFIG_NOT_VALID: 'CONFIG: it does not look like a valid config file',
|
||||
PROFILE_ERROR: 'profile unexpected error',
|
||||
PASSWORD_VALIDATION: 'not valid password',
|
||||
};
|
||||
|
||||
export const DEFAULT_NO_README = 'ERROR: No README data found!';
|
||||
export const MODULE_NOT_FOUND = 'MODULE_NOT_FOUND';
|
||||
|
||||
export const WEB_TITLE = 'Verdaccio';
|
||||
|
||||
export const PACKAGE_ACCESS = {
|
||||
SCOPE: '@*/*',
|
||||
ALL: '**',
|
||||
};
|
||||
|
||||
export const UPDATE_BANNER = {
|
||||
CHANGELOG_URL: 'https://github.com/verdaccio/verdaccio/releases/tag/',
|
||||
};
|
||||
|
||||
export const STORAGE = {
|
||||
PACKAGE_FILE_NAME: 'package.json',
|
||||
FILE_EXIST_ERROR: 'EEXISTS',
|
||||
NO_SUCH_FILE_ERROR: 'ENOENT',
|
||||
DEFAULT_REVISION: '0-0000000000000000',
|
||||
};
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
/**
|
||||
* @prettier
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import { createDecipher, createCipher, createHash, pseudoRandomBytes } from 'crypto';
|
||||
import jwt from 'jsonwebtoken';
|
||||
|
||||
import type { JWTSignOptions, RemoteUser } from '@verdaccio/types';
|
||||
|
||||
export const defaultAlgorithm = 'aes192';
|
||||
export const defaultTarballHashAlgorithm = 'sha1';
|
||||
|
||||
export function aesEncrypt(buf: Buffer, secret: string): Buffer {
|
||||
// deprecated
|
||||
// https://nodejs.org/api/crypto.html#crypto_crypto_createcipher_algorithm_password_options
|
||||
const c = createCipher(defaultAlgorithm, secret);
|
||||
const b1 = c.update(buf);
|
||||
const b2 = c.final();
|
||||
return Buffer.concat([b1, b2]);
|
||||
}
|
||||
|
||||
export function aesDecrypt(buf: Buffer, secret: string) {
|
||||
try {
|
||||
// deprecated
|
||||
// https://nodejs.org/api/crypto.html#crypto_crypto_createdecipher_algorithm_password_options
|
||||
const c = createDecipher(defaultAlgorithm, secret);
|
||||
const b1 = c.update(buf);
|
||||
const b2 = c.final();
|
||||
return Buffer.concat([b1, b2]);
|
||||
} catch (_) {
|
||||
return new Buffer(0);
|
||||
}
|
||||
}
|
||||
|
||||
export function createTarballHash() {
|
||||
return createHash(defaultTarballHashAlgorithm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Express doesn't do ETAGS with requests <= 1024b
|
||||
* we use md5 here, it works well on 1k+ bytes, but sucks with fewer data
|
||||
* could improve performance using crc32 after benchmarks.
|
||||
* @param {Object} data
|
||||
* @return {String}
|
||||
*/
|
||||
export function stringToMD5(data: Buffer | string) {
|
||||
return createHash('md5')
|
||||
.update(data)
|
||||
.digest('hex');
|
||||
}
|
||||
|
||||
export function generateRandomHexString(length: number = 8) {
|
||||
return pseudoRandomBytes(length).toString('hex');
|
||||
}
|
||||
|
||||
export async function signPayload(payload: RemoteUser, secretOrPrivateKey: string, options: JWTSignOptions): Promise<string> {
|
||||
return new Promise(function(resolve, reject) {
|
||||
return jwt.sign(
|
||||
payload,
|
||||
secretOrPrivateKey,
|
||||
{
|
||||
notBefore: '1', // Make sure the time will not rollback :)
|
||||
...options,
|
||||
},
|
||||
(error, token) => (error ? reject(error) : resolve(token))
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function verifyPayload(token: string, secretOrPrivateKey: string) {
|
||||
return jwt.verify(token, secretOrPrivateKey);
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
// @flow
|
||||
|
||||
export function spliceURL(...args: Array<string>): string {
|
||||
return Array.from(args).reduce((lastResult, current) => lastResult + current).replace(/([^:])(\/)+(.)/g, `$1/$3`);
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
// @flow
|
||||
import {stringToMD5} from '../lib/crypto-utils';
|
||||
import _ from 'lodash';
|
||||
|
||||
// this is a generic avatar
|
||||
// https://www.iconfinder.com/icons/403017/anonym_avatar_default_head_person_unknown_user_icon
|
||||
// license: free commercial usage
|
||||
export const GENERIC_AVATAR: string = `
|
||||
data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjwhRE9DVFlQRSBzdmcgIFBVQkxJQyAnLS8vVzNDLy9EVEQgU1
|
||||
ZHIDEuMS8vRU4nICAnaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkJz48c3ZnIGVuYWJsZS1iYW
|
||||
NrZ3JvdW5kPSJuZXcgLTI3IDI0IDEwMCAxMDAiIGhlaWdodD0iMTAwcHgiIGlkPSJ1bmtub3duIiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3
|
||||
g9Ii0yNyAyNCAxMDAgMTAwIiB3aWR0aD0iMTAwcHgiIHhtbDpzcGFjZT0icHJlc2VydmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy
|
||||
8yMDAwL3N2ZyIgeG1sbnM6c2tldGNoPSJodHRwOi8vd3d3LmJvaGVtaWFuY29kaW5nLmNvbS9za2V0Y2gvbnMiIHhtbG5zOnhsaW5rPS
|
||||
JodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48Zz48Zz48ZGVmcz48Y2lyY2xlIGN4PSIyMyIgY3k9Ijc0IiBpZD0iY2lyY2xlIi
|
||||
ByPSI1MCIvPjwvZGVmcz48dXNlIGZpbGw9IiNGNUVFRTUiIG92ZXJmbG93PSJ2aXNpYmxlIiB4bGluazpocmVmPSIjY2lyY2xlIi8+PGN
|
||||
saXBQYXRoIGlkPSJjaXJjbGVfMV8iPjx1c2Ugb3ZlcmZsb3c9InZpc2libGUiIHhsaW5rOmhyZWY9IiNjaXJjbGUiLz48L2NsaXBQYXR
|
||||
oPjxnIGNsaXAtcGF0aD0idXJsKCNjaXJjbGVfMV8pIj48ZGVmcz48cGF0aCBkPSJNMzYsOTUuOWMwLDQsNC43LDUuMiw3LjEsNS44Yzc
|
||||
uNiwyLDIyLjgsNS45LDIyLjgsNS45YzMuMiwxLjEsNS43LDMuNSw3LjEsNi42djkuOEgtMjd2LTkuOCAgICAgICBjMS4zLTMuMSwzLjk
|
||||
tNS41LDcuMS02LjZjMCwwLDE1LjItMy45LDIyLjgtNS45YzIuNC0wLjYsNy4xLTEuOCw3LjEtNS44YzAtNCwwLTEwLjksMC0xMC45aDI
|
||||
2QzM2LDg1LDM2LDkxLjksMzYsOTUuOXoiIGlkPSJzaG91bGRlcnMiLz48L2RlZnM+PHVzZSBmaWxsPSIjRTZDMTlDIiBvdmVyZmxvdz0
|
||||
idmlzaWJsZSIgeGxpbms6aHJlZj0iI3Nob3VsZGVycyIvPjxjbGlwUGF0aCBpZD0ic2hvdWxkZXJzXzFfIj48dXNlIG92ZXJmbG93PSJ
|
||||
2aXNpYmxlIiB4bGluazpocmVmPSIjc2hvdWxkZXJzIi8+PC9jbGlwUGF0aD48cGF0aCBjbGlwLXBhdGg9InVybCgjc2hvdWxkZXJzXzF
|
||||
fKSIgZD0iTTIzLjIsMzVjMC4xLDAsMC4xLDAsMC4yLDBjMCwwLDAsMCwwLDAgICAgICBjMy4zLDAsOC4yLDAuMiwxMS40LDJjMy4zLD
|
||||
EuOSw3LjMsNS42LDguNSwxMi4xYzIuNCwxMy43LTIuMSwzNS40LTYuMyw0Mi40Yy00LDYuNy05LjgsOS4yLTEzLjUsOS40YzAsMC0wL
|
||||
jEsMC0wLjEsMCAgICAgIGMtMC4xLDAtMC4xLDAtMC4yLDBjLTAuMSwwLTAuMSwwLTAuMiwwYzAsMC0wLjEsMC0wLjEsMGMtMy43LTAuM
|
||||
i05LjUtMi43LTEzLjUtOS40Yy00LjItNy04LjctMjguNy02LjMtNDIuNCAgICAgIGMxLjItNi41LDUuMi0xMC4yLDguNS0xMi4xYzMuM
|
||||
i0xLjgsOC4xLTIsMTEuNC0yYzAsMCwwLDAsMCwwQzIzLjEsMzUsMjMuMSwzNSwyMy4yLDM1TDIzLjIsMzV6IiBmaWxsPSIjRDRCMDhDI
|
||||
iBpZD0iaGVhZC1zaGFkb3ciLz48L2c+PC9nPjxwYXRoIGQ9Ik0yMi42LDQwYzE5LjEsMCwyMC43LDEzLjgsMjAuOCwxNS4xYzEuMSwxM
|
||||
S45LTMsMjguMS02LjgsMzMuN2MtNCw1LjktOS44LDguMS0xMy41LDguMyAgICBjLTAuMiwwLTAuMiwwLTAuMywwYy0wLjEsMC0wLjEs
|
||||
MC0wLjIsMEMxOC44LDk2LjgsMTMsOTQuNiw5LDg4LjdjLTMuOC01LjYtNy45LTIxLjgtNi44LTMzLjhDMi4zLDUzLjcsMy41LDQwLDIyL
|
||||
jYsNDB6IiBmaWxsPSIjRjJDRUE1IiBpZD0iaGVhZCIvPjwvZz48L3N2Zz4=`;
|
||||
|
||||
/**
|
||||
* Generate gravatar url from email address
|
||||
*/
|
||||
export function generateGravatarUrl(email: string = '', online: boolean = true): string {
|
||||
if (online) {
|
||||
if (_.isString(email) && _.size(email) > 0) {
|
||||
email = email.trim().toLocaleLowerCase();
|
||||
const emailMD5 = stringToMD5(email);
|
||||
return `https://www.gravatar.com/avatar/${emailMD5}`;
|
||||
}
|
||||
return GENERIC_AVATAR;
|
||||
} else {
|
||||
return GENERIC_AVATAR;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,18 @@
|
||||
/* eslint-disable react/jsx-max-depth */
|
||||
/**
|
||||
* @prettier
|
||||
*/
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { DetailContextConsumer } from '../../pages/version/index';
|
||||
import List from '@material-ui/core/List/index';
|
||||
|
||||
import DownloadIcon from '@material-ui/icons/CloudDownload';
|
||||
import BugReportIcon from '@material-ui/icons/BugReport';
|
||||
import DownloadIcon from '@material-ui/icons/CloudDownload';
|
||||
import HomeIcon from '@material-ui/icons/Home';
|
||||
import List from '@material-ui/core/List/index';
|
||||
import Tooltip from '@material-ui/core/Tooltip/index';
|
||||
|
||||
import { DetailContextConsumer } from '../../pages/version/index';
|
||||
import { Fab, ActionListItem } from './styles';
|
||||
import { isURL } from '../../utils/url';
|
||||
|
||||
const ACTIONS = {
|
||||
homepage: {
|
||||
@@ -42,28 +41,15 @@ class ActionBar extends Component<any, any> {
|
||||
}
|
||||
|
||||
renderIconsWithLink(link, component) {
|
||||
if (!link) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<a href={link} target={"_blank"}>
|
||||
<a href={link} target={'_blank'}>
|
||||
{component}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
renderActionBarListItems = (packageMeta) => {
|
||||
const {
|
||||
latest: {
|
||||
bugs: {
|
||||
url: issue,
|
||||
} = {},
|
||||
homepage,
|
||||
dist: {
|
||||
tarball,
|
||||
} = {},
|
||||
} = {},
|
||||
} = packageMeta;
|
||||
renderActionBarListItems = packageMeta => {
|
||||
const { latest: { bugs: { url: issue } = {}, homepage, dist: { tarball } = {} } = {} } = packageMeta;
|
||||
|
||||
const actionsMap = {
|
||||
homepage,
|
||||
@@ -73,12 +59,8 @@ class ActionBar extends Component<any, any> {
|
||||
|
||||
const renderList = Object.keys(actionsMap).reduce((component, value, key) => {
|
||||
const link = actionsMap[value];
|
||||
if (link) {
|
||||
const fab = (
|
||||
<Fab size={'small'}>
|
||||
{ACTIONS[value]['icon']}
|
||||
</Fab>
|
||||
);
|
||||
if (link && isURL(link)) {
|
||||
const fab = <Fab size={'small'}>{ACTIONS[value]['icon']}</Fab>;
|
||||
component.push(
|
||||
<Tooltip key={key} title={ACTIONS[value]['title']}>
|
||||
{this.renderIconsWithLink(link, fab)}
|
||||
@@ -90,19 +72,13 @@ class ActionBar extends Component<any, any> {
|
||||
|
||||
return (
|
||||
<>
|
||||
<ActionListItem alignItems={'flex-start'}>
|
||||
{renderList}
|
||||
</ActionListItem>
|
||||
<ActionListItem alignItems={'flex-start'}>{renderList}</ActionListItem>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
renderActionBar = ({ packageMeta = {} }) => {
|
||||
return (
|
||||
<List>
|
||||
{this.renderActionBarListItems(packageMeta)}
|
||||
</List>
|
||||
);
|
||||
return <List>{this.renderActionBarListItems(packageMeta)}</List>;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import ListItemText from '@material-ui/core/ListItemText/index';
|
||||
|
||||
import { DetailContextConsumer } from '../../pages/version/index';
|
||||
import { Heading, AuthorListItem } from './styles';
|
||||
import { isEmail } from '../../utils/url';
|
||||
|
||||
class Authors extends Component<any, any> {
|
||||
render() {
|
||||
@@ -23,9 +24,10 @@ class Authors extends Component<any, any> {
|
||||
}
|
||||
|
||||
renderLinkForMail(email, avatarComponent, packageName, version) {
|
||||
if (!email) {
|
||||
if (!email || isEmail(email) === false) {
|
||||
return avatarComponent;
|
||||
}
|
||||
|
||||
return (
|
||||
<a href={`mailto:${email}?subject=${packageName}@${version}`} target={'_top'}>
|
||||
{avatarComponent}
|
||||
|
||||
@@ -8,11 +8,10 @@ import type { Node } from 'react';
|
||||
import Autosuggest from 'react-autosuggest';
|
||||
import match from 'autosuggest-highlight/match';
|
||||
import parse from 'autosuggest-highlight/parse';
|
||||
import Paper from '@material-ui/core/Paper';
|
||||
import MenuItem from '@material-ui/core/MenuItem';
|
||||
|
||||
import { fontWeight } from '../../utils/styles/sizes';
|
||||
import { Wrapper, InputField } from './styles';
|
||||
import { Wrapper, InputField, SuggestionContainer } from './styles';
|
||||
import { IProps } from './types';
|
||||
|
||||
const renderInputComponent = (inputProps): Node => {
|
||||
@@ -110,12 +109,12 @@ const AutoComplete = ({
|
||||
// this format avoid arrow function eslint rule
|
||||
function renderSuggestionsContainer({ containerProps, children, query }) {
|
||||
return (
|
||||
<Paper {...containerProps} square={true}>
|
||||
<SuggestionContainer {...containerProps} square={true}>
|
||||
{suggestionsLoaded && children === null && query && renderMessage(SUGGESTIONS_RESPONSE.NO_RESULT)}
|
||||
{suggestionsLoading && query && renderMessage(SUGGESTIONS_RESPONSE.LOADING)}
|
||||
{suggestionsError && renderMessage(SUGGESTIONS_RESPONSE.FAILURE)}
|
||||
{children}
|
||||
</Paper>
|
||||
</SuggestionContainer>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
import React from 'react';
|
||||
import styled, { css } from 'react-emotion';
|
||||
import Paper from '@material-ui/core/Paper';
|
||||
|
||||
import TextField from '../TextField';
|
||||
import { IInputField } from './types';
|
||||
@@ -50,3 +51,10 @@ export const InputField = ({ color, ...others }: IInputField) => (
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
export const SuggestionContainer = styled(Paper)`
|
||||
&& {
|
||||
max-height: 500px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -4,15 +4,15 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import type { Node } from 'react';
|
||||
|
||||
import FileCopy from '@material-ui/icons/FileCopy';
|
||||
import Tooltip from '@material-ui/core/Tooltip/index';
|
||||
|
||||
import type { Node } from 'react';
|
||||
import { IProps } from './types';
|
||||
|
||||
import { ClipBoardCopy, ClipBoardCopyText, CopyIcon } from './styles';
|
||||
import { copyToClipBoardUtility } from '../../utils/cli-utils';
|
||||
import { TEXT } from '../../utils/constants';
|
||||
import { IProps } from './types';
|
||||
|
||||
const CopyToClipBoard = ({ text, children }: IProps): Node => {
|
||||
const renderToolTipFileCopy = () => (
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
* @flow
|
||||
*/
|
||||
|
||||
/* eslint react/jsx-max-depth: 0 */
|
||||
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import CardContent from '@material-ui/core/CardContent/index';
|
||||
@@ -40,7 +38,7 @@ class DepDetail extends Component<any, any> {
|
||||
};
|
||||
}
|
||||
|
||||
const WrappDepDetail = withRouter(DepDetail);
|
||||
const WrapperDependencyDetail = withRouter(DepDetail);
|
||||
|
||||
class DependencyBlock extends Component<any, any> {
|
||||
render() {
|
||||
@@ -68,7 +66,7 @@ class DependencyBlock extends Component<any, any> {
|
||||
deps.map(dep => {
|
||||
const [name, version] = dep;
|
||||
|
||||
return <WrappDepDetail key={name} name={name} onLoading={enableLoading} version={version} />;
|
||||
return <WrapperDependencyDetail key={name} name={name} onLoading={enableLoading} version={version} />;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import Card from '@material-ui/core/Card/index';
|
||||
import CardContent from '@material-ui/core/CardContent/index';
|
||||
import List from '@material-ui/core/List/index';
|
||||
|
||||
import ActtionBar from '../ActionBar';
|
||||
import ActionBar from '../ActionBar';
|
||||
import Author from '../Author';
|
||||
import Developers from '../Developers';
|
||||
import Dist from '../Dist';
|
||||
@@ -88,7 +88,7 @@ class DetailSidebar extends Component {
|
||||
}
|
||||
|
||||
renderActionBar = () => {
|
||||
return <ActtionBar />;
|
||||
return <ActionBar />;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
import React, {Component} from 'react';
|
||||
/**
|
||||
* @prettier
|
||||
*/
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import Avatar from '@material-ui/core/Avatar';
|
||||
import Tooltip from '@material-ui/core/Tooltip';
|
||||
import Add from '@material-ui/icons/Add';
|
||||
import Tooltip from '@material-ui/core/Tooltip';
|
||||
|
||||
import { DetailContextConsumer } from '../../pages/version';
|
||||
|
||||
import { Details, Heading, Content, Fab } from './styles';
|
||||
import { isEmail } from '../../utils/url';
|
||||
|
||||
interface Props {
|
||||
type: 'contributors' | 'maintainers'
|
||||
type: 'contributors' | 'maintainers';
|
||||
}
|
||||
|
||||
class Developers extends Component<Props, any> {
|
||||
@@ -28,11 +32,11 @@ class Developers extends Component<Props, any> {
|
||||
}}
|
||||
</DetailContextConsumer>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
handleLoadMore = () => {
|
||||
this.setState((prev) => ({ visibleDevs: prev.visibleDevs + 6 }));
|
||||
}
|
||||
this.setState(prev => ({ visibleDevs: prev.visibleDevs + 6 }));
|
||||
};
|
||||
|
||||
renderDevelopers = (developers, packageMeta) => {
|
||||
const { type } = this.props;
|
||||
@@ -44,40 +48,33 @@ class Developers extends Component<Props, any> {
|
||||
{developers.slice(0, visibleDevs).map(developer => (
|
||||
<Details key={developer.email}>{this.renderDeveloperDetails(developer, packageMeta)}</Details>
|
||||
))}
|
||||
{visibleDevs < developers.length &&
|
||||
<Fab onClick={this.handleLoadMore} size={'small'}><Add /></Fab>
|
||||
}
|
||||
{visibleDevs < developers.length && (
|
||||
<Fab onClick={this.handleLoadMore} size={'small'}>
|
||||
<Add />
|
||||
</Fab>
|
||||
)}
|
||||
</Content>
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
renderLinkForMail(email, avatarComponent, packageName, version) {
|
||||
if(!email) {
|
||||
if (!email || isEmail(email) === false) {
|
||||
return avatarComponent;
|
||||
}
|
||||
return (
|
||||
<a href={`mailto:${email}?subject=${packageName}@${version}`} target={"_top"}>
|
||||
<a href={`mailto:${email}?subject=${packageName}@${version}`} target={'_top'}>
|
||||
{avatarComponent}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
renderDeveloperDetails = ({ name, avatar, email }, packageMeta) => {
|
||||
const {
|
||||
name: packageName,
|
||||
version,
|
||||
} = packageMeta.latest;
|
||||
|
||||
const avatarComponent = <Avatar aria-label={name} src={avatar} />;
|
||||
return (
|
||||
<Tooltip title={name}>
|
||||
{this.renderLinkForMail(email, avatarComponent, packageName, version)}
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
const { name: packageName, version } = packageMeta.latest;
|
||||
|
||||
const avatarComponent = <Avatar aria-label={name} src={avatar} />;
|
||||
return <Tooltip title={name}>{this.renderLinkForMail(email, avatarComponent, packageName, version)}</Tooltip>;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
export default Developers;
|
||||
|
||||
@@ -2,13 +2,12 @@
|
||||
* @prettier
|
||||
*/
|
||||
|
||||
/* eslint-disable */
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import List from '@material-ui/core/List/index';
|
||||
|
||||
import { DetailContextConsumer } from '../../pages/version/index';
|
||||
|
||||
import { Heading, DistListItem, DistChips, DownloadButton } from './styles';
|
||||
import { Heading, DistListItem, DistChips } from './styles';
|
||||
import fileSizeSI from '../../utils/file-size';
|
||||
|
||||
class Dist extends Component<any, any> {
|
||||
@@ -34,10 +33,11 @@ class Dist extends Component<any, any> {
|
||||
if (value) {
|
||||
const label = (
|
||||
<span>
|
||||
<b>{title.split('-').join(' ')}</b>: {value}
|
||||
{/* eslint-disable-next-line */}
|
||||
<b>{title.split('-').join(' ')}</b>:{value}
|
||||
</span>
|
||||
);
|
||||
componentList.push(<DistChips label={label} key={key} />);
|
||||
componentList.push(<DistChips key={key} label={label} />);
|
||||
}
|
||||
return componentList;
|
||||
}, []);
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
/* eslint-disable */
|
||||
import React, {Component} from 'react';
|
||||
/**
|
||||
* @prettier
|
||||
*/
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import Avatar from '@material-ui/core/Avatar/index';
|
||||
import Grid from '@material-ui/core/Grid/index';
|
||||
@@ -7,29 +10,27 @@ import List from '@material-ui/core/List/index';
|
||||
import ListItemText from '@material-ui/core/ListItemText/index';
|
||||
|
||||
import { DetailContextConsumer } from '../../pages/version/index';
|
||||
|
||||
import { Heading, EngineListItem } from './styles';
|
||||
import node from './img/node.png';
|
||||
import npm from '../Install/img/npm.svg'
|
||||
|
||||
import npm from '../Install/img/npm.svg';
|
||||
|
||||
const ICONS = {
|
||||
'node-JS': <Avatar src={node} />,
|
||||
'NPM-version': <Avatar src={npm} />,
|
||||
}
|
||||
};
|
||||
|
||||
class Engine extends Component {
|
||||
render() {
|
||||
return (
|
||||
<DetailContextConsumer>
|
||||
{(context) => {
|
||||
{context => {
|
||||
return this.renderEngine(context);
|
||||
}}
|
||||
</DetailContextConsumer>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
renderEngine = ({packageMeta}) => {
|
||||
renderEngine = ({ packageMeta }) => {
|
||||
const { engines } = packageMeta.latest;
|
||||
if (!engines) {
|
||||
return null;
|
||||
@@ -37,14 +38,14 @@ class Engine extends Component {
|
||||
|
||||
const engineDict = {
|
||||
'node-JS': engines.node,
|
||||
'NPM-version': engines.npm
|
||||
}
|
||||
'NPM-version': engines.npm,
|
||||
};
|
||||
|
||||
const items = Object.keys(engineDict).reduce((markup, text, key) => {
|
||||
const heading = engineDict[text]
|
||||
if (heading){
|
||||
const heading = engineDict[text];
|
||||
if (heading) {
|
||||
markup.push(
|
||||
<Grid item={true} xs={6} key={key}>
|
||||
<Grid item={true} key={key} xs={6}>
|
||||
{this.renderListItems(heading, text)}
|
||||
</Grid>
|
||||
);
|
||||
@@ -56,23 +57,19 @@ class Engine extends Component {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Grid container={true}>
|
||||
{items}
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
return <Grid container={true}>{items}</Grid>;
|
||||
};
|
||||
|
||||
renderListItems = (heading, text) => {
|
||||
return (
|
||||
<List subheader={<Heading variant={"subheading"}>{text.split('-').join(' ')}</Heading>}>
|
||||
<List subheader={<Heading variant={'subheading'}>{text.split('-').join(' ')}</Heading>}>
|
||||
<EngineListItem>
|
||||
{ ICONS[text] }
|
||||
{ICONS[text]}
|
||||
<ListItemText primary={heading} />
|
||||
</EngineListItem>
|
||||
</List>
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default Engine;
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
import React from 'react';
|
||||
import type { Element } from 'react';
|
||||
|
||||
import { version } from '../../../../package.json';
|
||||
import { Wrapper, Left, Right, Earth, Flags, Love, Flag, Logo, Inner, ToolTip } from './styles';
|
||||
import { goToVerdaccioWebsite } from '../../utils/windows.js';
|
||||
|
||||
@@ -28,7 +27,7 @@ const MADEWITH_LABEL = ' Made with';
|
||||
const ON_LABEL = 'on';
|
||||
const HEARTH_EMOJI = '♥';
|
||||
|
||||
const renderRight = () => (
|
||||
const renderRight = (version = window.VERDACCIO_VERSION) => (
|
||||
<Right>
|
||||
{POWERED_LABEL}
|
||||
<Logo img={true} name={'verdaccio'} onClick={goToVerdaccioWebsite} pointer={true} size={'md'} />
|
||||
|
||||
@@ -6,12 +6,13 @@
|
||||
import styled, { css } from 'react-emotion';
|
||||
import mq from '../../utils/styles/media';
|
||||
import Icon from '../Icon';
|
||||
import colors from '../../utils/styles/colors';
|
||||
|
||||
export const Wrapper = styled.div`
|
||||
&& {
|
||||
background: #f9f9f9;
|
||||
border-top: 1px solid #e3e3e3;
|
||||
color: #999999;
|
||||
background: ${colors.snow};
|
||||
border-top: 1px solid ${colors.greyGainsboro};
|
||||
color: ${colors.nobel01};
|
||||
font-size: 14px;
|
||||
padding: 20px;
|
||||
}
|
||||
@@ -67,7 +68,7 @@ export const Earth = styled(Icon)`
|
||||
export const Flags = styled.span`
|
||||
&& {
|
||||
position: absolute;
|
||||
background: #d3dddd;
|
||||
background: ${colors.greyAthens};
|
||||
padding: 1px 4px;
|
||||
border-radius: 3px;
|
||||
height: 20px;
|
||||
@@ -82,7 +83,7 @@ export const Flags = styled.span`
|
||||
left: -4px;
|
||||
margin-left: -5px;
|
||||
border: 5px solid;
|
||||
border-color: #d3dddd transparent transparent transparent;
|
||||
border-color: ${colors.greyAthens} transparent transparent transparent;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
${ToolTip}:hover & {
|
||||
@@ -93,7 +94,7 @@ export const Flags = styled.span`
|
||||
|
||||
export const Love = styled.span`
|
||||
&& {
|
||||
color: #e25555;
|
||||
color: ${colors.love};
|
||||
padding: 0 5px;
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
Text,
|
||||
WrapperLink,
|
||||
} from './styles';
|
||||
import { isURL } from '../../utils/url';
|
||||
|
||||
const Package = ({
|
||||
author: { name: authorName, avatar: authorAvatar },
|
||||
@@ -92,7 +93,8 @@ const Package = ({
|
||||
);
|
||||
|
||||
const renderHomePageLink = () =>
|
||||
homepage && (
|
||||
homepage &&
|
||||
isURL(homepage) && (
|
||||
<a href={homepage} target={'_blank'}>
|
||||
<Tooltip aria-label={'Homepage'} title={'Visit homepage'}>
|
||||
<IconButton aria-label={'Homepage'}>
|
||||
@@ -104,7 +106,8 @@ const Package = ({
|
||||
);
|
||||
|
||||
const renderBugsLink = () =>
|
||||
url && (
|
||||
url &&
|
||||
isURL(url) && (
|
||||
<a href={url} target={'_blank'}>
|
||||
<Tooltip aria-label={'Bugs'} title={'Open an issue'}>
|
||||
<IconButton aria-label={'Bugs'}>
|
||||
|
||||
@@ -10,6 +10,7 @@ import CopyToClipBoard from '../CopyToClipBoard';
|
||||
|
||||
import { Heading, GithubLink, RepositoryListItem } from './styles';
|
||||
import git from './img/git.png';
|
||||
import { isURL } from '../../utils/url';
|
||||
|
||||
class Repository extends Component<any, any> {
|
||||
render() {
|
||||
@@ -33,7 +34,7 @@ class Repository extends Component<any, any> {
|
||||
} = {},
|
||||
} = packageMeta.latest;
|
||||
|
||||
if (!url) {
|
||||
if (!url || isURL(url) === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ import ListItem from '@material-ui/core/ListItem/index';
|
||||
import React from 'react';
|
||||
import { DIST_TAGS } from '../../../lib/constants';
|
||||
|
||||
const NOT_AVAILABLE = 'Not available';
|
||||
|
||||
class Versions extends React.PureComponent<any> {
|
||||
render() {
|
||||
return (
|
||||
@@ -32,7 +34,8 @@ class Versions extends React.PureComponent<any> {
|
||||
<ListItem className={'version-item'} key={version}>
|
||||
<ListItemText>{version}</ListItemText>
|
||||
<Spacer />
|
||||
<ListItemText>{isVersion && timeMap[version] ? `${formatDateDistance(timeMap[version])} ago` : packages[version]}</ListItemText>
|
||||
{isVersion && <ListItemText>{timeMap[version] ? `${formatDateDistance(timeMap[version])} ago` : NOT_AVAILABLE}</ListItemText>}
|
||||
{isVersion === false && <ListItemText>{packages[version]}</ListItemText>}
|
||||
</ListItem>
|
||||
))}
|
||||
</List>
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
*/
|
||||
|
||||
import { createBrowserHistory } from 'history';
|
||||
import { getBaseNamePath } from './utils/url';
|
||||
|
||||
const history = createBrowserHistory();
|
||||
const history = createBrowserHistory({
|
||||
basename: getBaseNamePath(),
|
||||
});
|
||||
|
||||
export default history;
|
||||
|
||||
@@ -9,9 +9,13 @@
|
||||
<link rel="icon" type="image/png" href="<%= htmlWebpackPlugin.options.verdaccioURL %>/-/static/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<script>
|
||||
window.__VERDACCIO_BASENAME_UI_OPTIONS = JSON.parse('<%= htmlWebpackPlugin.options.__UI_OPTIONS %>');
|
||||
window.VERDACCIO_BASENAME = '<%= htmlWebpackPlugin.options.basename %>';
|
||||
window.VERDACCIO_API_URL = '<%= htmlWebpackPlugin.options.verdaccioURL %>/-/verdaccio/';
|
||||
window.VERDACCIO_SCOPE = '<%= htmlWebpackPlugin.options.scope %>';
|
||||
window.VERDACCIO_LOGO = '<%= htmlWebpackPlugin.options.logo %>';
|
||||
window.VERDACCIO_PRIMARY_COLOR = '<%= htmlWebpackPlugin.options.primary_color %>';
|
||||
window.VERDACCIO_VERSION = '<%= htmlWebpackPlugin.options.version_app %>';
|
||||
</script>
|
||||
</head>
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ export const copyToClipBoardUtility = (str: string) => (event: SyntheticEvent<HT
|
||||
};
|
||||
|
||||
export function getCLISetConfigRegistry(command: string, scope: string, registryUrl: string): string {
|
||||
return `${command} ${scope} registry ${registryUrl}`;
|
||||
return `${command} ${scope}registry ${registryUrl}`;
|
||||
}
|
||||
|
||||
export function getCLISetRegistry(command: string, registryUrl: string): string {
|
||||
|
||||
@@ -22,6 +22,7 @@ const colors = {
|
||||
paleNavy: '#e4e8f1',
|
||||
saltpan: '#f7f8f6',
|
||||
snow: '#f9f9f9',
|
||||
love: '#e25555',
|
||||
|
||||
nobel01: '#999999',
|
||||
nobel02: '#9f9f9f',
|
||||
@@ -29,7 +30,7 @@ const colors = {
|
||||
// Main colors
|
||||
// -------------------------
|
||||
|
||||
primary: '#4b5e40',
|
||||
primary: window.VERDACCIO_PRIMARY_COLOR || '#4b5e40',
|
||||
secondary: '#20232a',
|
||||
|
||||
};
|
||||
|
||||
@@ -1,4 +1,26 @@
|
||||
import isURLValidator from 'validator/lib/isURL';
|
||||
import isEmailValidator from 'validator/lib/isEmail';
|
||||
|
||||
export function isURL(url) {
|
||||
return isURLValidator(url || '', {
|
||||
protocols: ['http', 'https', 'git+https'],
|
||||
require_protocol: true,
|
||||
});
|
||||
}
|
||||
|
||||
export function isEmail(email) {
|
||||
return isEmailValidator(email || '');
|
||||
}
|
||||
|
||||
export function getRegistryURL() {
|
||||
// Don't add slash if it's not a sub directory
|
||||
return `${location.origin}${location.pathname === '/' ? '' : location.pathname}`;
|
||||
}
|
||||
|
||||
export function getBaseNamePath() {
|
||||
return window.__VERDACCIO_BASENAME_UI_OPTIONS.url_prefix;
|
||||
}
|
||||
|
||||
export function getRootPath() {
|
||||
return window.__VERDACCIO_BASENAME_UI_OPTIONS.base;
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
import path from 'path';
|
||||
|
||||
export const parseConfigurationFile = (name) => {
|
||||
return path.join(__dirname, `./partials/config/yaml/${name}.yaml`);
|
||||
};
|
||||
@@ -1,11 +1,11 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import storage from '../../../src/webui/utils/storage';
|
||||
import App from '../../../src/webui/app';
|
||||
import storage from '../../src/webui/utils/storage';
|
||||
import App from '../../src/webui/app';
|
||||
|
||||
import { generateTokenWithTimeRange } from './components/__mocks__/token';
|
||||
|
||||
jest.mock('../../../src/webui/utils/storage', () => {
|
||||
jest.mock('../../src/webui/utils/storage', () => {
|
||||
class LocalStorageMock {
|
||||
constructor() {
|
||||
this.store = {};
|
||||
@@ -26,7 +26,7 @@ jest.mock('../../../src/webui/utils/storage', () => {
|
||||
return new LocalStorageMock();
|
||||
});
|
||||
|
||||
jest.mock('../../../src/webui/utils/api', () => ({
|
||||
jest.mock('../../src/webui/utils/api', () => ({
|
||||
request: require('./components/__mocks__/api').default.request
|
||||
}));
|
||||
|
||||
@@ -36,7 +36,7 @@ describe('App', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = mount(<App />);
|
||||
});
|
||||
|
||||
|
||||
test('toggleLoginModal: should toggle the value in state', () => {
|
||||
const { handleToggleLoginModal } = wrapper.instance();
|
||||
expect(wrapper.state().showLoginModal).toBeFalsy();
|
||||
@@ -1,3 +1,3 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<Footer /> component should load the initial state of Footer component 1`] = `"<div class=\\"css-i0nj2g e19gp4r80\\"><div class=\\"css-hzfs9b e19gp4r81\\"><div class=\\"css-d8nsp7 e19gp4r82\\"> Made with<span class=\\"css-1so4oe0 e19gp4r87\\">♥</span>on<span class=\\"css-1ie354y e19gp4r84\\"><svg class=\\"e19gp4r85 css-1kgp95j e9byyw50\\"><title>Earth</title><use xlink:href=\\"[object Object]#earth\\"></use></svg><span class=\\"css-1v4n0q4 e19gp4r86\\"><svg class=\\"e19gp4r88 css-f1ndto e9byyw50\\"><title>Spain</title><use xlink:href=\\"[object Object]#spain\\"></use></svg><svg class=\\"e19gp4r88 css-f1ndto e9byyw50\\"><title>Nicaragua</title><use xlink:href=\\"[object Object]#nicaragua\\"></use></svg><svg class=\\"e19gp4r88 css-f1ndto e9byyw50\\"><title>India</title><use xlink:href=\\"[object Object]#india\\"></use></svg><svg class=\\"e19gp4r88 css-f1ndto e9byyw50\\"><title>Brazil</title><use xlink:href=\\"[object Object]#brazil\\"></use></svg><svg class=\\"e19gp4r88 css-f1ndto e9byyw50\\"><title>China</title><use xlink:href=\\"[object Object]#china\\"></use></svg><svg class=\\"e19gp4r88 css-f1ndto e9byyw50\\"><title>Austria</title><use xlink:href=\\"[object Object]#austria\\"></use></svg></span></span></div><div class=\\"css-1wbzdyy e19gp4r83\\">Powered by<span class=\\"e19gp4r88 css-i15wza e9byyw51\\" title=\\"Verdaccio\\"><img alt=\\"Verdaccio\\" src=\\"[object Object]\\" class=\\"css-1ncdhax e9byyw52\\"></span>/ 4.0.0-alpha.3</div></div></div>"`;
|
||||
exports[`<Footer /> component should load the initial state of Footer component 1`] = `"<div class=\\"css-i0nj2g e19gp4r80\\"><div class=\\"css-hzfs9b e19gp4r81\\"><div class=\\"css-d8nsp7 e19gp4r82\\"> Made with<span class=\\"css-1so4oe0 e19gp4r87\\">♥</span>on<span class=\\"css-1ie354y e19gp4r84\\"><svg class=\\"e19gp4r85 css-1kgp95j e9byyw50\\"><title>Earth</title><use xlink:href=\\"[object Object]#earth\\"></use></svg><span class=\\"css-1v4n0q4 e19gp4r86\\"><svg class=\\"e19gp4r88 css-f1ndto e9byyw50\\"><title>Spain</title><use xlink:href=\\"[object Object]#spain\\"></use></svg><svg class=\\"e19gp4r88 css-f1ndto e9byyw50\\"><title>Nicaragua</title><use xlink:href=\\"[object Object]#nicaragua\\"></use></svg><svg class=\\"e19gp4r88 css-f1ndto e9byyw50\\"><title>India</title><use xlink:href=\\"[object Object]#india\\"></use></svg><svg class=\\"e19gp4r88 css-f1ndto e9byyw50\\"><title>Brazil</title><use xlink:href=\\"[object Object]#brazil\\"></use></svg><svg class=\\"e19gp4r88 css-f1ndto e9byyw50\\"><title>China</title><use xlink:href=\\"[object Object]#china\\"></use></svg><svg class=\\"e19gp4r88 css-f1ndto e9byyw50\\"><title>Austria</title><use xlink:href=\\"[object Object]#austria\\"></use></svg></span></span></div><div class=\\"css-1wbzdyy e19gp4r83\\">Powered by<span class=\\"e19gp4r88 css-i15wza e9byyw51\\" title=\\"Verdaccio\\"><img alt=\\"Verdaccio\\" src=\\"[object Object]\\" class=\\"css-1ncdhax e9byyw52\\"></span>/ v.1.0.0</div></div></div>"`;
|
||||
5
test/unit/components/__snapshots__/login.spec.js.snap
Normal file
5
test/unit/components/__snapshots__/login.spec.js.snap
Normal file
@@ -0,0 +1,5 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<LoginModal /> should load the component in default state 1`] = `"<div role=\\"dialog\\" class=\\"mui-fixed MuiModal-root-15 MuiDialog-root-1\\" id=\\"login--form-container\\" style=\\"padding-right: 0px;\\"><div class=\\"MuiBackdrop-root-17\\" aria-hidden=\\"true\\" style=\\"opacity: 1; webkit-transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;\\"></div><div class=\\"MuiDialog-container-4 MuiDialog-scrollPaper-2\\" role=\\"document\\" style=\\"opacity: 1; webkit-transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;\\" tabindex=\\"-1\\"><div class=\\"MuiPaper-root-19 MuiPaper-elevation24-45 MuiPaper-rounded-20 MuiDialog-paper-5 MuiDialog-paperScrollPaper-6 MuiDialog-paperWidthXs-8 MuiDialog-paperFullWidth-13\\"><form novalidate=\\"\\"><div class=\\"MuiDialogTitle-root-46\\"><h2 class=\\"MuiTypography-root-47 MuiTypography-title-53\\">Login</h2></div><div class=\\"MuiDialogContent-root-83\\"><div class=\\"MuiFormControl-root-84 MuiFormControl-fullWidth-87\\"><label class=\\"MuiFormLabel-root-99 MuiFormLabel-required-104 MuiInputLabel-required-92 MuiInputLabel-root-88 MuiInputLabel-formControl-93 MuiInputLabel-animated-96\\" data-shrink=\\"false\\" for=\\"username\\">Username<span class=\\"MuiFormLabel-asterisk-105\\"> *</span></label><div class=\\"MuiInputBase-root-119 MuiInput-root-106 MuiInput-underline-110 MuiInputBase-formControl-120 MuiInput-formControl-107\\"><input aria-invalid=\\"false\\" class=\\"MuiInputBase-input-129 MuiInput-input-114\\" id=\\"login--form-username\\" placeholder=\\"Your username\\" required=\\"\\" type=\\"text\\" value=\\"\\"></div></div><div class=\\"MuiFormControl-root-84 MuiFormControl-fullWidth-87\\" style=\\"margin-top: 8px;\\"><label class=\\"MuiFormLabel-root-99 MuiFormLabel-required-104 MuiInputLabel-required-92 MuiInputLabel-root-88 MuiInputLabel-formControl-93 MuiInputLabel-animated-96\\" data-shrink=\\"false\\" for=\\"password\\">Password<span class=\\"MuiFormLabel-asterisk-105\\"> *</span></label><div class=\\"MuiInputBase-root-119 MuiInput-root-106 MuiInput-underline-110 MuiInputBase-formControl-120 MuiInput-formControl-107\\"><input aria-invalid=\\"false\\" class=\\"MuiInputBase-input-129 MuiInput-input-114 MuiInputBase-inputType-132 MuiInput-inputType-117\\" id=\\"login--form-password\\" placeholder=\\"Your strong password\\" required=\\"\\" type=\\"password\\" value=\\"\\"></div></div></div><div class=\\"MuiDialogActions-root-136 dialog-footer\\"><button class=\\"MuiButtonBase-root-164 MuiButton-root-138 MuiButton-text-140 MuiButton-flat-143 MuiButton-colorInherit-159 MuiDialogActions-action-137\\" tabindex=\\"0\\" type=\\"button\\" id=\\"login--form-cancel\\"><span class=\\"MuiButton-label-139\\">Cancel</span><span class=\\"MuiTouchRipple-root-167\\"></span></button><button class=\\"MuiButtonBase-root-164 MuiButtonBase-disabled-165 MuiButton-root-138 MuiButton-text-140 MuiButton-flat-143 MuiButton-disabled-158 MuiButton-colorInherit-159 MuiDialogActions-action-137\\" tabindex=\\"-1\\" type=\\"submit\\" disabled=\\"\\" id=\\"login--form-submit\\"><span class=\\"MuiButton-label-139\\">Login</span></button></div></form></div></div></div>"`;
|
||||
|
||||
exports[`<LoginModal /> should load the component with props 1`] = `"<div role=\\"dialog\\" class=\\"mui-fixed MuiModal-root-15 MuiDialog-root-1\\" id=\\"login--form-container\\"><div class=\\"MuiBackdrop-root-17\\" aria-hidden=\\"true\\" style=\\"opacity: 1; webkit-transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;\\"></div><div class=\\"MuiDialog-container-4 MuiDialog-scrollPaper-2\\" role=\\"document\\" style=\\"opacity: 1; webkit-transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;\\" tabindex=\\"-1\\"><div class=\\"MuiPaper-root-19 MuiPaper-elevation24-45 MuiPaper-rounded-20 MuiDialog-paper-5 MuiDialog-paperScrollPaper-6 MuiDialog-paperWidthXs-8 MuiDialog-paperFullWidth-13\\"><form novalidate=\\"\\"><div class=\\"MuiDialogTitle-root-46\\"><h2 class=\\"MuiTypography-root-47 MuiTypography-title-53\\">Login</h2></div><div class=\\"MuiDialogContent-root-83\\"><div class=\\"MuiTypography-root-47 MuiTypography-body1-56 MuiPaper-root-19 MuiPaper-elevation6-27 MuiSnackbarContent-root-174 loginError\\" role=\\"alertdialog\\"><div class=\\"MuiSnackbarContent-message-175\\"><div class=\\"loginErrorMsg\\" id=\\"client-snackbar\\"><svg class=\\"MuiSvgIcon-root-177 loginIcon\\" focusable=\\"false\\" viewBox=\\"0 0 24 24\\" aria-hidden=\\"true\\" role=\\"presentation\\"><path fill=\\"none\\" d=\\"M0 0h24v24H0z\\"></path><path d=\\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z\\"></path></svg><span><div><strong>Error Title</strong></div><div>Error Description</div></span></div></div></div><div class=\\"MuiFormControl-root-84 MuiFormControl-fullWidth-87\\"><label class=\\"MuiFormLabel-root-99 MuiFormLabel-required-104 MuiInputLabel-required-92 MuiInputLabel-root-88 MuiInputLabel-formControl-93 MuiInputLabel-animated-96\\" data-shrink=\\"false\\" for=\\"username\\">Username<span class=\\"MuiFormLabel-asterisk-105\\"> *</span></label><div class=\\"MuiInputBase-root-119 MuiInput-root-106 MuiInput-underline-110 MuiInputBase-formControl-120 MuiInput-formControl-107\\"><input aria-invalid=\\"false\\" class=\\"MuiInputBase-input-129 MuiInput-input-114\\" id=\\"login--form-username\\" placeholder=\\"Your username\\" required=\\"\\" type=\\"text\\" value=\\"\\"></div></div><div class=\\"MuiFormControl-root-84 MuiFormControl-fullWidth-87\\" style=\\"margin-top: 8px;\\"><label class=\\"MuiFormLabel-root-99 MuiFormLabel-required-104 MuiInputLabel-required-92 MuiInputLabel-root-88 MuiInputLabel-formControl-93 MuiInputLabel-animated-96\\" data-shrink=\\"false\\" for=\\"password\\">Password<span class=\\"MuiFormLabel-asterisk-105\\"> *</span></label><div class=\\"MuiInputBase-root-119 MuiInput-root-106 MuiInput-underline-110 MuiInputBase-formControl-120 MuiInput-formControl-107\\"><input aria-invalid=\\"false\\" class=\\"MuiInputBase-input-129 MuiInput-input-114 MuiInputBase-inputType-132 MuiInput-inputType-117\\" id=\\"login--form-password\\" placeholder=\\"Your strong password\\" required=\\"\\" type=\\"password\\" value=\\"\\"></div></div></div><div class=\\"MuiDialogActions-root-136 dialog-footer\\"><button class=\\"MuiButtonBase-root-164 MuiButton-root-138 MuiButton-text-140 MuiButton-flat-143 MuiButton-colorInherit-159 MuiDialogActions-action-137\\" tabindex=\\"0\\" type=\\"button\\" id=\\"login--form-cancel\\"><span class=\\"MuiButton-label-139\\">Cancel</span><span class=\\"MuiTouchRipple-root-167\\"></span></button><button class=\\"MuiButtonBase-root-164 MuiButtonBase-disabled-165 MuiButton-root-138 MuiButton-text-140 MuiButton-flat-143 MuiButton-disabled-158 MuiButton-colorInherit-159 MuiDialogActions-action-137\\" tabindex=\\"-1\\" type=\\"submit\\" disabled=\\"\\" id=\\"login--form-submit\\"><span class=\\"MuiButton-label-139\\">Login</span></button></div></form></div></div></div>"`;
|
||||
@@ -1,3 +1,3 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<NotFound /> component should load the component in default state 1`] = `ShallowWrapper {}`;
|
||||
exports[`<NotFound /> component should load the component in default state 1`] = `<withRouter(WithTheme(WithWidth(NotFound))) />`;
|
||||
File diff suppressed because one or more lines are too long
@@ -1,3 +1,3 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<Search /> component test should load the component in default state 1`] = `"<div class=\\"css-1crzyyo e18292mt0\\"><div role=\\"combobox\\" aria-haspopup=\\"listbox\\" aria-owns=\\"react-autowhatever-1\\" aria-expanded=\\"false\\" class=\\"react-autosuggest__container\\"><div class=\\"MuiFormControl-root-1 MuiFormControl-fullWidth-4 react-autosuggest__input\\" aria-autocomplete=\\"list\\" aria-controls=\\"react-autowhatever-1\\"><div class=\\"MuiInputBase-root-18 MuiInput-root-5 css-n9ojyg MuiInput-underline-9 MuiInputBase-fullWidth-27 MuiInput-fullWidth-12 MuiInputBase-formControl-19 MuiInput-formControl-6 MuiInputBase-adornedStart-22\\"><div class=\\"MuiInputAdornment-root-35 MuiInputAdornment-positionStart-37\\" style=\\"color: rgb(255, 255, 255);\\"><svg class=\\"MuiSvgIcon-root-40\\" focusable=\\"false\\" viewBox=\\"0 0 24 24\\" aria-hidden=\\"true\\" role=\\"presentation\\"><path d=\\"M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z\\"></path><path fill=\\"none\\" d=\\"M0 0h24v24H0z\\"></path></svg></div><input aria-invalid=\\"false\\" autocomplete=\\"off\\" class=\\"MuiInputBase-input-28 MuiInput-input-13 css-hodoyq MuiInputBase-inputAdornedStart-33\\" placeholder=\\"Search Packages\\" type=\\"text\\" value=\\"\\"></div></div><div class=\\"MuiPaper-root-49 MuiPaper-elevation2-53 react-autosuggest__suggestions-container\\" id=\\"react-autowhatever-1\\" role=\\"listbox\\"></div></div></div>"`;
|
||||
exports[`<Search /> component test should load the component in default state 1`] = `"<div class=\\"css-1crzyyo e18292mt0\\"><div role=\\"combobox\\" aria-haspopup=\\"listbox\\" aria-owns=\\"react-autowhatever-1\\" aria-expanded=\\"false\\" class=\\"react-autosuggest__container\\"><div class=\\"MuiFormControl-root-1 MuiFormControl-fullWidth-4 react-autosuggest__input\\" aria-autocomplete=\\"list\\" aria-controls=\\"react-autowhatever-1\\"><div class=\\"MuiInputBase-root-18 MuiInput-root-5 css-n9ojyg MuiInput-underline-9 MuiInputBase-fullWidth-27 MuiInput-fullWidth-12 MuiInputBase-formControl-19 MuiInput-formControl-6 MuiInputBase-adornedStart-22\\"><div class=\\"MuiInputAdornment-root-35 MuiInputAdornment-positionStart-37\\" style=\\"color: rgb(255, 255, 255);\\"><svg class=\\"MuiSvgIcon-root-40\\" focusable=\\"false\\" viewBox=\\"0 0 24 24\\" aria-hidden=\\"true\\" role=\\"presentation\\"><path d=\\"M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z\\"></path><path fill=\\"none\\" d=\\"M0 0h24v24H0z\\"></path></svg></div><input aria-invalid=\\"false\\" autocomplete=\\"off\\" class=\\"MuiInputBase-input-28 MuiInput-input-13 css-hodoyq MuiInputBase-inputAdornedStart-33\\" placeholder=\\"Search Packages\\" type=\\"text\\" value=\\"\\"></div></div><div class=\\"MuiPaper-root-49 MuiPaper-elevation2-53 react-autosuggest__suggestions-container css-cfo6a e18292mt1\\" id=\\"react-autowhatever-1\\" role=\\"listbox\\"></div></div></div>"`;
|
||||
@@ -6,8 +6,8 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import CopyToClipBoard from '../../../../src/webui/components/CopyToClipBoard';
|
||||
import { CopyIcon } from '../../../../src/webui/components/CopyToClipBoard/styles';
|
||||
import CopyToClipBoard from '../../../src/webui/components/CopyToClipBoard/index';
|
||||
import { CopyIcon } from '../../../src/webui/components/CopyToClipBoard/styles';
|
||||
|
||||
describe('<CopyToClipBoard /> component', () => {
|
||||
let wrapper;
|
||||
@@ -2,16 +2,18 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
|
||||
import Footer from '../../../../src/webui/components/Footer/index';
|
||||
import Footer from '../../../src/webui/components/Footer/index';
|
||||
|
||||
jest.mock('../../../../package.json', () => ({
|
||||
jest.mock('../../../package.json', () => ({
|
||||
version: '4.0.0-alpha.3'
|
||||
}))
|
||||
}));
|
||||
|
||||
describe('<Footer /> component', () => {
|
||||
let wrapper;
|
||||
beforeEach(() => {
|
||||
window.VERDACCIO_VERSION = 'v.1.0.0';
|
||||
wrapper = mount(<Footer />);
|
||||
delete window.VERDACCIO_VERSION;
|
||||
});
|
||||
|
||||
test('should load the initial state of Footer component', () => {
|
||||
@@ -6,7 +6,7 @@
|
||||
import React from 'react';
|
||||
import { BrowserRouter as Router } from 'react-router-dom';
|
||||
import { shallow } from 'enzyme';
|
||||
import Header from '../../../../src/webui/components/Header';
|
||||
import Header from '../../../src/webui/components/Header/index';
|
||||
|
||||
describe('<Header /> component with logged in state', () => {
|
||||
let wrapper;
|
||||
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import Help from '../../../../src/webui/components/Help/index';
|
||||
import Help from '../../../src/webui/components/Help/index';
|
||||
|
||||
describe('<Help /> component', () => {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
|
||||
import LoginModal from '../../../../src/webui/components/Login';
|
||||
import LoginModal from '../../../src/webui/components/Login/index';
|
||||
|
||||
const eventUsername = {
|
||||
target: {
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import React from 'react';
|
||||
import { shallow, mount } from 'enzyme';
|
||||
import NoItems from '../../../../src/webui/components/NoItems/index';
|
||||
import NoItems from '../../../src/webui/components/NoItems/index';
|
||||
|
||||
console.error = jest.fn();
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import React from 'react';
|
||||
import { BrowserRouter as Router } from 'react-router-dom';
|
||||
import { shallow } from 'enzyme';
|
||||
import NotFound from '../../../../src/webui/components/NotFound/index';
|
||||
import NotFound from '../../../src/webui/components/NotFound/index';
|
||||
|
||||
console.error = jest.fn();
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import Package from '../../../../src/webui/components/Package/index';
|
||||
import Tag from '../../../../src/webui/components/Tag/index';
|
||||
import { Version, WrapperLink, Field, OverviewItem } from '../../../../src/webui/components/Package/styles';
|
||||
import Package from '../../../src/webui/components/Package/index';
|
||||
import Tag from '../../../src/webui/components/Tag/index';
|
||||
import { Version, WrapperLink, Field, OverviewItem } from '../../../src/webui/components/Package/styles';
|
||||
|
||||
|
||||
/**
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import PackageList from '../../../../src/webui/components/PackageList/index';
|
||||
import Help from '../../../../src/webui/components/Help/index';
|
||||
import PackageList from '../../../src/webui/components/PackageList/index';
|
||||
import Help from '../../../src/webui/components/Help/index';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
|
||||
describe('<PackageList /> component', () => {
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import React from 'react';
|
||||
import { shallow, mount } from 'enzyme';
|
||||
import Readme from '../../../../src/webui/components/Readme/index';
|
||||
import Readme from '../../../src/webui/components/Readme/index';
|
||||
|
||||
describe('<Readme /> component', () => {
|
||||
test('should load the component in default state', () => {
|
||||
@@ -6,11 +6,11 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
|
||||
import { Search } from '../../../../src/webui/components/Search/index';
|
||||
import { Search } from '../../../src/webui/components/Search/index';
|
||||
|
||||
const SEARCH_FILE_PATH = '../../../../src/webui/components/Search/index';
|
||||
const API_FILE_PATH = '../../../../src/webui/utils/api';
|
||||
const URL_FILE_PATH = '../../../../src/webui/utils/url';
|
||||
const SEARCH_FILE_PATH = '../../../src/webui/components/Search/index';
|
||||
const API_FILE_PATH = '../../../src/webui/utils/api';
|
||||
const URL_FILE_PATH = '../../../src/webui/utils/url';
|
||||
|
||||
// Global mocks
|
||||
const event = {
|
||||
@@ -1,4 +1,4 @@
|
||||
import {API_ERROR} from '../../../../../src/lib/constants';
|
||||
import {API_ERROR} from '../../../../src/lib/constants';
|
||||
/**
|
||||
* API mock for login endpoint
|
||||
* @param {object} config configuration of api call
|
||||
@@ -10,6 +10,7 @@ import Adapter from 'enzyme-adapter-react-16';
|
||||
configure({ adapter: new Adapter() });
|
||||
|
||||
global.__APP_VERSION__ = '1.0.0';
|
||||
global.__VERDACCIO_BASENAME_UI_OPTIONS = {};
|
||||
|
||||
// mocking few DOM methods
|
||||
if (global.document) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { isTokenExpire, makeLogin } from '../../../../src/webui/utils/login';
|
||||
import { isTokenExpire, makeLogin } from '../../../src/webui/utils/login';
|
||||
|
||||
import {
|
||||
generateTokenWithTimeRange,
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
formatDateDistance,
|
||||
getLastUpdatedPackageTime,
|
||||
getRecentReleases
|
||||
} from '../../../../src/webui/utils/package';
|
||||
} from '../../../src/webui/utils/package';
|
||||
|
||||
import { packageMeta } from '../components/store/packageMeta';
|
||||
|
||||
@@ -52,13 +52,22 @@ describe('formatDate', () => {
|
||||
|
||||
describe('formatDateDistance', () => {
|
||||
test('should calculate the distance', () => {
|
||||
// const dateAboutTwoMonthsAgo = () => {
|
||||
// const date = new Date();
|
||||
// date.setMonth(date.getMonth() - 1);
|
||||
// date.setDate(date.getDay() - 20);
|
||||
// return date;
|
||||
// };
|
||||
const dateTwoMonthsAgo = () => {
|
||||
const date = new Date();
|
||||
date.setMonth(date.getMonth() - 2);
|
||||
return date;
|
||||
};
|
||||
const date = dateTwoMonthsAgo();
|
||||
expect(formatDateDistance(date)).toEqual('about 2 months');
|
||||
// const date1 = dateAboutTwoMonthsAgo();
|
||||
const date2 = dateTwoMonthsAgo();
|
||||
// FIXME: we need to review this expect, fails every x time.
|
||||
// expect(formatDateDistance(date1)).toEqual('about 2 months');
|
||||
expect(formatDateDistance(date2)).toEqual('2 months');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<LoginModal /> should load the component in default state 1`] = `"<div role=\\"dialog\\" class=\\"mui-fixed MuiModal-root-15 MuiDialog-root-1\\" id=\\"login--form-container\\" style=\\"padding-right: 0px;\\"><div class=\\"MuiBackdrop-root-17\\" aria-hidden=\\"true\\" style=\\"opacity: 1; -webkit-transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;\\"></div><div class=\\"MuiDialog-container-4 MuiDialog-scrollPaper-2\\" role=\\"document\\" style=\\"opacity: 1; -webkit-transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;\\" tabindex=\\"-1\\"><div class=\\"MuiPaper-root-19 MuiPaper-elevation24-45 MuiPaper-rounded-20 MuiDialog-paper-5 MuiDialog-paperScrollPaper-6 MuiDialog-paperWidthXs-8 MuiDialog-paperFullWidth-13\\"><form novalidate=\\"\\"><div class=\\"MuiDialogTitle-root-46\\"><h2 class=\\"MuiTypography-root-47 MuiTypography-title-53\\">Login</h2></div><div class=\\"MuiDialogContent-root-83\\"><div class=\\"MuiFormControl-root-84 MuiFormControl-fullWidth-87\\"><label class=\\"MuiFormLabel-root-99 MuiFormLabel-required-104 MuiInputLabel-required-92 MuiInputLabel-root-88 MuiInputLabel-formControl-93 MuiInputLabel-animated-96\\" data-shrink=\\"false\\" for=\\"username\\">Username<span class=\\"MuiFormLabel-asterisk-105\\"> *</span></label><div class=\\"MuiInputBase-root-119 MuiInput-root-106 MuiInput-underline-110 MuiInputBase-formControl-120 MuiInput-formControl-107\\"><input aria-invalid=\\"false\\" class=\\"MuiInputBase-input-129 MuiInput-input-114\\" id=\\"login--form-username\\" placeholder=\\"Your username\\" required=\\"\\" type=\\"text\\" value=\\"\\"></div></div><div class=\\"MuiFormControl-root-84 MuiFormControl-fullWidth-87\\" style=\\"margin-top: 8px;\\"><label class=\\"MuiFormLabel-root-99 MuiFormLabel-required-104 MuiInputLabel-required-92 MuiInputLabel-root-88 MuiInputLabel-formControl-93 MuiInputLabel-animated-96\\" data-shrink=\\"false\\" for=\\"password\\">Password<span class=\\"MuiFormLabel-asterisk-105\\"> *</span></label><div class=\\"MuiInputBase-root-119 MuiInput-root-106 MuiInput-underline-110 MuiInputBase-formControl-120 MuiInput-formControl-107\\"><input aria-invalid=\\"false\\" class=\\"MuiInputBase-input-129 MuiInput-input-114 MuiInputBase-inputType-132 MuiInput-inputType-117\\" id=\\"login--form-password\\" placeholder=\\"Your strong password\\" required=\\"\\" type=\\"password\\" value=\\"\\"></div></div></div><div class=\\"MuiDialogActions-root-136 dialog-footer\\"><button class=\\"MuiButtonBase-root-164 MuiButton-root-138 MuiButton-text-140 MuiButton-flat-143 MuiButton-colorInherit-159 MuiDialogActions-action-137\\" tabindex=\\"0\\" type=\\"button\\" id=\\"login--form-cancel\\"><span class=\\"MuiButton-label-139\\">Cancel</span><span class=\\"MuiTouchRipple-root-167\\"></span></button><button class=\\"MuiButtonBase-root-164 MuiButtonBase-disabled-165 MuiButton-root-138 MuiButton-text-140 MuiButton-flat-143 MuiButton-disabled-158 MuiButton-colorInherit-159 MuiDialogActions-action-137\\" tabindex=\\"-1\\" type=\\"submit\\" disabled=\\"\\" id=\\"login--form-submit\\"><span class=\\"MuiButton-label-139\\">Login</span></button></div></form></div></div></div>"`;
|
||||
|
||||
exports[`<LoginModal /> should load the component with props 1`] = `"<div role=\\"dialog\\" class=\\"mui-fixed MuiModal-root-15 MuiDialog-root-1\\" id=\\"login--form-container\\"><div class=\\"MuiBackdrop-root-17\\" aria-hidden=\\"true\\" style=\\"opacity: 1; -webkit-transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;\\"></div><div class=\\"MuiDialog-container-4 MuiDialog-scrollPaper-2\\" role=\\"document\\" style=\\"opacity: 1; -webkit-transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;\\" tabindex=\\"-1\\"><div class=\\"MuiPaper-root-19 MuiPaper-elevation24-45 MuiPaper-rounded-20 MuiDialog-paper-5 MuiDialog-paperScrollPaper-6 MuiDialog-paperWidthXs-8 MuiDialog-paperFullWidth-13\\"><form novalidate=\\"\\"><div class=\\"MuiDialogTitle-root-46\\"><h2 class=\\"MuiTypography-root-47 MuiTypography-title-53\\">Login</h2></div><div class=\\"MuiDialogContent-root-83\\"><div class=\\"MuiTypography-root-47 MuiTypography-body1-56 MuiPaper-root-19 MuiPaper-elevation6-27 MuiSnackbarContent-root-174 loginError\\" role=\\"alertdialog\\"><div class=\\"MuiSnackbarContent-message-175\\"><div class=\\"loginErrorMsg\\" id=\\"client-snackbar\\"><svg class=\\"MuiSvgIcon-root-177 loginIcon\\" focusable=\\"false\\" viewBox=\\"0 0 24 24\\" aria-hidden=\\"true\\" role=\\"presentation\\"><path fill=\\"none\\" d=\\"M0 0h24v24H0z\\"></path><path d=\\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z\\"></path></svg><span><div><strong>Error Title</strong></div><div>Error Description</div></span></div></div></div><div class=\\"MuiFormControl-root-84 MuiFormControl-fullWidth-87\\"><label class=\\"MuiFormLabel-root-99 MuiFormLabel-required-104 MuiInputLabel-required-92 MuiInputLabel-root-88 MuiInputLabel-formControl-93 MuiInputLabel-animated-96\\" data-shrink=\\"false\\" for=\\"username\\">Username<span class=\\"MuiFormLabel-asterisk-105\\"> *</span></label><div class=\\"MuiInputBase-root-119 MuiInput-root-106 MuiInput-underline-110 MuiInputBase-formControl-120 MuiInput-formControl-107\\"><input aria-invalid=\\"false\\" class=\\"MuiInputBase-input-129 MuiInput-input-114\\" id=\\"login--form-username\\" placeholder=\\"Your username\\" required=\\"\\" type=\\"text\\" value=\\"\\"></div></div><div class=\\"MuiFormControl-root-84 MuiFormControl-fullWidth-87\\" style=\\"margin-top: 8px;\\"><label class=\\"MuiFormLabel-root-99 MuiFormLabel-required-104 MuiInputLabel-required-92 MuiInputLabel-root-88 MuiInputLabel-formControl-93 MuiInputLabel-animated-96\\" data-shrink=\\"false\\" for=\\"password\\">Password<span class=\\"MuiFormLabel-asterisk-105\\"> *</span></label><div class=\\"MuiInputBase-root-119 MuiInput-root-106 MuiInput-underline-110 MuiInputBase-formControl-120 MuiInput-formControl-107\\"><input aria-invalid=\\"false\\" class=\\"MuiInputBase-input-129 MuiInput-input-114 MuiInputBase-inputType-132 MuiInput-inputType-117\\" id=\\"login--form-password\\" placeholder=\\"Your strong password\\" required=\\"\\" type=\\"password\\" value=\\"\\"></div></div></div><div class=\\"MuiDialogActions-root-136 dialog-footer\\"><button class=\\"MuiButtonBase-root-164 MuiButton-root-138 MuiButton-text-140 MuiButton-flat-143 MuiButton-colorInherit-159 MuiDialogActions-action-137\\" tabindex=\\"0\\" type=\\"button\\" id=\\"login--form-cancel\\"><span class=\\"MuiButton-label-139\\">Cancel</span><span class=\\"MuiTouchRipple-root-167\\"></span></button><button class=\\"MuiButtonBase-root-164 MuiButtonBase-disabled-165 MuiButton-root-138 MuiButton-text-140 MuiButton-flat-143 MuiButton-disabled-158 MuiButton-colorInherit-159 MuiDialogActions-action-137\\" tabindex=\\"-1\\" type=\\"submit\\" disabled=\\"\\" id=\\"login--form-submit\\"><span class=\\"MuiButton-label-139\\">Login</span></button></div></form></div></div></div>"`;
|
||||
File diff suppressed because one or more lines are too long
56
tools/_config.yaml
Normal file
56
tools/_config.yaml
Normal file
@@ -0,0 +1,56 @@
|
||||
web:
|
||||
title: Verdaccio
|
||||
# gravatar: false
|
||||
# sort_packages: asc
|
||||
|
||||
plugins: ../
|
||||
|
||||
auth:
|
||||
auth-memory:
|
||||
users:
|
||||
foo:
|
||||
name: test
|
||||
password: test
|
||||
bar:
|
||||
name: bar
|
||||
password: test
|
||||
store:
|
||||
memory:
|
||||
limit: 1000
|
||||
|
||||
# theme:
|
||||
|
||||
|
||||
security:
|
||||
api:
|
||||
jwt:
|
||||
sign:
|
||||
expiresIn: 60d
|
||||
notBefore: 1
|
||||
web:
|
||||
sign:
|
||||
expiresIn: 7d
|
||||
notBefore: 1
|
||||
|
||||
uplinks:
|
||||
npmjs:
|
||||
url: https://registry.npmjs.org/
|
||||
|
||||
packages:
|
||||
'@*/*':
|
||||
access: $all
|
||||
publish: $authenticated
|
||||
unpublish: $authenticated
|
||||
|
||||
'**':
|
||||
access: $all
|
||||
publish: $authenticated
|
||||
unpublish: $authenticated
|
||||
|
||||
middlewares:
|
||||
audit:
|
||||
enabled: true
|
||||
|
||||
logs:
|
||||
- { type: stdout, format: pretty, level: trace }
|
||||
|
||||
@@ -32,7 +32,7 @@ new WebpackDevServer(compiler, {
|
||||
},
|
||||
proxy: [{
|
||||
context: ['/-/verdaccio/logo', '/-/verdaccio/packages', '/-/static/logo.png'],
|
||||
target: 'http://localhost:4873',
|
||||
target: 'http://localhost:8080',
|
||||
}],
|
||||
}).listen(4872, 'localhost', function(err) {
|
||||
if (err) {
|
||||
|
||||
23
tools/verdaccio.js
Normal file
23
tools/verdaccio.js
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @prettier
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const startServer = require('verdaccio').default;
|
||||
const yalm = require('js-yaml');
|
||||
|
||||
const configJsonFormat = yalm.safeLoad(fs.readFileSync('./tools/_config.yaml', 'utf8'));
|
||||
|
||||
const handler = function(webServer, addr, pkgName, pkgVersion) {
|
||||
webServer.listen(addr.port || addr.path, addr.host, () => {
|
||||
console.log(`${pkgName}:${pkgVersion} running ${addr.proto}://${addr.host}:${addr.port}`);
|
||||
});
|
||||
|
||||
process.on('SIGTERM', () => {
|
||||
webServer.close(() => {
|
||||
console.log('Process terminated');
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
startServer(configJsonFormat, 8080, '', '1.0.0', 'verdaccio', handler);
|
||||
@@ -7,6 +7,7 @@ module.exports = {
|
||||
output: {
|
||||
path: `${env.APP_ROOT}/static/`,
|
||||
filename: '[name].[hash].js',
|
||||
// FIXME: do we need this?
|
||||
publicPath: 'ToReplaceByVerdaccio/-/static',
|
||||
},
|
||||
|
||||
|
||||
@@ -34,11 +34,12 @@ export default {
|
||||
__APP_VERSION__: `"${getPackageJson('version')}"`,
|
||||
}),
|
||||
new HTMLWebpackPlugin({
|
||||
__UI_OPTIONS: JSON.stringify({base: '/'}),
|
||||
title: 'Verdaccio Dev UI',
|
||||
scope: '',
|
||||
logo: 'https://verdaccio.org/img/logo/symbol/svg/verdaccio-tiny.svg',
|
||||
filename: 'index.html',
|
||||
verdaccioURL: '//localhost:4873',
|
||||
verdaccioURL: '//localhost:8080',
|
||||
template: `${env.SRC_ROOT}/webui/template/index.html`,
|
||||
debug: true,
|
||||
inject: true,
|
||||
|
||||
@@ -45,11 +45,15 @@ const prodConf = {
|
||||
}),
|
||||
new HTMLWebpackPlugin({
|
||||
title: 'ToReplaceByTitle',
|
||||
__UI_OPTIONS: 'ToReplaceByVerdaccioUI',
|
||||
scope: 'ToReplaceByScope',
|
||||
basename: 'ToReplaceByPrefix',
|
||||
logo: 'ToReplaceByLogo',
|
||||
primary_color: 'ToReplaceByPrimaryColor',
|
||||
filename: 'index.html',
|
||||
favicon: `${env.SRC_ROOT}/webui/template/favicon.ico`,
|
||||
verdaccioURL: 'ToReplaceByVerdaccio',
|
||||
version_app: 'ToReplaceByVersion',
|
||||
template: `${env.SRC_ROOT}/webui/template/index.html`,
|
||||
debug: false,
|
||||
inject: true,
|
||||
|
||||
Reference in New Issue
Block a user