Compare commits
34 Commits
@verdaccio
...
@verdaccio
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4fc14eab02 | ||
|
|
a2b69a08e2 | ||
|
|
6eea70a6dd | ||
|
|
e533f1d500 | ||
|
|
45cc559f47 | ||
|
|
ce81b3e96d | ||
|
|
31d661c7bd | ||
|
|
b69333778d | ||
|
|
4dcc250fdb | ||
|
|
756a47aee0 | ||
|
|
2c45bc6e82 | ||
|
|
31050ee369 | ||
|
|
9652472780 | ||
|
|
87f903d530 | ||
|
|
8d625d25d2 | ||
|
|
a179f1fd43 | ||
|
|
a049eaa38f | ||
|
|
d2dd76260b | ||
|
|
f38c759cb2 | ||
|
|
28c3aad443 | ||
|
|
a020d4f580 | ||
|
|
160c25ddc5 | ||
|
|
1debee3e9d | ||
|
|
76d78b0328 | ||
|
|
61bbede301 | ||
|
|
635ca3f924 | ||
|
|
aeff267d94 | ||
|
|
a0dca6e927 | ||
|
|
71e5fb0221 | ||
|
|
aa0b2aa9df | ||
|
|
498afcd222 | ||
|
|
83561bc52d | ||
|
|
67b4681ce7 | ||
|
|
df53f61c64 |
5
.changeset/brown-pandas-wink.md
Normal file
5
.changeset/brown-pandas-wink.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@verdaccio/ui-theme': patch
|
||||
---
|
||||
|
||||
add banner support ukraine
|
||||
5
.changeset/dull-monkeys-search.md
Normal file
5
.changeset/dull-monkeys-search.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@verdaccio/ui-theme': patch
|
||||
---
|
||||
|
||||
show verdaccio logo in the footer even when custom brand is set
|
||||
5
.changeset/kind-bears-nail.md
Normal file
5
.changeset/kind-bears-nail.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@verdaccio/ui-theme': patch
|
||||
---
|
||||
|
||||
feat: add types and package module icons on sidebar
|
||||
5
.changeset/loud-shoes-jog.md
Normal file
5
.changeset/loud-shoes-jog.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@verdaccio/ui-theme': patch
|
||||
---
|
||||
|
||||
chore: force publish
|
||||
5
.changeset/lovely-drinks-argue.md
Normal file
5
.changeset/lovely-drinks-argue.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@verdaccio/loaders': patch
|
||||
---
|
||||
|
||||
always create plugin instance with new
|
||||
5
.changeset/neat-toys-float.md
Normal file
5
.changeset/neat-toys-float.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@verdaccio/ui-theme': patch
|
||||
---
|
||||
|
||||
fix: replace ts icon by td and fix commonjs icon
|
||||
@@ -50,8 +50,10 @@
|
||||
"afraid-mice-obey",
|
||||
"big-lobsters-sin",
|
||||
"bright-poems-obey",
|
||||
"brown-pandas-wink",
|
||||
"calm-pants-impress",
|
||||
"dry-planes-tap",
|
||||
"dull-monkeys-search",
|
||||
"eleven-brooms-hunt",
|
||||
"eleven-spoons-matter",
|
||||
"fair-lemons-beam",
|
||||
@@ -67,13 +69,17 @@
|
||||
"healthy-poets-compare",
|
||||
"heavy-ravens-lay",
|
||||
"hip-hounds-destroy",
|
||||
"kind-bears-nail",
|
||||
"late-adults-love",
|
||||
"late-parents-act",
|
||||
"light-walls-begin",
|
||||
"little-stingrays-rule",
|
||||
"loud-shoes-jog",
|
||||
"lovely-drinks-argue",
|
||||
"many-vans-care",
|
||||
"modern-spies-tell",
|
||||
"neat-toes-report",
|
||||
"neat-toys-float",
|
||||
"olive-candles-speak",
|
||||
"perfect-candles-clap",
|
||||
"perfect-emus-clean",
|
||||
@@ -93,6 +99,7 @@
|
||||
"sour-buses-shout",
|
||||
"spicy-frogs-press",
|
||||
"spicy-snakes-sip",
|
||||
"swift-pumpkins-knock",
|
||||
"ten-parents-breathe",
|
||||
"tender-bags-call",
|
||||
"thick-countries-move",
|
||||
|
||||
6
.changeset/swift-pumpkins-knock.md
Normal file
6
.changeset/swift-pumpkins-knock.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@verdaccio/auth': patch
|
||||
'verdaccio-htpasswd': patch
|
||||
---
|
||||
|
||||
Refactor htpasswd plugin to use the bcryptjs 'compare' api call instead of 'comparSync'. Add a new configuration value named 'slow_verify_ms' to the htpasswd plugin that when exceeded during password verification will log a warning message.
|
||||
20
.github/workflows/benchmark.yml
vendored
20
.github/workflows/benchmark.yml
vendored
@@ -15,8 +15,8 @@ jobs:
|
||||
name: Prepare build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 14.x
|
||||
- name: install pnpm
|
||||
@@ -57,13 +57,13 @@ jobs:
|
||||
# - local
|
||||
- 3.13.1
|
||||
- 4.12.2
|
||||
- 5.5.2
|
||||
- 6.0.0-6-next.31
|
||||
- 5.7.0
|
||||
- 6.0.0-6-next.35
|
||||
name: Benchmark autocannon
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 14.x
|
||||
- uses: actions/download-artifact@v2
|
||||
@@ -118,13 +118,13 @@ jobs:
|
||||
# old versions to compare same test along previous releases
|
||||
- 3.13.1
|
||||
- 4.12.2
|
||||
- 5.5.2
|
||||
- 6.0.0-6-next.31
|
||||
- 5.7.0
|
||||
- 6.0.0-6-next.35
|
||||
name: Benchmark hyperfine
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 14.x
|
||||
- uses: actions/download-artifact@v2
|
||||
|
||||
4
.github/workflows/changesets.yml
vendored
4
.github/workflows/changesets.yml
vendored
@@ -20,12 +20,12 @@ jobs:
|
||||
if: github.ref == 'refs/heads/master' && github.repository == 'verdaccio/verdaccio'
|
||||
steps:
|
||||
- name: checkout code repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: setup node.js
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 14
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
80
.github/workflows/ci.yml
vendored
80
.github/workflows/ci.yml
vendored
@@ -24,9 +24,9 @@ jobs:
|
||||
ports:
|
||||
- 4873:4873
|
||||
steps:
|
||||
- uses: actions/checkout@v2.4.0
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node 16
|
||||
uses: actions/setup-node@v1
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
- name: Install pnpm
|
||||
@@ -49,9 +49,9 @@ jobs:
|
||||
name: Lint
|
||||
needs: prepare
|
||||
steps:
|
||||
- uses: actions/checkout@v2.4.0
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node 16
|
||||
uses: actions/setup-node@v1
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
- name: Install pnpm
|
||||
@@ -69,9 +69,9 @@ jobs:
|
||||
name: Format
|
||||
needs: prepare
|
||||
steps:
|
||||
- uses: actions/checkout@v2.4.0
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node 16
|
||||
uses: actions/setup-node@v1
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
- name: Install pnpm
|
||||
@@ -95,9 +95,9 @@ jobs:
|
||||
name: ${{ matrix.os }} / Node ${{ matrix.node_version }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2.4.0
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node ${{ matrix.node_version }}
|
||||
uses: actions/setup-node@v1
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node_version }}
|
||||
- name: Install pnpm
|
||||
@@ -117,12 +117,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: UI Test E2E Node 16
|
||||
steps:
|
||||
- uses: actions/checkout@v2.4.0
|
||||
- uses: actions/setup-node@v1
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
- name: Install pnpm
|
||||
run: npm i pnpm@6.24.1 -g
|
||||
run: npm i pnpm@latest -g
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.pnpm-store
|
||||
@@ -136,39 +136,41 @@ jobs:
|
||||
run: pnpm test:e2e:ui
|
||||
# env:
|
||||
# DEBUG: verdaccio:e2e*
|
||||
ci-e2e-cli:
|
||||
needs: [format, lint]
|
||||
runs-on: ubuntu-latest
|
||||
# TODO: fails on migrate to node 16, we need to check why
|
||||
name: CLI Test E2E Node 14
|
||||
steps:
|
||||
- uses: actions/checkout@v2.4.0
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 14
|
||||
- name: Install pnpm
|
||||
run: npm i pnpm@6.24.1 -g
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.pnpm-store
|
||||
key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}
|
||||
- name: Install
|
||||
## we need scripts, pupetter downloads aditional content
|
||||
run: pnpm recursive install --frozen-lockfile
|
||||
- name: build
|
||||
run: pnpm build
|
||||
- name: Test CLI
|
||||
run: pnpm test:e2e:cli
|
||||
env:
|
||||
DEBUG: verdaccio*
|
||||
# FIXME verify why fails on Node 16 (locally works fine)
|
||||
# ci-e2e-cli:
|
||||
# needs: [format, lint]
|
||||
# runs-on: ubuntu-latest
|
||||
# # TODO: fails on migrate to node 16, we need to check why
|
||||
# name: CLI Test E2E Node 16
|
||||
# steps:
|
||||
# - uses: actions/checkout@v3
|
||||
# - uses: actions/setup-node@v3
|
||||
# with:
|
||||
# node-version: 16
|
||||
# - name: Install pnpm
|
||||
# run: npm i pnpm@latest -g
|
||||
# - uses: actions/cache@v2
|
||||
# with:
|
||||
# path: ~/.pnpm-store
|
||||
# key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}
|
||||
# - name: Install
|
||||
# ## we need scripts, pupetter downloads aditional content
|
||||
# run: pnpm recursive install --frozen-lockfile
|
||||
# - name: build
|
||||
# run: pnpm build
|
||||
# - name: Test CLI
|
||||
# run: pnpm test:e2e:cli
|
||||
# env:
|
||||
# DEBUG: verdaccio*
|
||||
sync-translations:
|
||||
needs: [ci-e2e-cli, ci-e2e-ui]
|
||||
# needs: [ci-e2e-cli, ci-e2e-ui]
|
||||
needs: [ci-e2e-ui]
|
||||
runs-on: ubuntu-latest
|
||||
name: synchronize translations
|
||||
if: (github.event_name == 'push' && github.ref == 'refs/heads/master') || github.event_name == 'workflow_dispatch'
|
||||
steps:
|
||||
- uses: actions/checkout@v2.4.0
|
||||
- uses: actions/setup-node@v1
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
- name: Install pnpm
|
||||
|
||||
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2.4.0
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
|
||||
4
.github/workflows/contributors.yml
vendored
4
.github/workflows/contributors.yml
vendored
@@ -15,11 +15,11 @@ jobs:
|
||||
name: Run script
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 17.x
|
||||
- name: install pnpm
|
||||
|
||||
2
.github/workflows/docker-publish.yml
vendored
2
.github/workflows/docker-publish.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: docker/setup-qemu-action@v1
|
||||
- uses: docker/setup-buildx-action@v1
|
||||
with:
|
||||
|
||||
10
.github/workflows/website.yml
vendored
10
.github/workflows/website.yml
vendored
@@ -24,10 +24,10 @@ jobs:
|
||||
env:
|
||||
NODE_OPTIONS: --max_old_space_size=4096
|
||||
steps:
|
||||
- uses: actions/checkout@v2.4.0
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Use Node 14
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 14
|
||||
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-${{ matrix.node-version }}-
|
||||
|
||||
- uses: pnpm/action-setup@v2.1.0
|
||||
- uses: pnpm/action-setup@v2.2.1
|
||||
with:
|
||||
version: 6.10.2
|
||||
run_install: |
|
||||
@@ -97,7 +97,7 @@ jobs:
|
||||
|
||||
- name: Audit preview URL with Lighthouse
|
||||
id: lighthouse_audit
|
||||
uses: treosh/lighthouse-ci-action@v3
|
||||
uses: treosh/lighthouse-ci-action@9.3.0
|
||||
with:
|
||||
urls: |
|
||||
${{ steps.netlify_preview.outputs.preview-url }}
|
||||
@@ -106,7 +106,7 @@ jobs:
|
||||
|
||||
- name: Format lighthouse score
|
||||
id: format_lighthouse_score
|
||||
uses: actions/github-script@v3
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||
script: |
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
[](https://donate.redcrossredcrescent.org/ua/donate/~my-donation?_cv=1)
|
||||
|
||||
> Verdaccio stands for **peace**, stop the war, we will be yellow / blue 🇺🇦 until that happens.
|
||||
|
||||

|
||||
|
||||

|
||||
@@ -26,6 +30,7 @@ Google Cloud Storage** or create your own plugin.
|
||||
|
||||
[](https://twitter.com/verdaccio_npm)
|
||||
[](https://github.com/verdaccio/verdaccio/stargazers)
|
||||
[](https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md)
|
||||
|
||||
## Install
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
"docker": "docker build -t verdaccio/verdaccio:local . --no-cache",
|
||||
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,yml,yaml,md}\"",
|
||||
"format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,json,yml,yaml,md}\"",
|
||||
"lint": "eslint --max-warnings 44 \"**/*.{js,jsx,ts,tsx}\"",
|
||||
"lint": "eslint --max-warnings 42 \"**/*.{js,jsx,ts,tsx}\"",
|
||||
"test": "pnpm recursive test --filter ./packages",
|
||||
"test:e2e:cli": "pnpm test --filter ...@verdaccio/e2e-cli",
|
||||
"test:e2e:ui": "pnpm test --filter ...@verdaccio/e2e-ui",
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
# @verdaccio/api
|
||||
|
||||
## 6.0.0-6-next.23
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @verdaccio/auth@6.0.0-6-next.20
|
||||
- @verdaccio/store@6.0.0-6-next.20
|
||||
- @verdaccio/hooks@6.0.0-6-next.12
|
||||
- @verdaccio/middleware@6.0.0-6-next.20
|
||||
|
||||
## 6.0.0-6-next.22
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [aeff267d]
|
||||
- @verdaccio/auth@6.0.0-6-next.19
|
||||
- @verdaccio/hooks@6.0.0-6-next.12
|
||||
- @verdaccio/middleware@6.0.0-6-next.19
|
||||
|
||||
## 6.0.0-6-next.21
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@verdaccio/api",
|
||||
"version": "6.0.0-6-next.21",
|
||||
"version": "6.0.0-6-next.23",
|
||||
"description": "loaders logic",
|
||||
"main": "./build/index.js",
|
||||
"types": "build/index.d.ts",
|
||||
@@ -39,13 +39,13 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@verdaccio/auth": "workspace:6.0.0-6-next.18",
|
||||
"@verdaccio/auth": "workspace:6.0.0-6-next.20",
|
||||
"@verdaccio/config": "workspace:6.0.0-6-next.12",
|
||||
"@verdaccio/core": "workspace:6.0.0-6-next.4",
|
||||
"@verdaccio/hooks": "workspace:6.0.0-6-next.12",
|
||||
"@verdaccio/logger": "workspace:6.0.0-6-next.10",
|
||||
"@verdaccio/middleware": "workspace:6.0.0-6-next.18",
|
||||
"@verdaccio/store": "workspace:6.0.0-6-next.19",
|
||||
"@verdaccio/middleware": "workspace:6.0.0-6-next.20",
|
||||
"@verdaccio/store": "workspace:6.0.0-6-next.20",
|
||||
"@verdaccio/utils": "workspace:6.0.0-6-next.10",
|
||||
"abortcontroller-polyfill": "1.7.3",
|
||||
"cookies": "0.8.0",
|
||||
@@ -58,7 +58,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "16.11.21",
|
||||
"@verdaccio/server": "workspace:6.0.0-6-next.26",
|
||||
"@verdaccio/server": "workspace:6.0.0-6-next.28",
|
||||
"@verdaccio/types": "workspace:11.0.0-6-next.10",
|
||||
"@verdaccio/helper": "1.0.0",
|
||||
"supertest": "6.2.2"
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# @verdaccio/auth
|
||||
|
||||
## 6.0.0-6-next.20
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [31d661c7]
|
||||
- @verdaccio/loaders@6.0.0-6-next.11
|
||||
|
||||
## 6.0.0-6-next.19
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- aeff267d: Refactor htpasswd plugin to use the bcryptjs 'compare' api call instead of 'comparSync'. Add a new configuration value named 'slow_verify_ms' to the htpasswd plugin that when exceeded during password verification will log a warning message.
|
||||
- Updated dependencies [aeff267d]
|
||||
- verdaccio-htpasswd@11.0.0-6-next.12
|
||||
|
||||
## 6.0.0-6-next.18
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@verdaccio/auth",
|
||||
"version": "6.0.0-6-next.18",
|
||||
"version": "6.0.0-6-next.20",
|
||||
"description": "logger",
|
||||
"main": "./build/index.js",
|
||||
"types": "build/index.d.ts",
|
||||
@@ -41,14 +41,14 @@
|
||||
"dependencies": {
|
||||
"@verdaccio/core": "workspace:6.0.0-6-next.4",
|
||||
"@verdaccio/config": "workspace:6.0.0-6-next.12",
|
||||
"@verdaccio/loaders": "workspace:6.0.0-6-next.10",
|
||||
"@verdaccio/loaders": "workspace:6.0.0-6-next.11",
|
||||
"@verdaccio/logger": "workspace:6.0.0-6-next.10",
|
||||
"@verdaccio/utils": "workspace:6.0.0-6-next.10",
|
||||
"debug": "4.3.3",
|
||||
"express": "4.17.2",
|
||||
"jsonwebtoken": "8.5.1",
|
||||
"lodash": "4.17.21",
|
||||
"verdaccio-htpasswd": "workspace:11.0.0-6-next.11"
|
||||
"verdaccio-htpasswd": "workspace:11.0.0-6-next.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@verdaccio/mock": "workspace:6.0.0-6-next.13",
|
||||
|
||||
@@ -111,7 +111,7 @@ class Auth implements IAuth {
|
||||
};
|
||||
let authPlugin;
|
||||
try {
|
||||
authPlugin = new HTPasswd(plugingConf, pluginOptions);
|
||||
authPlugin = new HTPasswd(plugingConf, pluginOptions as any as PluginOptions<HTPasswdConfig>);
|
||||
} catch (error: any) {
|
||||
debug('error on loading auth htpasswd plugin stack: %o', error);
|
||||
return [];
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# @verdaccio/cli
|
||||
|
||||
## 6.0.0-6-next.30
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @verdaccio/fastify-migration@6.0.0-6-next.21
|
||||
- @verdaccio/node-api@6.0.0-6-next.29
|
||||
|
||||
## 6.0.0-6-next.29
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @verdaccio/fastify-migration@6.0.0-6-next.20
|
||||
- @verdaccio/node-api@6.0.0-6-next.28
|
||||
|
||||
## 6.0.0-6-next.28
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@verdaccio/cli",
|
||||
"version": "6.0.0-6-next.28",
|
||||
"version": "6.0.0-6-next.30",
|
||||
"author": {
|
||||
"name": "Juan Picado",
|
||||
"email": "juanpicado19@gmail.com"
|
||||
@@ -47,8 +47,8 @@
|
||||
"@verdaccio/core": "workspace:6.0.0-6-next.4",
|
||||
"@verdaccio/config": "workspace:6.0.0-6-next.12",
|
||||
"@verdaccio/logger": "workspace:6.0.0-6-next.10",
|
||||
"@verdaccio/node-api": "workspace:6.0.0-6-next.27",
|
||||
"@verdaccio/fastify-migration": "workspace:6.0.0-6-next.19",
|
||||
"@verdaccio/node-api": "workspace:6.0.0-6-next.29",
|
||||
"@verdaccio/fastify-migration": "workspace:6.0.0-6-next.21",
|
||||
"clipanion": "3.1.0",
|
||||
"envinfo": "7.8.1",
|
||||
"kleur": "3.0.3",
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# @verdaccio/fastify-migration
|
||||
|
||||
## 6.0.0-6-next.21
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @verdaccio/auth@6.0.0-6-next.20
|
||||
- @verdaccio/store@6.0.0-6-next.20
|
||||
|
||||
## 6.0.0-6-next.20
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [aeff267d]
|
||||
- @verdaccio/auth@6.0.0-6-next.19
|
||||
|
||||
## 6.0.0-6-next.19
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@verdaccio/fastify-migration",
|
||||
"version": "6.0.0-6-next.19",
|
||||
"version": "6.0.0-6-next.21",
|
||||
"description": "Fastify server migration package",
|
||||
"keywords": [
|
||||
"private",
|
||||
@@ -36,9 +36,9 @@
|
||||
"dependencies": {
|
||||
"@verdaccio/core": "workspace:6.0.0-6-next.4",
|
||||
"@verdaccio/config": "workspace:6.0.0-6-next.12",
|
||||
"@verdaccio/auth": "workspace:6.0.0-6-next.18",
|
||||
"@verdaccio/auth": "workspace:6.0.0-6-next.20",
|
||||
"@verdaccio/logger": "workspace:6.0.0-6-next.10",
|
||||
"@verdaccio/store": "workspace:6.0.0-6-next.19",
|
||||
"@verdaccio/store": "workspace:6.0.0-6-next.20",
|
||||
"@verdaccio/tarball": "workspace:11.0.0-6-next.11",
|
||||
"@verdaccio/utils": "workspace:6.0.0-6-next.10",
|
||||
"@verdaccio/readme": "workspace:11.0.0-6-next.4",
|
||||
|
||||
@@ -35,12 +35,11 @@
|
||||
"core-js": "3.20.3",
|
||||
"debug": "4.3.3",
|
||||
"handlebars": "4.7.7",
|
||||
"undici": "4.12.2",
|
||||
"undici-fetch": "1.0.0-rc.4"
|
||||
"undici": "4.15.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "16.11.21",
|
||||
"@verdaccio/auth": "workspace:6.0.0-6-next.18",
|
||||
"@verdaccio/auth": "workspace:6.0.0-6-next.20",
|
||||
"@verdaccio/config": "workspace:6.0.0-6-next.12",
|
||||
"@verdaccio/types": "workspace:11.0.0-6-next.10"
|
||||
},
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import buildDebug from 'debug';
|
||||
import { fetch } from 'undici';
|
||||
|
||||
import { HTTP_STATUS } from '@verdaccio/core';
|
||||
import { logger } from '@verdaccio/logger';
|
||||
|
||||
const debug = buildDebug('verdaccio:hooks:request');
|
||||
const fetch = require('undici-fetch');
|
||||
|
||||
export type FetchOptions = {
|
||||
body: string;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { MockAgent, setGlobalDispatcher } from 'undici';
|
||||
|
||||
import { createRemoteUser, parseConfigFile } from '@verdaccio/config';
|
||||
import { setup } from '@verdaccio/logger';
|
||||
import { Config } from '@verdaccio/types';
|
||||
@@ -16,8 +18,6 @@ const multiNotificationConfig = parseConfigFile(parseConfigurationNotifyFile('mu
|
||||
setup([]);
|
||||
|
||||
const domain = 'http://slack-service';
|
||||
const { MockAgent } = require('undici');
|
||||
const { setGlobalDispatcher } = require('undici-fetch');
|
||||
|
||||
const options = {
|
||||
path: '/foo?auth_token=mySecretToken',
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @verdaccio/loaders
|
||||
|
||||
## 6.0.0-6-next.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 31d661c7: always create plugin instance with new
|
||||
|
||||
## 6.0.0-6-next.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@verdaccio/loaders",
|
||||
"version": "6.0.0-6-next.10",
|
||||
"version": "6.0.0-6-next.11",
|
||||
"description": "loaders logic",
|
||||
"main": "./build/index.js",
|
||||
"types": "build/index.d.ts",
|
||||
|
||||
@@ -121,7 +121,7 @@ export function loadPlugin<T extends IPlugin<T>>(
|
||||
try {
|
||||
plugin = isES6(plugin)
|
||||
? new plugin.default(mergeConfig(config, pluginConfigs[pluginId]), params)
|
||||
: plugin(pluginConfigs[pluginId], params);
|
||||
: new plugin(pluginConfigs[pluginId], params);
|
||||
} catch (error: any) {
|
||||
plugin = null;
|
||||
logger.error({ error, pluginId }, 'error loading a plugin @{pluginId}: @{error}');
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
# @verdaccio/middleware
|
||||
|
||||
## 6.0.0-6-next.20
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @verdaccio/auth@6.0.0-6-next.20
|
||||
|
||||
## 6.0.0-6-next.19
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [aeff267d]
|
||||
- @verdaccio/auth@6.0.0-6-next.19
|
||||
|
||||
## 6.0.0-6-next.18
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@verdaccio/middleware",
|
||||
"version": "6.0.0-6-next.18",
|
||||
"version": "6.0.0-6-next.20",
|
||||
"description": "loaders logic",
|
||||
"main": "./build/index.js",
|
||||
"types": "build/index.d.ts",
|
||||
@@ -40,7 +40,7 @@
|
||||
"dependencies": {
|
||||
"debug": "4.3.3",
|
||||
"body-parser": "1.19.1",
|
||||
"@verdaccio/auth": "workspace:6.0.0-6-next.18",
|
||||
"@verdaccio/auth": "workspace:6.0.0-6-next.20",
|
||||
"@verdaccio/core": "workspace:6.0.0-6-next.4",
|
||||
"@verdaccio/logger": "workspace:6.0.0-6-next.10",
|
||||
"@verdaccio/utils": "workspace:6.0.0-6-next.10",
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# @verdaccio/node-api
|
||||
|
||||
## 6.0.0-6-next.29
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @verdaccio/server@6.0.0-6-next.28
|
||||
|
||||
## 6.0.0-6-next.28
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @verdaccio/server@6.0.0-6-next.27
|
||||
|
||||
## 6.0.0-6-next.27
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@verdaccio/node-api",
|
||||
"version": "6.0.0-6-next.27",
|
||||
"version": "6.0.0-6-next.29",
|
||||
"description": "node API",
|
||||
"main": "build/index.js",
|
||||
"types": "build/index.d.ts",
|
||||
@@ -42,7 +42,7 @@
|
||||
"@verdaccio/core": "workspace:6.0.0-6-next.4",
|
||||
"@verdaccio/config": "workspace:6.0.0-6-next.12",
|
||||
"@verdaccio/logger": "workspace:6.0.0-6-next.10",
|
||||
"@verdaccio/server": "workspace:6.0.0-6-next.26",
|
||||
"@verdaccio/server": "workspace:6.0.0-6-next.28",
|
||||
"core-js": "3.20.3",
|
||||
"debug": "4.3.3",
|
||||
"lodash": "4.17.21"
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# Change Log
|
||||
|
||||
## 11.0.0-6-next.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- aeff267d: Refactor htpasswd plugin to use the bcryptjs 'compare' api call instead of 'comparSync'. Add a new configuration value named 'slow_verify_ms' to the htpasswd plugin that when exceeded during password verification will log a warning message.
|
||||
|
||||
## 11.0.0-6-next.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -30,7 +30,26 @@ As simple as running:
|
||||
# Hash algorithm, possible options are: "bcrypt", "md5", "sha1", "crypt".
|
||||
#algorithm: bcrypt
|
||||
# Rounds number for "bcrypt", will be ignored for other algorithms.
|
||||
# Setting this value higher will result in password verification taking longer.
|
||||
#rounds: 10
|
||||
# Log a warning if the password takes more then this duration in milliseconds to verify.
|
||||
#slow_verify_ms: 200
|
||||
|
||||
### Bcrypt rounds
|
||||
|
||||
It is important to note that when using the default `bcrypt` algorithm and setting
|
||||
the `rounds` configuration value to a higher number then the default of `10`, that
|
||||
verification of a user password can cause significantly increased CPU usage and
|
||||
additional latency in processing requests.
|
||||
|
||||
If your Verdaccio instance handles a large number of authenticated requests using
|
||||
username and password for authentication, the `rounds` configuration value may need
|
||||
to be decreased to prevent excessive CPU usage and request latency.
|
||||
|
||||
Also note that setting the `rounds` configuration value to a value that is too small
|
||||
increases the risk of successful brute force attack. Auth0 has a
|
||||
[blog article](https://auth0.com/blog/hashing-in-action-understanding-bcrypt)
|
||||
that provides an overview of how `bcrypt` hashing works and some best practices.
|
||||
|
||||
## Logging In
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "verdaccio-htpasswd",
|
||||
"version": "11.0.0-6-next.11",
|
||||
"version": "11.0.0-6-next.12",
|
||||
"description": "htpasswd auth plugin for Verdaccio",
|
||||
"keywords": [
|
||||
"private",
|
||||
|
||||
@@ -19,9 +19,12 @@ export type HTPasswdConfig = {
|
||||
file: string;
|
||||
algorithm?: HtpasswdHashAlgorithm;
|
||||
rounds?: number;
|
||||
max_users?: number;
|
||||
slow_verify_ms?: number;
|
||||
} & Config;
|
||||
|
||||
export const DEFAULT_BCRYPT_ROUNDS = 10;
|
||||
export const DEFAULT_SLOW_VERIFY_MS = 200;
|
||||
|
||||
/**
|
||||
* HTPasswd - Verdaccio auth class
|
||||
@@ -30,30 +33,21 @@ export default class HTPasswd implements IPluginAuth<HTPasswdConfig> {
|
||||
/**
|
||||
*
|
||||
* @param {*} config htpasswd file
|
||||
* @param {object} stuff config.yaml in object from
|
||||
* @param {object} options config.yaml in object from
|
||||
*/
|
||||
private users: {};
|
||||
private stuff: {};
|
||||
private config: {};
|
||||
private verdaccioConfig: Config;
|
||||
private maxUsers: number;
|
||||
private hashConfig: HtpasswdHashConfig;
|
||||
private path: string;
|
||||
private slowVerifyMs: number;
|
||||
private logger: Logger;
|
||||
private lastTime: any;
|
||||
// constructor
|
||||
public constructor(config: HTPasswdConfig, stuff: PluginOptions<{}>) {
|
||||
public constructor(config: HTPasswdConfig, options: PluginOptions<HTPasswdConfig>) {
|
||||
this.users = {};
|
||||
|
||||
// config for this module
|
||||
this.config = config;
|
||||
this.stuff = stuff;
|
||||
|
||||
// verdaccio logger
|
||||
this.logger = stuff.logger;
|
||||
|
||||
// verdaccio main config object
|
||||
this.verdaccioConfig = stuff.config;
|
||||
this.logger = options.logger;
|
||||
|
||||
// all this "verdaccio_config" stuff is for b/w compatibility only
|
||||
this.maxUsers = config.max_users ? config.max_users : Infinity;
|
||||
@@ -88,25 +82,41 @@ export default class HTPasswd implements IPluginAuth<HTPasswdConfig> {
|
||||
throw new Error('should specify "file" in config');
|
||||
}
|
||||
|
||||
this.path = Path.resolve(Path.dirname(this.verdaccioConfig.config_path), file);
|
||||
this.path = Path.resolve(Path.dirname(options.config.config_path), file);
|
||||
this.slowVerifyMs = config.slow_verify_ms || DEFAULT_SLOW_VERIFY_MS;
|
||||
}
|
||||
|
||||
/**
|
||||
* authenticate - Authenticate user.
|
||||
* @param {string} user
|
||||
* @param {string} password
|
||||
* @param {function} cd
|
||||
* @returns {function}
|
||||
* @param {function} cb
|
||||
* @returns {void}
|
||||
*/
|
||||
public authenticate(user: string, password: string, cb: Callback): void {
|
||||
this.reload((err) => {
|
||||
this.reload(async (err) => {
|
||||
if (err) {
|
||||
return cb(err.code === 'ENOENT' ? null : err);
|
||||
}
|
||||
if (!this.users[user]) {
|
||||
return cb(null, false);
|
||||
}
|
||||
if (!verifyPassword(password, this.users[user])) {
|
||||
|
||||
let passwordValid = false;
|
||||
try {
|
||||
const start = new Date();
|
||||
passwordValid = await verifyPassword(password, this.users[user]);
|
||||
const durationMs = new Date().getTime() - start.getTime();
|
||||
if (durationMs > this.slowVerifyMs) {
|
||||
this.logger.warn(
|
||||
{ user, durationMs },
|
||||
'Password for user "@{user}" took @{durationMs}ms to verify'
|
||||
);
|
||||
}
|
||||
} catch ({ message }) {
|
||||
this.logger.error({ message }, 'Unable to verify user password: @{message}');
|
||||
}
|
||||
if (!passwordValid) {
|
||||
return cb(null, false);
|
||||
}
|
||||
|
||||
@@ -130,11 +140,11 @@ export default class HTPasswd implements IPluginAuth<HTPasswdConfig> {
|
||||
* @param {string} user
|
||||
* @param {string} password
|
||||
* @param {function} realCb
|
||||
* @returns {function}
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
public adduser(user: string, password: string, realCb: Callback): any {
|
||||
public async adduser(user: string, password: string, realCb: Callback): Promise<any> {
|
||||
const pathPass = this.path;
|
||||
let sanity = sanityCheck(user, password, verifyPassword, this.users, this.maxUsers);
|
||||
let sanity = await sanityCheck(user, password, verifyPassword, this.users, this.maxUsers);
|
||||
|
||||
// preliminary checks, just to ensure that file won't be reloaded if it's
|
||||
// not needed
|
||||
@@ -142,7 +152,7 @@ export default class HTPasswd implements IPluginAuth<HTPasswdConfig> {
|
||||
return realCb(sanity, false);
|
||||
}
|
||||
|
||||
lockAndRead(pathPass, (err, res): void => {
|
||||
lockAndRead(pathPass, async (err, res): Promise<void> => {
|
||||
let locked = false;
|
||||
|
||||
// callback that cleans up lock first
|
||||
@@ -170,7 +180,7 @@ export default class HTPasswd implements IPluginAuth<HTPasswdConfig> {
|
||||
|
||||
// real checks, to prevent race conditions
|
||||
// parsing users after reading file.
|
||||
sanity = sanityCheck(user, password, verifyPassword, this.users, this.maxUsers);
|
||||
sanity = await sanityCheck(user, password, verifyPassword, this.users, this.maxUsers);
|
||||
|
||||
if (sanity) {
|
||||
return cb(sanity);
|
||||
@@ -230,7 +240,8 @@ export default class HTPasswd implements IPluginAuth<HTPasswdConfig> {
|
||||
* changePassword - change password for existing user.
|
||||
* @param {string} user
|
||||
* @param {string} password
|
||||
* @param {function} cd
|
||||
* @param {string} newPassword
|
||||
* @param {function} realCb
|
||||
* @returns {function}
|
||||
*/
|
||||
public changePassword(
|
||||
@@ -239,7 +250,7 @@ export default class HTPasswd implements IPluginAuth<HTPasswdConfig> {
|
||||
newPassword: string,
|
||||
realCb: Callback
|
||||
): void {
|
||||
lockAndRead(this.path, (err, res) => {
|
||||
lockAndRead(this.path, async (err, res) => {
|
||||
let locked = false;
|
||||
const pathPassFile = this.path;
|
||||
|
||||
@@ -266,13 +277,9 @@ export default class HTPasswd implements IPluginAuth<HTPasswdConfig> {
|
||||
const body = this._stringToUt8(res);
|
||||
this.users = parseHTPasswd(body);
|
||||
|
||||
if (!this.users[user]) {
|
||||
return cb(new Error('User not found'));
|
||||
}
|
||||
|
||||
try {
|
||||
this._writeFile(
|
||||
changePasswordToHTPasswd(body, user, password, newPassword, this.hashConfig),
|
||||
await changePasswordToHTPasswd(body, user, password, newPassword, this.hashConfig),
|
||||
cb
|
||||
);
|
||||
} catch (err: any) {
|
||||
|
||||
@@ -39,8 +39,9 @@ export function lockAndRead(name: string, cb: Callback): void {
|
||||
* @returns {object}
|
||||
*/
|
||||
export function parseHTPasswd(input: string): Record<string, any> {
|
||||
return input.split('\n').reduce((result, line) => {
|
||||
const args = line.split(':', 3);
|
||||
// The input is split on line ending styles that are both windows and unix compatible
|
||||
return input.split(/[\r]?[\n]/).reduce((result, line) => {
|
||||
const args = line.split(':', 3).map((str) => str.trim());
|
||||
if (args.length > 1) {
|
||||
result[args[0]] = args[1];
|
||||
}
|
||||
@@ -52,11 +53,13 @@ export function parseHTPasswd(input: string): Record<string, any> {
|
||||
* verifyPassword - matches password and it's hash.
|
||||
* @param {string} passwd
|
||||
* @param {string} hash
|
||||
* @returns {boolean}
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
export function verifyPassword(passwd: string, hash: string): boolean {
|
||||
if (hash.match(/^\$2(a|b|y)\$/)) {
|
||||
return bcrypt.compareSync(passwd, hash);
|
||||
export async function verifyPassword(passwd: string, hash: string): Promise<boolean> {
|
||||
if (hash.match(/^\$2([aby])\$/)) {
|
||||
return new Promise((resolve, reject) =>
|
||||
bcrypt.compare(passwd, hash, (error, result) => (error ? reject(error) : resolve(result)))
|
||||
);
|
||||
} else if (hash.indexOf('{PLAIN}') === 0) {
|
||||
return passwd === hash.substr(7);
|
||||
} else if (hash.indexOf('{SHA}') === 0) {
|
||||
@@ -112,6 +115,7 @@ export function generateHtpasswdLine(
|
||||
* @param {string} body
|
||||
* @param {string} user
|
||||
* @param {string} passwd
|
||||
* @param {HtpasswdHashConfig} hashConfig
|
||||
* @returns {string}
|
||||
*/
|
||||
export function addUserToHTPasswd(
|
||||
@@ -139,16 +143,18 @@ export function addUserToHTPasswd(
|
||||
* Sanity check for a user
|
||||
* @param {string} user
|
||||
* @param {object} users
|
||||
* @param {string} password
|
||||
* @param {Callback} verifyFn
|
||||
* @param {number} maxUsers
|
||||
* @returns {object}
|
||||
*/
|
||||
export function sanityCheck(
|
||||
export async function sanityCheck(
|
||||
user: string,
|
||||
password: string,
|
||||
verifyFn: Callback,
|
||||
users: {},
|
||||
maxUsers: number
|
||||
): HttpError | null {
|
||||
): Promise<HttpError | null> {
|
||||
let err;
|
||||
|
||||
// check for user or password
|
||||
@@ -167,7 +173,7 @@ export function sanityCheck(
|
||||
}
|
||||
|
||||
if (hash) {
|
||||
const auth = verifyFn(password, users[user]);
|
||||
const auth = await verifyFn(password, users[user]);
|
||||
if (auth) {
|
||||
err = Error(API_ERROR.USERNAME_ALREADY_REGISTERED);
|
||||
err.status = HTTP_STATUS.CONFLICT;
|
||||
@@ -191,28 +197,27 @@ export function sanityCheck(
|
||||
* @param {string} user
|
||||
* @param {string} passwd
|
||||
* @param {string} newPasswd
|
||||
* @param {HtpasswdHashConfig} hashConfig
|
||||
* @returns {string}
|
||||
*/
|
||||
export function changePasswordToHTPasswd(
|
||||
export async function changePasswordToHTPasswd(
|
||||
body: string,
|
||||
user: string,
|
||||
passwd: string,
|
||||
newPasswd: string,
|
||||
hashConfig: HtpasswdHashConfig
|
||||
): string {
|
||||
): Promise<string> {
|
||||
let lines = body.split('\n');
|
||||
lines = lines.map((line) => {
|
||||
const [username, hash] = line.split(':', 3);
|
||||
|
||||
if (username === user) {
|
||||
if (verifyPassword(passwd, hash)) {
|
||||
line = generateHtpasswdLine(user, newPasswd, hashConfig);
|
||||
} else {
|
||||
throw new Error('Invalid old Password');
|
||||
}
|
||||
}
|
||||
return line;
|
||||
});
|
||||
|
||||
const userLineIndex = lines.findIndex((line) => line.split(':', 1).shift() === user);
|
||||
if (userLineIndex === -1) {
|
||||
throw new Error(`Unable to change password for user '${user}': user does not currently exist`);
|
||||
}
|
||||
const [username, hash] = lines[userLineIndex].split(':', 2);
|
||||
const passwordValid = await verifyPassword(passwd, hash);
|
||||
if (!passwordValid) {
|
||||
throw new Error(`Unable to change password for user '${user}': invalid old password`);
|
||||
}
|
||||
const updatedUserLine = generateHtpasswdLine(username, newPasswd, hashConfig);
|
||||
lines.splice(userLineIndex, 1, updatedUserLine);
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
test:$6FrCaT/v0dwE:autocreated 2018-01-17T03:40:22.958Z
|
||||
username:$66to3JK5RgZM:autocreated 2018-01-17T03:40:46.315Z
|
||||
bcrypt:$2y$04$K2Cn3StiXx4CnLmcTW/ymekOrj7WlycZZF9xgmoJ/U0zGPqSLPVBe
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export default class Logger {}
|
||||
@@ -1,36 +1,35 @@
|
||||
/* eslint-disable jest/no-mocks-import */
|
||||
// @ts-ignore: Module has no default export
|
||||
import bcrypt from 'bcryptjs';
|
||||
// @ts-ignore: Module has no default export
|
||||
import crypto from 'crypto';
|
||||
// @ts-ignore
|
||||
// @ts-ignore: Module has no default export
|
||||
import fs from 'fs';
|
||||
import MockDate from 'mockdate';
|
||||
|
||||
import HTPasswd, { VerdaccioConfigApp } from '../src/htpasswd';
|
||||
import { PluginOptions } from '@verdaccio/types';
|
||||
|
||||
import HTPasswd, { DEFAULT_SLOW_VERIFY_MS, HTPasswdConfig } from '../src/htpasswd';
|
||||
import { HtpasswdHashAlgorithm } from '../src/utils';
|
||||
import Config from './__mocks__/Config';
|
||||
// FIXME: remove this mocks imports
|
||||
import Logger from './__mocks__/Logger';
|
||||
|
||||
const stuff = {
|
||||
logger: new Logger(),
|
||||
const options = {
|
||||
logger: { warn: jest.fn() },
|
||||
config: new Config(),
|
||||
};
|
||||
} as any as PluginOptions<HTPasswdConfig>;
|
||||
|
||||
const config = {
|
||||
file: './htpasswd',
|
||||
max_users: 1000,
|
||||
};
|
||||
|
||||
const getDefaultConfig = (): VerdaccioConfigApp => ({
|
||||
file: './htpasswd',
|
||||
max_users: 1000,
|
||||
});
|
||||
} as HTPasswdConfig;
|
||||
|
||||
describe('HTPasswd', () => {
|
||||
let wrapper;
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = new HTPasswd(getDefaultConfig(), stuff as unknown as VerdaccioConfigApp);
|
||||
wrapper = new HTPasswd(config, options);
|
||||
jest.resetModules();
|
||||
jest.clearAllMocks();
|
||||
|
||||
crypto.randomBytes = jest.fn(() => {
|
||||
return {
|
||||
@@ -40,47 +39,72 @@ describe('HTPasswd', () => {
|
||||
});
|
||||
|
||||
describe('constructor()', () => {
|
||||
const emptyPluginOptions = { config: {} } as VerdaccioConfigApp;
|
||||
const emptyPluginOptions = { config: {} } as any as PluginOptions<HTPasswdConfig>;
|
||||
|
||||
test('should files whether file path does not exist', () => {
|
||||
test('should ensure file path configuration exists', () => {
|
||||
expect(function () {
|
||||
new HTPasswd({}, emptyPluginOptions);
|
||||
new HTPasswd({} as HTPasswdConfig, emptyPluginOptions);
|
||||
}).toThrow(/should specify "file" in config/);
|
||||
});
|
||||
|
||||
test('should throw error about incorrect algorithm', () => {
|
||||
expect(function () {
|
||||
let config = getDefaultConfig();
|
||||
config.algorithm = 'invalid' as any;
|
||||
new HTPasswd(config, emptyPluginOptions);
|
||||
let invalidConfig = { algorithm: 'invalid', ...config } as HTPasswdConfig;
|
||||
new HTPasswd(invalidConfig, emptyPluginOptions);
|
||||
}).toThrow(/Invalid algorithm "invalid"/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('authenticate()', () => {
|
||||
test('it should authenticate user with given credentials', (done) => {
|
||||
const callbackTest = (a, b): void => {
|
||||
expect(a).toBeNull();
|
||||
expect(b).toContain('test');
|
||||
done();
|
||||
const users = [
|
||||
{ username: 'test', password: 'test' },
|
||||
{ username: 'username', password: 'password' },
|
||||
{ username: 'bcrypt', password: 'password' },
|
||||
];
|
||||
let usersAuthenticated = 0;
|
||||
const generateCallback = (username) => (error, userGroups) => {
|
||||
usersAuthenticated += 1;
|
||||
expect(error).toBeNull();
|
||||
expect(userGroups).toContain(username);
|
||||
usersAuthenticated === users.length && done();
|
||||
};
|
||||
const callbackUsername = (a, b): void => {
|
||||
expect(a).toBeNull();
|
||||
expect(b).toContain('username');
|
||||
done();
|
||||
};
|
||||
wrapper.authenticate('test', 'test', callbackTest);
|
||||
wrapper.authenticate('username', 'password', callbackUsername);
|
||||
users.forEach(({ username, password }) =>
|
||||
wrapper.authenticate(username, password, generateCallback(username))
|
||||
);
|
||||
});
|
||||
|
||||
test('it should not authenticate user with given credentials', (done) => {
|
||||
const users = ['test', 'username', 'bcrypt'];
|
||||
let usersAuthenticated = 0;
|
||||
const generateCallback = () => (error, userGroups) => {
|
||||
usersAuthenticated += 1;
|
||||
expect(error).toBeNull();
|
||||
expect(userGroups).toBeFalsy();
|
||||
usersAuthenticated === users.length && done();
|
||||
};
|
||||
users.forEach((username) =>
|
||||
wrapper.authenticate(username, 'somerandompassword', generateCallback())
|
||||
);
|
||||
});
|
||||
|
||||
test('it should warn on slow password verification', (done) => {
|
||||
bcrypt.compare = jest.fn((passwd, hash, callback) => {
|
||||
setTimeout(() => callback(null, true), DEFAULT_SLOW_VERIFY_MS + 1);
|
||||
});
|
||||
const callback = (a, b): void => {
|
||||
expect(a).toBeNull();
|
||||
expect(b).toBeFalsy();
|
||||
expect(b).toContain('bcrypt');
|
||||
const mockWarn = options.logger.warn as jest.MockedFn<jest.MockableFunction>;
|
||||
expect(mockWarn.mock.calls.length).toBe(1);
|
||||
const [{ user, durationMs }, message] = mockWarn.mock.calls[0];
|
||||
expect(user).toEqual('bcrypt');
|
||||
expect(durationMs).toBeGreaterThan(DEFAULT_SLOW_VERIFY_MS);
|
||||
expect(message).toEqual('Password for user "@{user}" took @{durationMs}ms to verify');
|
||||
done();
|
||||
};
|
||||
wrapper.authenticate('test', 'somerandompassword', callback);
|
||||
});
|
||||
wrapper.authenticate('bcrypt', 'password', callback);
|
||||
}, 15000);
|
||||
});
|
||||
|
||||
describe('addUser()', () => {
|
||||
@@ -122,7 +146,7 @@ describe('HTPasswd', () => {
|
||||
});
|
||||
|
||||
const HTPasswd = require('../src/htpasswd.ts').default;
|
||||
const wrapper = new HTPasswd(config, stuff);
|
||||
const wrapper = new HTPasswd(config, options);
|
||||
wrapper.adduser('sanityCheck', 'test', (sanity) => {
|
||||
expect(sanity.message).toBeDefined();
|
||||
expect(sanity.message).toMatch('some error');
|
||||
@@ -140,7 +164,7 @@ describe('HTPasswd', () => {
|
||||
});
|
||||
|
||||
const HTPasswd = require('../src/htpasswd.ts').default;
|
||||
const wrapper = new HTPasswd(config, stuff);
|
||||
const wrapper = new HTPasswd(config, options);
|
||||
wrapper.adduser('lockAndRead', 'test', (sanity) => {
|
||||
expect(sanity.message).toBeDefined();
|
||||
expect(sanity.message).toMatch('lock error');
|
||||
@@ -160,7 +184,7 @@ describe('HTPasswd', () => {
|
||||
});
|
||||
|
||||
const HTPasswd = require('../src/htpasswd.ts').default;
|
||||
const wrapper = new HTPasswd(config, stuff);
|
||||
const wrapper = new HTPasswd(config, options);
|
||||
wrapper.adduser('addUserToHTPasswd', 'test', () => {
|
||||
done();
|
||||
});
|
||||
@@ -187,7 +211,7 @@ describe('HTPasswd', () => {
|
||||
});
|
||||
|
||||
const HTPasswd = require('../src/htpasswd.ts').default;
|
||||
const wrapper = new HTPasswd(config, stuff);
|
||||
const wrapper = new HTPasswd(config, options);
|
||||
wrapper.adduser('addUserToHTPasswd', 'test', (err) => {
|
||||
expect(err).not.toBeNull();
|
||||
expect(err.message).toMatch('write error');
|
||||
@@ -198,7 +222,11 @@ describe('HTPasswd', () => {
|
||||
|
||||
describe('reload()', () => {
|
||||
test('it should read the file and set the users', (done) => {
|
||||
const output = { test: '$6FrCaT/v0dwE', username: '$66to3JK5RgZM' };
|
||||
const output = {
|
||||
test: '$6FrCaT/v0dwE',
|
||||
username: '$66to3JK5RgZM',
|
||||
bcrypt: '$2y$04$K2Cn3StiXx4CnLmcTW/ymekOrj7WlycZZF9xgmoJ/U0zGPqSLPVBe',
|
||||
};
|
||||
const callback = (): void => {
|
||||
expect(wrapper.users).toEqual(output);
|
||||
done();
|
||||
@@ -224,7 +252,7 @@ describe('HTPasswd', () => {
|
||||
};
|
||||
|
||||
const HTPasswd = require('../src/htpasswd.ts').default;
|
||||
const wrapper = new HTPasswd(config, stuff);
|
||||
const wrapper = new HTPasswd(config, options);
|
||||
wrapper.reload(callback);
|
||||
});
|
||||
|
||||
@@ -247,7 +275,7 @@ describe('HTPasswd', () => {
|
||||
};
|
||||
|
||||
const HTPasswd = require('../src/htpasswd.ts').default;
|
||||
const wrapper = new HTPasswd(config, stuff);
|
||||
const wrapper = new HTPasswd(config, options);
|
||||
wrapper.reload(callback);
|
||||
});
|
||||
|
||||
@@ -267,7 +295,7 @@ describe('HTPasswd', () => {
|
||||
};
|
||||
|
||||
const HTPasswd = require('../src/htpasswd.ts').default;
|
||||
const wrapper = new HTPasswd(config, stuff);
|
||||
const wrapper = new HTPasswd(config, options);
|
||||
wrapper.reload(callback);
|
||||
});
|
||||
});
|
||||
@@ -276,7 +304,9 @@ describe('HTPasswd', () => {
|
||||
test('changePassword - it should throw an error for user not found', (done) => {
|
||||
const callback = (error, isSuccess): void => {
|
||||
expect(error).not.toBeNull();
|
||||
expect(error.message).toBe('User not found');
|
||||
expect(error.message).toBe(
|
||||
`Unable to change password for user 'usernotpresent': user does not currently exist`
|
||||
);
|
||||
expect(isSuccess).toBeFalsy();
|
||||
done();
|
||||
};
|
||||
@@ -286,7 +316,9 @@ describe('HTPasswd', () => {
|
||||
test('changePassword - it should throw an error for wrong password', (done) => {
|
||||
const callback = (error, isSuccess): void => {
|
||||
expect(error).not.toBeNull();
|
||||
expect(error.message).toBe('Invalid old Password');
|
||||
expect(error.message).toBe(
|
||||
`Unable to change password for user 'username': invalid old password`
|
||||
);
|
||||
expect(isSuccess).toBeFalsy();
|
||||
done();
|
||||
};
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// @ts-ignore: Module has no default export
|
||||
import crypto from 'crypto';
|
||||
import MockDate from 'mockdate';
|
||||
|
||||
@@ -66,40 +67,40 @@ user4:$6FrCasdvppdwE:autocreated 2017-12-14T13:30:20.838Z`;
|
||||
});
|
||||
|
||||
describe('verifyPassword', () => {
|
||||
it('should verify the MD5/Crypt3 password with true', () => {
|
||||
it('should verify the MD5/Crypt3 password with true', async () => {
|
||||
const input = ['test', '$apr1$sKXK9.lG$rZ4Iy63Vtn8jF9/USc4BV0'];
|
||||
expect(verifyPassword(input[0], input[1])).toBeTruthy();
|
||||
expect(await verifyPassword(input[0], input[1])).toBeTruthy();
|
||||
});
|
||||
it('should verify the MD5/Crypt3 password with false', () => {
|
||||
it('should verify the MD5/Crypt3 password with false', async () => {
|
||||
const input = ['testpasswordchanged', '$apr1$sKXK9.lG$rZ4Iy63Vtn8jF9/USc4BV0'];
|
||||
expect(verifyPassword(input[0], input[1])).toBeFalsy();
|
||||
expect(await verifyPassword(input[0], input[1])).toBeFalsy();
|
||||
});
|
||||
it('should verify the plain password with true', () => {
|
||||
it('should verify the plain password with true', async () => {
|
||||
const input = ['testpasswordchanged', '{PLAIN}testpasswordchanged'];
|
||||
expect(verifyPassword(input[0], input[1])).toBeTruthy();
|
||||
expect(await verifyPassword(input[0], input[1])).toBeTruthy();
|
||||
});
|
||||
it('should verify the plain password with false', () => {
|
||||
it('should verify the plain password with false', async () => {
|
||||
const input = ['testpassword', '{PLAIN}testpasswordchanged'];
|
||||
expect(verifyPassword(input[0], input[1])).toBeFalsy();
|
||||
expect(await verifyPassword(input[0], input[1])).toBeFalsy();
|
||||
});
|
||||
it('should verify the crypto SHA password with true', () => {
|
||||
it('should verify the crypto SHA password with true', async () => {
|
||||
const input = ['testpassword', '{SHA}i7YRj4/Wk1rQh2o740pxfTJwj/0='];
|
||||
expect(verifyPassword(input[0], input[1])).toBeTruthy();
|
||||
expect(await verifyPassword(input[0], input[1])).toBeTruthy();
|
||||
});
|
||||
it('should verify the crypto SHA password with false', () => {
|
||||
it('should verify the crypto SHA password with false', async () => {
|
||||
const input = ['testpasswordchanged', '{SHA}i7YRj4/Wk1rQh2o740pxfTJwj/0='];
|
||||
expect(verifyPassword(input[0], input[1])).toBeFalsy();
|
||||
expect(await verifyPassword(input[0], input[1])).toBeFalsy();
|
||||
});
|
||||
it('should verify the bcrypt password with true', () => {
|
||||
it('should verify the bcrypt password with true', async () => {
|
||||
const input = ['testpassword', '$2y$04$Wqed4yN0OktGbiUdxSTwtOva1xfESfkNIZfcS9/vmHLsn3.lkFxJO'];
|
||||
expect(verifyPassword(input[0], input[1])).toBeTruthy();
|
||||
expect(await verifyPassword(input[0], input[1])).toBeTruthy();
|
||||
});
|
||||
it('should verify the bcrypt password with false', () => {
|
||||
it('should verify the bcrypt password with false', async () => {
|
||||
const input = [
|
||||
'testpasswordchanged',
|
||||
'$2y$04$Wqed4yN0OktGbiUdxSTwtOva1xfESfkNIZfcS9/vmHLsn3.lkFxJO',
|
||||
];
|
||||
expect(verifyPassword(input[0], input[1])).toBeFalsy();
|
||||
expect(await verifyPassword(input[0], input[1])).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -170,58 +171,58 @@ describe('sanityCheck', () => {
|
||||
users = { test: '$6FrCaT/v0dwE' };
|
||||
});
|
||||
|
||||
test('should throw error for user already exists', () => {
|
||||
test('should throw error for user already exists', async () => {
|
||||
const verifyFn = jest.fn();
|
||||
const input = sanityCheck('test', users.test, verifyFn, users, Infinity);
|
||||
const input = await sanityCheck('test', users.test, verifyFn, users, Infinity);
|
||||
expect(input.status).toEqual(401);
|
||||
expect(input.message).toEqual('unauthorized access');
|
||||
expect(verifyFn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should throw error for registration disabled of users', () => {
|
||||
test('should throw error for registration disabled of users', async () => {
|
||||
const verifyFn = (): void => {};
|
||||
const input = sanityCheck('username', users.test, verifyFn, users, -1);
|
||||
const input = await sanityCheck('username', users.test, verifyFn, users, -1);
|
||||
expect(input.status).toEqual(409);
|
||||
expect(input.message).toEqual('user registration disabled');
|
||||
});
|
||||
|
||||
test('should throw error max number of users', () => {
|
||||
test('should throw error max number of users', async () => {
|
||||
const verifyFn = (): void => {};
|
||||
const input = sanityCheck('username', users.test, verifyFn, users, 1);
|
||||
const input = await sanityCheck('username', users.test, verifyFn, users, 1);
|
||||
expect(input.status).toEqual(403);
|
||||
expect(input.message).toEqual('maximum amount of users reached');
|
||||
});
|
||||
|
||||
test('should not throw anything and sanity check', () => {
|
||||
test('should not throw anything and sanity check', async () => {
|
||||
const verifyFn = (): void => {};
|
||||
const input = sanityCheck('username', users.test, verifyFn, users, 2);
|
||||
const input = await sanityCheck('username', users.test, verifyFn, users, 2);
|
||||
expect(input).toBeNull();
|
||||
});
|
||||
|
||||
test('should throw error for required username field', () => {
|
||||
test('should throw error for required username field', async () => {
|
||||
const verifyFn = (): void => {};
|
||||
const input = sanityCheck(undefined, users.test, verifyFn, users, 2);
|
||||
const input = await sanityCheck(undefined, users.test, verifyFn, users, 2);
|
||||
expect(input.message).toEqual('username and password is required');
|
||||
expect(input.status).toEqual(400);
|
||||
});
|
||||
|
||||
test('should throw error for required password field', () => {
|
||||
test('should throw error for required password field', async () => {
|
||||
const verifyFn = (): void => {};
|
||||
const input = sanityCheck('username', undefined, verifyFn, users, 2);
|
||||
const input = await sanityCheck('username', undefined, verifyFn, users, 2);
|
||||
expect(input.message).toEqual('username and password is required');
|
||||
expect(input.status).toEqual(400);
|
||||
});
|
||||
|
||||
test('should throw error for required username & password fields', () => {
|
||||
test('should throw error for required username & password fields', async () => {
|
||||
const verifyFn = (): void => {};
|
||||
const input = sanityCheck(undefined, undefined, verifyFn, users, 2);
|
||||
const input = await sanityCheck(undefined, undefined, verifyFn, users, 2);
|
||||
expect(input.message).toEqual('username and password is required');
|
||||
expect(input.status).toEqual(400);
|
||||
});
|
||||
|
||||
test('should throw error for existing username and password', () => {
|
||||
test('should throw error for existing username and password', async () => {
|
||||
const verifyFn = jest.fn(() => true);
|
||||
const input = sanityCheck('test', users.test, verifyFn, users, 2);
|
||||
const input = await sanityCheck('test', users.test, verifyFn, users, 2);
|
||||
expect(input.status).toEqual(409);
|
||||
expect(input.message).toEqual('username is already registered');
|
||||
expect(verifyFn).toHaveBeenCalledTimes(1);
|
||||
@@ -229,9 +230,9 @@ describe('sanityCheck', () => {
|
||||
|
||||
test(
|
||||
'should throw error for existing username and password with max number ' + 'of users reached',
|
||||
() => {
|
||||
async () => {
|
||||
const verifyFn = jest.fn(() => true);
|
||||
const input = sanityCheck('test', users.test, verifyFn, users, 1);
|
||||
const input = await sanityCheck('test', users.test, verifyFn, users, 1);
|
||||
expect(input.status).toEqual(409);
|
||||
expect(input.message).toEqual('username is already registered');
|
||||
expect(verifyFn).toHaveBeenCalledTimes(1);
|
||||
@@ -240,11 +241,11 @@ describe('sanityCheck', () => {
|
||||
});
|
||||
|
||||
describe('changePasswordToHTPasswd', () => {
|
||||
test('should throw error for wrong password', () => {
|
||||
test('should throw error for wrong password', async () => {
|
||||
const body = 'test:$6b9MlB3WUELU:autocreated 2017-11-06T18:17:21.957Z';
|
||||
|
||||
try {
|
||||
changePasswordToHTPasswd(
|
||||
await changePasswordToHTPasswd(
|
||||
body,
|
||||
'test',
|
||||
'somerandompassword',
|
||||
@@ -252,15 +253,35 @@ describe('changePasswordToHTPasswd', () => {
|
||||
defaultHashConfig
|
||||
);
|
||||
} catch (error: any) {
|
||||
expect(error.message).toEqual('Invalid old Password');
|
||||
expect(error.message).toEqual(
|
||||
`Unable to change password for user 'test': invalid old password`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test('should change the password', () => {
|
||||
test('should throw error when user does not exist', async () => {
|
||||
const body = 'test:$6b9MlB3WUELU:autocreated 2017-11-06T18:17:21.957Z';
|
||||
|
||||
try {
|
||||
await changePasswordToHTPasswd(
|
||||
body,
|
||||
'test2',
|
||||
'somerandompassword',
|
||||
'newPassword',
|
||||
defaultHashConfig
|
||||
);
|
||||
} catch (error: any) {
|
||||
expect(error.message).toEqual(
|
||||
`Unable to change password for user 'test2': user does not currently exist`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test('should change the password', async () => {
|
||||
const body = 'root:$6qLTHoPfGLy2:autocreated 2018-08-20T13:38:12.164Z';
|
||||
|
||||
expect(
|
||||
changePasswordToHTPasswd(body, 'root', 'demo123', 'newPassword', defaultHashConfig)
|
||||
await changePasswordToHTPasswd(body, 'root', 'demo123', 'newPassword', defaultHashConfig)
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,35 @@
|
||||
# @verdaccio/ui-theme
|
||||
|
||||
## 6.0.0-6-next.22
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- a2b69a08: add banner support ukraine
|
||||
|
||||
## 6.0.0-6-next.21
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- a179f1fd: show verdaccio logo in the footer even when custom brand is set
|
||||
|
||||
## 6.0.0-6-next.20
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 635ca3f9: chore: force publish
|
||||
|
||||
## 6.0.0-6-next.19
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- aa0b2aa9: fix: replace ts icon by td and fix commonjs icon
|
||||
|
||||
## 6.0.0-6-next.18
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- df53f61c: feat: add types and package module icons on sidebar
|
||||
|
||||
## 6.0.0-6-next.17
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -4,7 +4,7 @@ module.exports = Object.assign({}, config, {
|
||||
name: 'verdaccio-ui-jest',
|
||||
verbose: true,
|
||||
automock: false,
|
||||
collectCoverage: true,
|
||||
collectCoverage: false,
|
||||
testEnvironment: 'jest-environment-jsdom-global',
|
||||
transform: {
|
||||
'^.+\\.(js|ts|tsx)$': 'babel-jest',
|
||||
@@ -29,6 +29,7 @@ module.exports = Object.assign({}, config, {
|
||||
'\\.(s?css)$': '<rootDir>/jest/identity.js',
|
||||
'\\.(png)$': '<rootDir>/jest/identity.js',
|
||||
'\\.(svg)$': '<rootDir>/jest/unit/empty.ts',
|
||||
'\\.(jpg)$': '<rootDir>/jest/unit/empty.ts',
|
||||
'github-markdown-css': '<rootDir>/jest/identity.js',
|
||||
// note: this section has to be on sync with webpack configuration
|
||||
'verdaccio-ui/components/(.*)': '<rootDir>/src/components/$1',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@verdaccio/ui-theme",
|
||||
"version": "6.0.0-6-next.17",
|
||||
"version": "6.0.0-6-next.22",
|
||||
"description": "Verdaccio User Interface",
|
||||
"author": {
|
||||
"name": "Verdaccio Contributors",
|
||||
@@ -33,7 +33,7 @@
|
||||
"@testing-library/dom": "8.11.2",
|
||||
"@testing-library/jest-dom": "5.16.1",
|
||||
"@testing-library/react": "12.1.2",
|
||||
"@verdaccio/node-api": "workspace:6.0.0-6-next.27",
|
||||
"@verdaccio/node-api": "workspace:6.0.0-6-next.29",
|
||||
"@verdaccio/types": "workspace:*",
|
||||
"babel-loader": "8.2.3",
|
||||
"babel-plugin-dynamic-import-node": "2.3.3",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/* eslint-disable react/jsx-max-depth */
|
||||
import styled from '@emotion/styled';
|
||||
import Box from '@mui/material/Box';
|
||||
import React, { Suspense, useEffect } from 'react';
|
||||
import { Router } from 'react-router-dom';
|
||||
import Box from 'verdaccio-ui/components/Box';
|
||||
import Loading from 'verdaccio-ui/components/Loading';
|
||||
import StyleBaseline from 'verdaccio-ui/design-tokens/StyleBaseline';
|
||||
import loadDayJSLocale from 'verdaccio-ui/design-tokens/load-dayjs-locale';
|
||||
|
||||
@@ -56,7 +56,7 @@ const Footer = () => {
|
||||
{configOptions?.version && (
|
||||
<>
|
||||
{t('footer.powered-by')}
|
||||
<Logo onClick={goToVerdaccioWebsite} size="x-small" />
|
||||
<Logo isDefault={true} onClick={goToVerdaccioWebsite} size="x-small" />
|
||||
{`/ ${configOptions.version}`}
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Button from '@mui/material/Button';
|
||||
import React, { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import Button from 'verdaccio-ui/components/Button';
|
||||
import { useConfig } from 'verdaccio-ui/providers/config';
|
||||
|
||||
import { Dispatch, RootState } from '../../store/store';
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import AccountCircle from '@mui/icons-material/AccountCircle';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import Menu from '@mui/material/Menu';
|
||||
import React, { MouseEvent } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import IconButton from 'verdaccio-ui/components/IconButton';
|
||||
import Menu from 'verdaccio-ui/components/Menu';
|
||||
import MenuItem from 'verdaccio-ui/components/MenuItem';
|
||||
|
||||
import HeaderGreetings from './HeaderGreetings';
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import Button from '@mui/material/Button';
|
||||
import React, { MouseEvent, useContext, useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Button from 'verdaccio-ui/components/Button';
|
||||
import ThemeContext from 'verdaccio-ui/design-tokens/ThemeContext';
|
||||
|
||||
import HeaderMenu from './HeaderMenu';
|
||||
import HeaderToolTip from './HeaderToolTip';
|
||||
import { Support } from './Support';
|
||||
import { RightSide } from './styles';
|
||||
|
||||
interface Props {
|
||||
@@ -78,6 +79,7 @@ const HeaderRight: React.FC<Props> = ({
|
||||
tooltipIconType={'search'}
|
||||
/>
|
||||
)}
|
||||
<Support />
|
||||
<HeaderToolTip title={t('header.documentation')} tooltipIconType={'help'} />
|
||||
<HeaderToolTip
|
||||
onClick={onOpenRegistryInfoDialog}
|
||||
|
||||
@@ -3,8 +3,8 @@ import Info from '@mui/icons-material/Info';
|
||||
import NightsStay from '@mui/icons-material/NightsStay';
|
||||
import Search from '@mui/icons-material/Search';
|
||||
import WbSunny from '@mui/icons-material/WbSunny';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import React, { forwardRef } from 'react';
|
||||
import IconButton from 'verdaccio-ui/components/IconButton';
|
||||
|
||||
import { IconSearchButton, StyledLink } from './styles';
|
||||
|
||||
@@ -55,7 +55,6 @@ const HeaderToolTipIcon = forwardRef<HeaderToolTipIconRef, Props>(function Heade
|
||||
</IconSearchButton>
|
||||
);
|
||||
case 'dark-mode':
|
||||
// todo(Priscila): Add Zoom transition effect
|
||||
return (
|
||||
<IconButton color="inherit" onClick={onClick} ref={ref} size="large">
|
||||
<NightsStay />
|
||||
@@ -63,7 +62,6 @@ const HeaderToolTipIcon = forwardRef<HeaderToolTipIconRef, Props>(function Heade
|
||||
);
|
||||
|
||||
case 'light-mode':
|
||||
// todo(Priscila): Add Zoom transition effect
|
||||
return (
|
||||
<IconButton color="inherit" onClick={onClick} ref={ref} size="large">
|
||||
<WbSunny />
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import Dialog from '@mui/material/Dialog';
|
||||
import DialogContent from '@mui/material/DialogContent';
|
||||
import i18next from 'i18next';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import Dialog from 'verdaccio-ui/components/Dialog';
|
||||
import DialogContent from 'verdaccio-ui/components/DialogContent';
|
||||
|
||||
import { LoginBody } from '../../../store/models/login';
|
||||
import { Dispatch, RootState } from '../../../store/store';
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import styled from '@emotion/styled';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import DialogTitle from '@mui/material/DialogTitle';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import DialogTitle from 'verdaccio-ui/components/DialogTitle';
|
||||
import IconButton from 'verdaccio-ui/components/IconButton';
|
||||
import { Theme } from 'verdaccio-ui/design-tokens/theme';
|
||||
|
||||
const StyledIconButton = styled(IconButton)<{ theme?: Theme }>(({ theme }) => ({
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/* eslint-disable verdaccio/jsx-spread */
|
||||
import styled from '@emotion/styled';
|
||||
import Button from '@mui/material/Button';
|
||||
import React, { memo } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Button from 'verdaccio-ui/components/Button';
|
||||
import TextField from 'verdaccio-ui/components/TextField';
|
||||
import { Theme } from 'verdaccio-ui/design-tokens/theme';
|
||||
import { LoginError } from 'verdaccio-ui/utils/login';
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import styled from '@emotion/styled';
|
||||
import Error from '@mui/icons-material/Error';
|
||||
import Box from '@mui/material/Box';
|
||||
import SnackbarContent from '@mui/material/SnackbarContent';
|
||||
import React, { memo } from 'react';
|
||||
import Box from 'verdaccio-ui/components/Box';
|
||||
import SnackbarContent from 'verdaccio-ui/components/SnackbarContent';
|
||||
import { Theme } from 'verdaccio-ui/design-tokens/theme';
|
||||
import { LoginError } from 'verdaccio-ui/utils/login';
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import styled from '@emotion/styled';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import LockOutlined from '@mui/icons-material/LockOutlined';
|
||||
import Avatar from '@mui/material/Avatar';
|
||||
import Box from '@mui/material/Box';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Avatar from 'verdaccio-ui/components/Avatar';
|
||||
import Box from 'verdaccio-ui/components/Box';
|
||||
import Heading from 'verdaccio-ui/components/Heading';
|
||||
import IconButton from 'verdaccio-ui/components/IconButton';
|
||||
import { Theme } from 'verdaccio-ui/design-tokens/theme';
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import Button from '@mui/material/Button';
|
||||
import Dialog from '@mui/material/Dialog';
|
||||
import DialogActions from '@mui/material/DialogActions';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Button from 'verdaccio-ui/components/Button';
|
||||
import Dialog from 'verdaccio-ui/components/Dialog';
|
||||
import DialogActions from 'verdaccio-ui/components/DialogActions';
|
||||
|
||||
import { Content, Title } from './styles';
|
||||
import { Props } from './types';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import styled from '@emotion/styled';
|
||||
import DialogContent from 'verdaccio-ui/components/DialogContent';
|
||||
import DialogTitle from 'verdaccio-ui/components/DialogTitle';
|
||||
import DialogContent from '@mui/material/DialogContent';
|
||||
import DialogTitle from '@mui/material/DialogTitle';
|
||||
import { Theme } from 'verdaccio-ui/design-tokens/theme';
|
||||
|
||||
export const Title = styled(DialogTitle)<{ theme?: Theme }>((props) => ({
|
||||
|
||||
139
packages/plugins/ui-theme/src/App/Header/Support/Support.tsx
Normal file
139
packages/plugins/ui-theme/src/App/Header/Support/Support.tsx
Normal file
@@ -0,0 +1,139 @@
|
||||
/* eslint-disable verdaccio/jsx-no-style */
|
||||
|
||||
/* eslint-disable react/jsx-max-depth */
|
||||
|
||||
/* eslint-disable react/jsx-pascal-case */
|
||||
import styled from '@emotion/styled';
|
||||
import { Theme } from '@mui/material';
|
||||
import Box from '@mui/material/Box';
|
||||
import Divider from '@mui/material/Divider';
|
||||
import Grid from '@mui/material/Grid';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import Modal from '@mui/material/Modal';
|
||||
import Tooltip from '@mui/material/Tooltip';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import FlagsIcon from 'country-flag-icons/react/3x2';
|
||||
import React from 'react';
|
||||
|
||||
import flag from './uk.jpg';
|
||||
|
||||
const style = {
|
||||
position: 'absolute',
|
||||
top: '50%',
|
||||
left: '50%',
|
||||
transform: 'translate(-50%, -50%)',
|
||||
bgcolor: 'background.paper',
|
||||
border: '2px solid #000',
|
||||
boxShadow: 24,
|
||||
p: 4,
|
||||
};
|
||||
|
||||
const Flags = styled('span')<{ theme?: Theme }>(() => ({
|
||||
width: '25px',
|
||||
}));
|
||||
|
||||
const title = 'Support people affected by the war in Ukraine';
|
||||
const Support = () => {
|
||||
const [open, setOpen] = React.useState(false);
|
||||
const handleOpen = () => setOpen(true);
|
||||
const handleClose = () => setOpen(false);
|
||||
return (
|
||||
<>
|
||||
<Tooltip title={title}>
|
||||
<IconButton color="inherit" onClick={handleOpen} size="large">
|
||||
<Flags>
|
||||
<FlagsIcon.UA />
|
||||
</Flags>
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Modal
|
||||
aria-describedby="modal-modal-description"
|
||||
aria-labelledby="modal-modal-title"
|
||||
onClose={handleClose}
|
||||
open={open}
|
||||
>
|
||||
<Box sx={style}>
|
||||
<Grid container={true} spacing={2}>
|
||||
<Grid item={true} xs={12}>
|
||||
<Typography component="h2" variant="h6">
|
||||
{title}
|
||||
</Typography>
|
||||
<Divider />
|
||||
</Grid>
|
||||
<Grid item={true} lg={4} xs={12}>
|
||||
<img alt={title} height="150" src={flag} />
|
||||
</Grid>
|
||||
<Grid item={true} lg={8} xs={12}>
|
||||
<span style={{ fontStyle: 'italic', fontSize: '0.75rem' }}>
|
||||
<Typography>
|
||||
{`Hi, this is a message that I've composed to call your attention to ask
|
||||
for humanitarian support for more than 44 million Ukrainians that are having
|
||||
a hard time suffering for a horrible and unjustified war. It would be great if you
|
||||
decide today to make a difference and help others. You could help by donating
|
||||
to very well-known humanitarian organizations, helping in your local
|
||||
area with food, clothes, donate blood, toys for kids, or your own time. Any help is very welcome.`}
|
||||
</Typography>
|
||||
</span>
|
||||
<ul style={{ padding: '10px 0' }}>
|
||||
<li>
|
||||
<a
|
||||
href="https://twitter.com/denysdovhan/status/1501486563842211843"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
{'Listen at Twitter OSS developers about the war'}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://snyk.io/blog/celebrating-amazing-open-source-innovation-ukraine/"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
{'Learn more about Open Source developers in Ukraine'}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://www.savethechildren.org/us/where-we-work/ukraine/"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
{'Donate to Save the Children'}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.ifrc.org/" rel="noreferrer" target="_blank">
|
||||
{'Donate to the International Red Cross'}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://www.hrw.org/news/2022/03/10/ukraine-russian-air-dropped-bombs-hit-residential-area/"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
{'Read Reports from Human Rights Watch'}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://europeanbloodalliance.eu/" rel="noreferrer" target="_blank">
|
||||
{'Donate blood in Europe'}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div>
|
||||
<Typography variant="div">{`Spread the voice, make the difference today.`}</Typography>
|
||||
</div>
|
||||
<div style={{ padding: '10px 0', fontWeight: 600 }}>
|
||||
<Typography variant="div">{`Att: Verdaccio Lead Mantainer, Juan P.`}</Typography>
|
||||
</div>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export { Support };
|
||||
@@ -0,0 +1,3 @@
|
||||
import { Support } from './Support';
|
||||
|
||||
export { Support };
|
||||
BIN
packages/plugins/ui-theme/src/App/Header/Support/uk.jpg
Normal file
BIN
packages/plugins/ui-theme/src/App/Header/Support/uk.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.2 KiB |
@@ -1,7 +1,7 @@
|
||||
import { css } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import AppBar from 'verdaccio-ui/components/AppBar';
|
||||
import IconButton from 'verdaccio-ui/components/IconButton';
|
||||
import Link from 'verdaccio-ui/components/Link';
|
||||
import Toolbar from 'verdaccio-ui/components/Toolbar';
|
||||
import { Theme } from 'verdaccio-ui/design-tokens/theme';
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import Box from '@mui/material/Box';
|
||||
import React from 'react';
|
||||
import { isURL } from 'verdaccio-ui/utils/url';
|
||||
|
||||
import { DetailContext } from '../../pages/Version';
|
||||
import Box from '../Box';
|
||||
import ActionBarAction, { ActionBarActionProps } from './ActionBarAction';
|
||||
|
||||
/* eslint-disable verdaccio/jsx-spread */
|
||||
|
||||
@@ -18,7 +18,7 @@ exports[`<ActionBar /> component should render the component in default state 1`
|
||||
font-family: -apple-system,BlinkMacSystemFont,"Helvetica Neue",Arial,sans-serif;
|
||||
font-weight: 400;
|
||||
font-size: 1rem;
|
||||
line-height: 1.75;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.emotion-3 {
|
||||
@@ -162,8 +162,8 @@ exports[`<ActionBar /> component should render the component in default state 1`
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
<span
|
||||
class="MuiTypography-root MuiTypography-subtitle1 emotion-1"
|
||||
<p
|
||||
class="MuiTypography-root MuiTypography-body1 emotion-1"
|
||||
>
|
||||
<button
|
||||
class="MuiButtonBase-root MuiFab-root MuiFab-circular MuiFab-sizeSmall emotion-2 emotion-3"
|
||||
@@ -186,7 +186,7 @@ exports[`<ActionBar /> component should render the component in default state 1`
|
||||
class="MuiTouchRipple-root emotion-5"
|
||||
/>
|
||||
</button>
|
||||
</span>
|
||||
</p>
|
||||
</a>
|
||||
<a
|
||||
aria-label="Open an issue"
|
||||
@@ -196,8 +196,8 @@ exports[`<ActionBar /> component should render the component in default state 1`
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
<span
|
||||
class="MuiTypography-root MuiTypography-subtitle1 emotion-1"
|
||||
<p
|
||||
class="MuiTypography-root MuiTypography-body1 emotion-1"
|
||||
>
|
||||
<button
|
||||
class="MuiButtonBase-root MuiFab-root MuiFab-circular MuiFab-sizeSmall emotion-2 emotion-3"
|
||||
@@ -220,7 +220,7 @@ exports[`<ActionBar /> component should render the component in default state 1`
|
||||
class="MuiTouchRipple-root emotion-5"
|
||||
/>
|
||||
</button>
|
||||
</span>
|
||||
</p>
|
||||
</a>
|
||||
<button
|
||||
aria-label="Download tarball"
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
import { AppBarProps, default as MaterialUIAppBar } from '@mui/material/AppBar';
|
||||
import React, { forwardRef } from 'react';
|
||||
import { default as MaterialUIAppBar } from '@mui/material/AppBar';
|
||||
|
||||
type AppBarRef = HTMLElementTagNameMap[keyof HTMLElementTagNameMap];
|
||||
|
||||
const AppBar = forwardRef<AppBarRef, AppBarProps>(function AppBar(props, ref) {
|
||||
return <MaterialUIAppBar {...props} ref={ref} />;
|
||||
});
|
||||
|
||||
export default AppBar;
|
||||
export default MaterialUIAppBar;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import Avatar from '@mui/material/Avatar';
|
||||
import List from '@mui/material/List';
|
||||
import React, { FC, useContext } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { getAuthorName } from 'verdaccio-ui/utils/package';
|
||||
import { isEmail } from 'verdaccio-ui/utils/url';
|
||||
|
||||
import { DetailContext } from '../../pages/Version';
|
||||
import List from '../List';
|
||||
import { AuthorListItem, AuthorListItemText, StyledText } from './styles';
|
||||
|
||||
const Author: FC = () => {
|
||||
|
||||
@@ -215,11 +215,11 @@ Object {
|
||||
<ul
|
||||
class="MuiList-root MuiList-padding MuiList-subheader emotion-0"
|
||||
>
|
||||
<span
|
||||
<h6
|
||||
class="MuiTypography-root MuiTypography-subtitle1 emotion-1 emotion-2"
|
||||
>
|
||||
Author
|
||||
</span>
|
||||
</h6>
|
||||
<div
|
||||
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-padding MuiListItem-button emotion-3 emotion-4"
|
||||
role="button"
|
||||
@@ -466,11 +466,11 @@ Object {
|
||||
<ul
|
||||
class="MuiList-root MuiList-padding MuiList-subheader emotion-0"
|
||||
>
|
||||
<span
|
||||
<h6
|
||||
class="MuiTypography-root MuiTypography-subtitle1 emotion-1 emotion-2"
|
||||
>
|
||||
Author
|
||||
</span>
|
||||
</h6>
|
||||
<div
|
||||
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-padding MuiListItem-button emotion-3 emotion-4"
|
||||
role="button"
|
||||
@@ -774,11 +774,11 @@ Object {
|
||||
<ul
|
||||
class="MuiList-root MuiList-padding MuiList-subheader emotion-0"
|
||||
>
|
||||
<span
|
||||
<h6
|
||||
class="MuiTypography-root MuiTypography-subtitle1 emotion-1 emotion-2"
|
||||
>
|
||||
Author
|
||||
</span>
|
||||
</h6>
|
||||
<div
|
||||
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-padding MuiListItem-button emotion-3 emotion-4"
|
||||
role="button"
|
||||
@@ -1020,11 +1020,11 @@ Object {
|
||||
<ul
|
||||
class="MuiList-root MuiList-padding MuiList-subheader emotion-0"
|
||||
>
|
||||
<span
|
||||
<h6
|
||||
class="MuiTypography-root MuiTypography-subtitle1 emotion-1 emotion-2"
|
||||
>
|
||||
Author
|
||||
</span>
|
||||
</h6>
|
||||
<div
|
||||
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-padding MuiListItem-button emotion-3 emotion-4"
|
||||
role="button"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import styled from '@emotion/styled';
|
||||
import ListItem from '@mui/material/ListItem';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
import { Theme } from 'verdaccio-ui/design-tokens/theme';
|
||||
|
||||
import ListItem from '../ListItem';
|
||||
import ListItemText from '../ListItemText';
|
||||
import Text from '../Text';
|
||||
|
||||
export const StyledText = styled(Text)<{ theme?: Theme }>((props) => ({
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import { default as MaterialUIAvatar } from '@mui/material/Avatar';
|
||||
|
||||
export default MaterialUIAvatar;
|
||||
@@ -1,8 +0,0 @@
|
||||
import { BoxProps, default as MaterialUIBox } from '@mui/material/Box';
|
||||
import React from 'react';
|
||||
|
||||
function Box(props: BoxProps) {
|
||||
return <MaterialUIBox {...props} />;
|
||||
}
|
||||
|
||||
export default Box;
|
||||
@@ -1,10 +0,0 @@
|
||||
import { ButtonProps, default as MaterialUIButton } from '@mui/material/Button';
|
||||
import React, { forwardRef } from 'react';
|
||||
|
||||
type ButtonRef = HTMLButtonElement;
|
||||
|
||||
const Button = forwardRef<ButtonRef, ButtonProps>(function Button(props, ref) {
|
||||
return <MaterialUIButton {...props} ref={ref} />;
|
||||
});
|
||||
|
||||
export default Button;
|
||||
@@ -1,10 +0,0 @@
|
||||
import { CardProps, default as MaterialUICard } from '@mui/material/Card';
|
||||
import React, { forwardRef } from 'react';
|
||||
|
||||
type CardRef = HTMLDivElement;
|
||||
|
||||
const Card = forwardRef<CardRef, CardProps>(function Card(props, ref) {
|
||||
return <MaterialUICard {...props} ref={ref} />;
|
||||
});
|
||||
|
||||
export default Card;
|
||||
@@ -1,13 +0,0 @@
|
||||
import { CardActionsProps, default as MaterialUICardActions } from '@mui/material/CardActions';
|
||||
import React, { forwardRef } from 'react';
|
||||
|
||||
type CardActionsRef = HTMLDivElement;
|
||||
|
||||
const CardActions = forwardRef<CardActionsRef, CardActionsProps>(function CardContentActions(
|
||||
props,
|
||||
ref
|
||||
) {
|
||||
return <MaterialUICardActions {...props} innerRef={ref} />;
|
||||
});
|
||||
|
||||
export default CardActions;
|
||||
@@ -1,10 +0,0 @@
|
||||
import { CardContentProps, default as MaterialUICardContent } from '@mui/material/CardContent';
|
||||
import React, { forwardRef } from 'react';
|
||||
|
||||
type CardContentRef = HTMLElementTagNameMap[keyof HTMLElementTagNameMap];
|
||||
|
||||
const CardContent = forwardRef<CardContentRef, CardContentProps>(function CardContent(props) {
|
||||
return <MaterialUICardContent {...props} />;
|
||||
});
|
||||
|
||||
export default CardContent;
|
||||
@@ -1,10 +0,0 @@
|
||||
import { ChipProps, default as MaterialUIChip } from '@mui/material/Chip';
|
||||
import React, { forwardRef } from 'react';
|
||||
|
||||
type ChipRef = HTMLElementTagNameMap[keyof HTMLElementTagNameMap];
|
||||
|
||||
const Chip = forwardRef<ChipRef, ChipProps>(function Chip(props) {
|
||||
return <MaterialUIChip {...props} />;
|
||||
});
|
||||
|
||||
export default Chip;
|
||||
@@ -1,15 +0,0 @@
|
||||
import {
|
||||
CircularProgressProps,
|
||||
default as MaterialUICircularProgress,
|
||||
} from '@mui/material/CircularProgress';
|
||||
import React, { forwardRef } from 'react';
|
||||
|
||||
type CircularProgressRef = HTMLDivElement;
|
||||
|
||||
const CircularProgress = forwardRef<CircularProgressRef, CircularProgressProps>(
|
||||
function CircularProgress(props, ref) {
|
||||
return <MaterialUICircularProgress {...props} ref={ref} />;
|
||||
}
|
||||
);
|
||||
|
||||
export default CircularProgress;
|
||||
@@ -1,12 +1,11 @@
|
||||
import styled from '@emotion/styled';
|
||||
import FileCopy from '@mui/icons-material/FileCopy';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import Tooltip from '@mui/material/Tooltip';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { copyToClipBoardUtility } from 'verdaccio-ui/utils/cli-utils';
|
||||
|
||||
import IconButton from './IconButton';
|
||||
import Tooltip from './Tooltip';
|
||||
|
||||
interface Props {
|
||||
text: string;
|
||||
children?: React.ReactNode;
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
import { DialogProps, default as MaterialUIDialog } from '@mui/material/Dialog';
|
||||
import React, { forwardRef } from 'react';
|
||||
|
||||
type DialogRef = HTMLDivElement;
|
||||
|
||||
const Dialog = forwardRef<DialogRef, DialogProps>(function Dialog(props, ref) {
|
||||
return <MaterialUIDialog {...props} ref={ref} />;
|
||||
});
|
||||
|
||||
export default Dialog;
|
||||
@@ -1,16 +0,0 @@
|
||||
import {
|
||||
DialogActionsProps,
|
||||
default as MaterialUIDialogActions,
|
||||
} from '@mui/material/DialogActions';
|
||||
import React, { forwardRef } from 'react';
|
||||
|
||||
type DialogActionsRef = HTMLDivElement;
|
||||
|
||||
const DialogActions = forwardRef<DialogActionsRef, DialogActionsProps>(function DialogActions(
|
||||
props,
|
||||
ref
|
||||
) {
|
||||
return <MaterialUIDialogActions {...props} ref={ref} />;
|
||||
});
|
||||
|
||||
export default DialogActions;
|
||||
@@ -1,16 +0,0 @@
|
||||
import {
|
||||
DialogContentProps,
|
||||
default as MaterialUIDialogContent,
|
||||
} from '@mui/material/DialogContent';
|
||||
import React, { forwardRef } from 'react';
|
||||
|
||||
type DialogContentRef = HTMLDivElement;
|
||||
|
||||
const DialogContent = forwardRef<DialogContentRef, DialogContentProps>(function DialogContent(
|
||||
props,
|
||||
ref
|
||||
) {
|
||||
return <MaterialUIDialogContent {...props} ref={ref} />;
|
||||
});
|
||||
|
||||
export default DialogContent;
|
||||
@@ -1,10 +0,0 @@
|
||||
import { DialogTitleProps, default as MaterialUIDialogTitle } from '@mui/material/DialogTitle';
|
||||
import React, { forwardRef } from 'react';
|
||||
|
||||
type DialogTitleRef = HTMLDivElement;
|
||||
|
||||
const DialogTitle = forwardRef<DialogTitleRef, DialogTitleProps>(function DialogTitle(props, ref) {
|
||||
return <MaterialUIDialogTitle {...props} ref={ref} />;
|
||||
});
|
||||
|
||||
export default DialogTitle;
|
||||
@@ -1,10 +0,0 @@
|
||||
import { DividerProps, default as MaterialUIDivider } from '@mui/material/Divider';
|
||||
import React, { forwardRef } from 'react';
|
||||
|
||||
type DividerRef = HTMLElementTagNameMap[keyof HTMLElementTagNameMap];
|
||||
|
||||
const Divider = forwardRef<DividerRef, DividerProps>(function Divider(props, ref) {
|
||||
return <MaterialUIDivider {...props} innerRef={ref} />;
|
||||
});
|
||||
|
||||
export default Divider;
|
||||
@@ -1,12 +1,8 @@
|
||||
import { FabProps, default as MaterialUIFab } from '@mui/material/Fab';
|
||||
import React, { forwardRef } from 'react';
|
||||
import Fab from '@mui/material/Fab';
|
||||
import React from 'react';
|
||||
|
||||
type FloatingActionButtonRef = HTMLButtonElement;
|
||||
|
||||
const FloatingActionButton = forwardRef<FloatingActionButtonRef, FabProps>(
|
||||
function FloatingActionButton(props, ref) {
|
||||
return <MaterialUIFab {...props} ref={ref} data-testid="fab" />;
|
||||
}
|
||||
);
|
||||
const FloatingActionButton = (props) => {
|
||||
return <Fab {...props} data-testid="fab" />;
|
||||
};
|
||||
|
||||
export default FloatingActionButton;
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
import { FormControlProps, default as MaterialUIFormControl } from '@mui/material/FormControl';
|
||||
import React, { forwardRef } from 'react';
|
||||
|
||||
type FormControlRef = HTMLElementTagNameMap[keyof HTMLElementTagNameMap];
|
||||
|
||||
const FormControl = forwardRef<FormControlRef, FormControlProps>(function FormControl(props, ref) {
|
||||
return <MaterialUIFormControl {...props} innerRef={ref} />;
|
||||
});
|
||||
|
||||
export default FormControl;
|
||||
@@ -1,16 +1,3 @@
|
||||
import {
|
||||
FormHelperTextProps,
|
||||
default as MaterialUIFormHelperText,
|
||||
} from '@mui/material/FormHelperText';
|
||||
import React, { forwardRef } from 'react';
|
||||
import { default as MaterialUIFormHelperText } from '@mui/material/FormHelperText';
|
||||
|
||||
type FormHelperTextRef = HTMLParagraphElement;
|
||||
|
||||
const FormHelperText = forwardRef<FormHelperTextRef, FormHelperTextProps>(function FormHelperText(
|
||||
props,
|
||||
ref
|
||||
) {
|
||||
return <MaterialUIFormHelperText {...props} ref={ref} />;
|
||||
});
|
||||
|
||||
export default FormHelperText;
|
||||
export default MaterialUIFormHelperText;
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
import { GridProps, default as MaterialUIGrid } from '@mui/material/Grid';
|
||||
import React, { forwardRef } from 'react';
|
||||
|
||||
type GridRef = HTMLElementTagNameMap[keyof HTMLElementTagNameMap];
|
||||
|
||||
const Grid = forwardRef<GridRef, GridProps>(function Grid(props, ref) {
|
||||
return <MaterialUIGrid {...props} innerRef={ref} />;
|
||||
});
|
||||
|
||||
export default Grid;
|
||||
@@ -1,10 +0,0 @@
|
||||
import { IconButtonProps, default as MaterialUIIconButton } from '@mui/material/IconButton';
|
||||
import React, { forwardRef } from 'react';
|
||||
|
||||
type IconButtonRef = HTMLButtonElement;
|
||||
|
||||
const IconButton = forwardRef<IconButtonRef, IconButtonProps>(function IconButton(props, ref) {
|
||||
return <MaterialUIIconButton {...props} ref={ref} />;
|
||||
});
|
||||
|
||||
export default IconButton;
|
||||
@@ -0,0 +1,13 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { Theme } from '@mui/material';
|
||||
import React from 'react';
|
||||
|
||||
import icon from './commonjs.svg';
|
||||
|
||||
const ImgIcon = styled.img<{ theme?: Theme }>(({ theme }) => ({
|
||||
marginLeft: theme?.spacing(1),
|
||||
}));
|
||||
|
||||
export function CommonJS() {
|
||||
return <ImgIcon alt="commonjs" height="20" src={icon} width="20" />;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { Theme } from '@mui/material';
|
||||
import React from 'react';
|
||||
|
||||
import icon from './es6modules.svg';
|
||||
|
||||
const ImgIcon = styled.img<{ theme?: Theme }>(({ theme }) => ({
|
||||
marginLeft: theme?.spacing(1),
|
||||
}));
|
||||
|
||||
export function ES6Modules() {
|
||||
return <ImgIcon alt="es6 modules" height="20" src={icon} width="20" />;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { Theme } from '@mui/material';
|
||||
import React from 'react';
|
||||
|
||||
import iconTS from './typescript.svg';
|
||||
|
||||
const ImgIcon = styled.img<{ theme?: Theme }>(({ theme }) => ({
|
||||
marginLeft: theme?.spacing(1),
|
||||
}));
|
||||
|
||||
export function TypeScript() {
|
||||
return <ImgIcon alt="typescript" height="20" src={iconTS} width="20" />;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 0H36V36H0V0Z" fill="#FFD102"/>
|
||||
<path d="M9.41113 21.7109H12.2588C12.2119 22.5898 11.9717 23.3662 11.5381 24.04C11.1104 24.708 10.5156 25.2324 9.75391 25.6133C8.99219 25.9883 8.08691 26.1758 7.03809 26.1758C6.2002 26.1758 5.4502 26.0322 4.78809 25.7451C4.12598 25.458 3.56348 25.0479 3.10059 24.5146C2.64355 23.9756 2.29199 23.3281 2.0459 22.5723C1.80566 21.8105 1.68555 20.9521 1.68555 19.9971V19.2148C1.68555 18.2598 1.81152 17.4014 2.06348 16.6396C2.31543 15.8779 2.67578 15.2275 3.14453 14.6885C3.61328 14.1494 4.17578 13.7363 4.83203 13.4492C5.48828 13.1621 6.2207 13.0186 7.0293 13.0186C8.11914 13.0186 9.03906 13.2148 9.78906 13.6074C10.5391 14 11.1191 14.5391 11.5293 15.2246C11.9453 15.9102 12.1943 16.6924 12.2764 17.5713H9.41992C9.39648 17.0732 9.30273 16.6543 9.13867 16.3145C8.97461 15.9688 8.72266 15.708 8.38281 15.5322C8.04297 15.3564 7.5918 15.2686 7.0293 15.2686C6.61914 15.2686 6.25879 15.3447 5.94824 15.4971C5.64355 15.6494 5.38867 15.8867 5.18359 16.209C4.98438 16.5312 4.83496 16.9414 4.73535 17.4395C4.63574 17.9316 4.58594 18.5176 4.58594 19.1973V19.9971C4.58594 20.6709 4.62988 21.2539 4.71777 21.7461C4.80566 22.2383 4.94629 22.6455 5.13965 22.9678C5.33887 23.29 5.59375 23.5303 5.9043 23.6885C6.21484 23.8467 6.59277 23.9258 7.03809 23.9258C7.54785 23.9258 7.97266 23.8467 8.3125 23.6885C8.65234 23.5244 8.91309 23.2783 9.09473 22.9502C9.27637 22.6221 9.38184 22.209 9.41113 21.7109ZM18.9912 22.0273V13.2031H21.8389V22.0273C21.8389 22.8828 21.6455 23.6211 21.2588 24.2422C20.8779 24.8574 20.3594 25.335 19.7031 25.6748C19.0527 26.0088 18.3174 26.1758 17.4971 26.1758C16.6533 26.1758 15.9033 26.0352 15.2471 25.7539C14.5908 25.4668 14.0752 25.0303 13.7002 24.4443C13.3311 23.8525 13.1465 23.0996 13.1465 22.1855H16.0117C16.0117 22.6367 16.0674 22.9941 16.1787 23.2578C16.2959 23.5156 16.4658 23.6973 16.6885 23.8027C16.9111 23.9082 17.1807 23.9609 17.4971 23.9609C17.8018 23.9609 18.0654 23.8877 18.2881 23.7412C18.5107 23.5889 18.6836 23.3691 18.8066 23.082C18.9297 22.7891 18.9912 22.4375 18.9912 22.0273ZM30.5752 22.625C30.5752 22.4082 30.543 22.2148 30.4785 22.0449C30.4141 21.8691 30.2969 21.708 30.127 21.5615C29.957 21.415 29.7168 21.2686 29.4062 21.1221C29.0957 20.9697 28.6885 20.8145 28.1846 20.6562C27.6104 20.4688 27.0625 20.2578 26.541 20.0234C26.0254 19.7832 25.5654 19.5049 25.1611 19.1885C24.7568 18.8721 24.4375 18.5029 24.2031 18.0811C23.9746 17.6592 23.8604 17.167 23.8604 16.6045C23.8604 16.0596 23.9805 15.5674 24.2207 15.1279C24.4609 14.6885 24.7979 14.3135 25.2314 14.0029C25.665 13.6865 26.1748 13.4463 26.7607 13.2822C27.3467 13.1123 27.9912 13.0273 28.6943 13.0273C29.6318 13.0273 30.4551 13.1943 31.1641 13.5283C31.8789 13.8564 32.4355 14.3193 32.834 14.917C33.2324 15.5088 33.4316 16.1973 33.4316 16.9824H30.584C30.584 16.6367 30.5107 16.332 30.3643 16.0684C30.2236 15.7988 30.0068 15.5879 29.7139 15.4355C29.4268 15.2832 29.0664 15.207 28.6328 15.207C28.2109 15.207 27.8564 15.2715 27.5693 15.4004C27.2881 15.5234 27.0742 15.6934 26.9277 15.9102C26.7871 16.127 26.7168 16.3643 26.7168 16.6221C26.7168 16.8271 26.7695 17.0146 26.875 17.1846C26.9863 17.3486 27.1445 17.5039 27.3496 17.6504C27.5605 17.791 27.8184 17.9258 28.123 18.0547C28.4277 18.1836 28.7764 18.3066 29.1689 18.4238C29.8545 18.6406 30.4609 18.8809 30.9883 19.1445C31.5215 19.4082 31.9697 19.707 32.333 20.041C32.6963 20.375 32.9688 20.7529 33.1504 21.1748C33.3379 21.5967 33.4316 22.0742 33.4316 22.6074C33.4316 23.1758 33.3203 23.6797 33.0977 24.1191C32.8809 24.5586 32.5645 24.9336 32.1484 25.2441C31.7383 25.5488 31.2461 25.7803 30.6719 25.9385C30.0977 26.0967 29.4561 26.1758 28.7471 26.1758C28.1025 26.1758 27.4668 26.0938 26.8398 25.9297C26.2129 25.7598 25.6445 25.502 25.1348 25.1562C24.6309 24.8105 24.2266 24.3711 23.9219 23.8379C23.623 23.2988 23.4736 22.6602 23.4736 21.9219H26.3389C26.3389 22.3086 26.3945 22.6367 26.5059 22.9062C26.6172 23.1699 26.7754 23.3838 26.9805 23.5479C27.1914 23.7119 27.4463 23.8291 27.7451 23.8994C28.0439 23.9697 28.3779 24.0049 28.7471 24.0049C29.1748 24.0049 29.5205 23.9463 29.7842 23.8291C30.0537 23.7061 30.2529 23.5391 30.3818 23.3281C30.5107 23.1172 30.5752 22.8828 30.5752 22.625Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.2 KiB |
@@ -0,0 +1,4 @@
|
||||
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 0H36V36H0V0Z" fill="#93C2DB"/>
|
||||
<path d="M11.7559 22.7852V25H4.94434V22.7852H11.7559ZM5.91992 12.2031V25H3.05469V12.2031H5.91992ZM10.877 17.3535V19.498H4.94434V17.3535H10.877ZM11.7646 12.2031V14.4268H4.94434V12.2031H11.7646ZM19.7979 21.625C19.7979 21.4082 19.7656 21.2148 19.7012 21.0449C19.6367 20.8691 19.5195 20.708 19.3496 20.5615C19.1797 20.415 18.9395 20.2686 18.6289 20.1221C18.3184 19.9697 17.9111 19.8145 17.4072 19.6562C16.833 19.4688 16.2852 19.2578 15.7637 19.0234C15.248 18.7832 14.7881 18.5049 14.3838 18.1885C13.9795 17.8721 13.6602 17.5029 13.4258 17.0811C13.1973 16.6592 13.083 16.167 13.083 15.6045C13.083 15.0596 13.2031 14.5674 13.4434 14.1279C13.6836 13.6885 14.0205 13.3135 14.4541 13.0029C14.8877 12.6865 15.3975 12.4463 15.9834 12.2822C16.5693 12.1123 17.2139 12.0273 17.917 12.0273C18.8545 12.0273 19.6777 12.1943 20.3867 12.5283C21.1016 12.8564 21.6582 13.3193 22.0566 13.917C22.4551 14.5088 22.6543 15.1973 22.6543 15.9824H19.8066C19.8066 15.6367 19.7334 15.332 19.5869 15.0684C19.4463 14.7988 19.2295 14.5879 18.9365 14.4355C18.6494 14.2832 18.2891 14.207 17.8555 14.207C17.4336 14.207 17.0791 14.2715 16.792 14.4004C16.5107 14.5234 16.2969 14.6934 16.1504 14.9102C16.0098 15.127 15.9395 15.3643 15.9395 15.6221C15.9395 15.8271 15.9922 16.0146 16.0977 16.1846C16.209 16.3486 16.3672 16.5039 16.5723 16.6504C16.7832 16.791 17.041 16.9258 17.3457 17.0547C17.6504 17.1836 17.999 17.3066 18.3916 17.4238C19.0771 17.6406 19.6836 17.8809 20.2109 18.1445C20.7441 18.4082 21.1924 18.707 21.5557 19.041C21.9189 19.375 22.1914 19.7529 22.373 20.1748C22.5605 20.5967 22.6543 21.0742 22.6543 21.6074C22.6543 22.1758 22.543 22.6797 22.3203 23.1191C22.1035 23.5586 21.7871 23.9336 21.3711 24.2441C20.9609 24.5488 20.4688 24.7803 19.8945 24.9385C19.3203 25.0967 18.6787 25.1758 17.9697 25.1758C17.3252 25.1758 16.6895 25.0938 16.0625 24.9297C15.4355 24.7598 14.8672 24.502 14.3574 24.1562C13.8535 23.8105 13.4492 23.3711 13.1445 22.8379C12.8457 22.2988 12.6963 21.6602 12.6963 20.9219H15.5615C15.5615 21.3086 15.6172 21.6367 15.7285 21.9062C15.8398 22.1699 15.998 22.3838 16.2031 22.5479C16.4141 22.7119 16.6689 22.8291 16.9678 22.8994C17.2666 22.9697 17.6006 23.0049 17.9697 23.0049C18.3975 23.0049 18.7432 22.9463 19.0068 22.8291C19.2764 22.7061 19.4756 22.5391 19.6045 22.3281C19.7334 22.1172 19.7979 21.8828 19.7979 21.625ZM30.7227 12.0449H31.1445V14.2246H30.9863C30.3711 14.2246 29.8086 14.3125 29.2988 14.4883C28.7949 14.6641 28.3584 14.9248 27.9893 15.2705C27.6201 15.6104 27.3359 16.0322 27.1367 16.5361C26.9434 17.0342 26.8467 17.6084 26.8467 18.2588V20.4385C26.8467 20.8779 26.8848 21.2617 26.9609 21.5898C27.043 21.9121 27.1602 22.1816 27.3125 22.3984C27.4707 22.6094 27.6611 22.7705 27.8838 22.8818C28.1064 22.9873 28.3584 23.04 28.6396 23.04C28.8916 23.04 29.123 22.9844 29.334 22.873C29.5449 22.7617 29.7266 22.6035 29.8789 22.3984C30.0312 22.1934 30.1484 21.9561 30.2305 21.6865C30.3125 21.4111 30.3535 21.1123 30.3535 20.79C30.3535 20.4502 30.3096 20.1426 30.2217 19.8672C30.1396 19.5859 30.0195 19.3457 29.8613 19.1465C29.709 18.9473 29.5215 18.7949 29.2988 18.6895C29.0762 18.5781 28.8301 18.5225 28.5605 18.5225C28.1738 18.5225 27.8398 18.6104 27.5586 18.7861C27.2773 18.9619 27.0605 19.1875 26.9082 19.4629C26.7559 19.7383 26.6768 20.0195 26.6709 20.3066L25.9414 19.7002C25.9414 19.3018 26.0205 18.9092 26.1787 18.5225C26.3428 18.1299 26.5742 17.7754 26.873 17.459C27.1719 17.1367 27.5381 16.8818 27.9717 16.6943C28.4111 16.501 28.9121 16.4043 29.4746 16.4043C30.0664 16.4043 30.5879 16.5186 31.0391 16.7471C31.4902 16.9697 31.8682 17.2803 32.1729 17.6787C32.4834 18.0771 32.7148 18.543 32.8672 19.0762C33.0254 19.6035 33.1045 20.1689 33.1045 20.7725C33.1045 21.3936 32.9961 21.9736 32.7793 22.5127C32.5684 23.0459 32.2695 23.5117 31.8828 23.9102C31.4961 24.3086 31.0332 24.6191 30.4941 24.8418C29.9609 25.0645 29.3662 25.1758 28.71 25.1758C28.0303 25.1758 27.4092 25.0557 26.8467 24.8154C26.29 24.5752 25.8037 24.2324 25.3877 23.7871C24.9775 23.3359 24.6582 22.7969 24.4297 22.1699C24.207 21.543 24.0957 20.8398 24.0957 20.0605V19.0322C24.0957 17.9658 24.2598 17.0049 24.5879 16.1494C24.9219 15.2939 25.3848 14.5615 25.9766 13.9521C26.5742 13.3369 27.2773 12.8652 28.0859 12.5371C28.8945 12.209 29.7734 12.0449 30.7227 12.0449Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.3 KiB |
@@ -0,0 +1,3 @@
|
||||
export { TypeScript } from './TypeScript';
|
||||
export { CommonJS } from './CommonJS';
|
||||
export { ES6Modules } from './ES6Module';
|
||||
@@ -0,0 +1,4 @@
|
||||
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 0H36V36H0V0Z" fill="#1976D2"/>
|
||||
<path d="M14.0137 12.2031V25H11.1572V12.2031H14.0137ZM17.9072 12.2031V14.4268H7.34277V12.2031H17.9072ZM23.374 25H20.5615L20.5791 22.7852H23.374C24.0127 22.7852 24.5518 22.6387 24.9912 22.3457C25.4307 22.0469 25.7646 21.6074 25.9932 21.0273C26.2217 20.4414 26.3359 19.7295 26.3359 18.8916V18.3027C26.3359 17.6699 26.2715 17.1133 26.1426 16.6328C26.0137 16.1465 25.8232 15.7393 25.5713 15.4111C25.3193 15.083 25.0059 14.8369 24.6309 14.6729C24.2617 14.5088 23.8369 14.4268 23.3564 14.4268H20.5088V12.2031H23.3564C24.2236 12.2031 25.0146 12.3496 25.7295 12.6426C26.4502 12.9355 27.0713 13.3545 27.5928 13.8994C28.1201 14.4443 28.5273 15.0889 28.8145 15.833C29.1016 16.5771 29.2451 17.4062 29.2451 18.3203V18.8916C29.2451 19.7998 29.1016 20.6289 28.8145 21.3789C28.5273 22.123 28.1201 22.7676 27.5928 23.3125C27.0713 23.8516 26.4531 24.2676 25.7383 24.5605C25.0234 24.8535 24.2354 25 23.374 25ZM22.1875 12.2031V25H19.3223V12.2031H22.1875Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -3,3 +3,4 @@ export { Time } from './Time';
|
||||
export { FileBinary } from './FileBinary';
|
||||
export { Law } from './Law';
|
||||
export { Earth } from './Earth';
|
||||
export * from './DevsIcons';
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
import { InputProps, default as MaterialUIInput } from '@mui/material/Input';
|
||||
import React, { forwardRef } from 'react';
|
||||
import { default as MaterialUIInput } from '@mui/material/Input';
|
||||
|
||||
type InputRef = HTMLDivElement;
|
||||
|
||||
const Input = forwardRef<InputRef, InputProps>(function Input(props, ref) {
|
||||
return <MaterialUIInput {...props} ref={ref} />;
|
||||
});
|
||||
|
||||
export default Input;
|
||||
export default MaterialUIInput;
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import {
|
||||
InputAdornmentProps,
|
||||
default as MaterialUIInputAdornment,
|
||||
} from '@mui/material/InputAdornment';
|
||||
import React, { forwardRef } from 'react';
|
||||
|
||||
type InputAdornmentRef = HTMLDivElement;
|
||||
|
||||
const InputAdornment = forwardRef<InputAdornmentRef, InputAdornmentProps>(function InputAdornment(
|
||||
props,
|
||||
ref
|
||||
) {
|
||||
return <MaterialUIInputAdornment {...props} ref={ref} />;
|
||||
});
|
||||
|
||||
export default InputAdornment;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user