Merge branch 'master' into portal-latest
This commit is contained in:
commit
3364282875
|
@ -3,48 +3,48 @@ updates:
|
|||
- package-ecosystem: npm
|
||||
directory: "/packages/dashboard"
|
||||
schedule:
|
||||
interval: weekly
|
||||
interval: monthly
|
||||
- package-ecosystem: npm
|
||||
directory: "/packages/dnslink-api"
|
||||
schedule:
|
||||
interval: weekly
|
||||
interval: monthly
|
||||
- package-ecosystem: npm
|
||||
directory: "/packages/handshake-api"
|
||||
schedule:
|
||||
interval: weekly
|
||||
interval: monthly
|
||||
- package-ecosystem: npm
|
||||
directory: "/packages/health-check"
|
||||
schedule:
|
||||
interval: weekly
|
||||
interval: monthly
|
||||
- package-ecosystem: npm
|
||||
directory: "/packages/website"
|
||||
schedule:
|
||||
interval: weekly
|
||||
interval: monthly
|
||||
- package-ecosystem: docker
|
||||
directory: "/docker/nginx"
|
||||
schedule:
|
||||
interval: weekly
|
||||
interval: monthly
|
||||
- package-ecosystem: docker
|
||||
directory: "/docker/sia"
|
||||
schedule:
|
||||
interval: weekly
|
||||
interval: monthly
|
||||
- package-ecosystem: docker
|
||||
directory: "/packages/dashboard"
|
||||
schedule:
|
||||
interval: weekly
|
||||
interval: monthly
|
||||
- package-ecosystem: docker
|
||||
directory: "/packages/dnslink-api"
|
||||
schedule:
|
||||
interval: weekly
|
||||
interval: monthly
|
||||
- package-ecosystem: docker
|
||||
directory: "/packages/handshake-api"
|
||||
schedule:
|
||||
interval: weekly
|
||||
interval: monthly
|
||||
- package-ecosystem: docker
|
||||
directory: "/packages/health-check"
|
||||
schedule:
|
||||
interval: weekly
|
||||
interval: monthly
|
||||
- package-ecosystem: docker
|
||||
directory: "/packages/website"
|
||||
schedule:
|
||||
interval: weekly
|
||||
interval: monthly
|
||||
|
|
|
@ -14,6 +14,7 @@ jobs:
|
|||
matrix:
|
||||
dockerfile:
|
||||
- docker/nginx/Dockerfile
|
||||
- docker/nginx/testing/Dockerfile
|
||||
- docker/sia/Dockerfile
|
||||
- packages/dashboard/Dockerfile
|
||||
- packages/dashboard-v2/Dockerfile
|
||||
|
|
|
@ -6,48 +6,41 @@ name: Nginx Lua Unit Tests
|
|||
on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- master
|
||||
paths:
|
||||
- ".github/workflows/nginx-lua-unit-tests.yml"
|
||||
- "docker/nginx/libs/**.lua"
|
||||
- docker/nginx/libs/**
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/nginx-lua-unit-tests.yml"
|
||||
- "docker/nginx/libs/**.lua"
|
||||
- docker/nginx/libs/**
|
||||
|
||||
jobs:
|
||||
build:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
container: openresty/openresty:1.19.9.1-focal
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: "3.x"
|
||||
architecture: "x64"
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
pip install hererocks
|
||||
hererocks env --lua=5.1 -rlatest
|
||||
source env/bin/activate
|
||||
luarocks install lua-resty-http
|
||||
luarocks install hasher
|
||||
luarocks install busted
|
||||
luarocks install luacov
|
||||
luarocks install hasher
|
||||
luarocks install luacheck
|
||||
|
||||
- name: Lint code
|
||||
run: |
|
||||
source env/bin/activate
|
||||
luacheck docker/nginx/libs --std ngx_lua+busted
|
||||
- name: Lint Code With Luacheck
|
||||
run: luacheck docker/nginx/libs --std ngx_lua+busted
|
||||
|
||||
- name: Unit Tests
|
||||
run: |
|
||||
source env/bin/activate
|
||||
busted --verbose --coverage --pattern=spec --directory=docker/nginx/libs .
|
||||
cd docker/nginx/libs && luacov
|
||||
- name: Run Tests With Busted
|
||||
# ran from root repo directory; produces luacov.stats.out file
|
||||
run: docker/nginx/testing/rbusted --lpath='docker/nginx/libs/?.lua;docker/nginx/libs/?/?.lua' --verbose --coverage --pattern=spec docker/nginx/libs
|
||||
|
||||
- uses: codecov/codecov-action@v2
|
||||
- name: Generate Code Coverage Report With Luacov
|
||||
# requires config file in cwd; produces luacov.report.out file
|
||||
run: cp docker/nginx/testing/.luacov . && luacov && rm .luacov
|
||||
|
||||
- uses: codecov/codecov-action@v3
|
||||
with:
|
||||
directory: docker/nginx/libs
|
||||
root_dir: ${GITHUB_WORKSPACE}
|
||||
files: ./luacov.report.out
|
||||
flags: nginx-lua
|
||||
|
|
|
@ -86,6 +86,10 @@ __pycache__
|
|||
/.idea/
|
||||
/venv*
|
||||
|
||||
# Luacov file
|
||||
luacov.stats.out
|
||||
luacov.report.out
|
||||
|
||||
# Setup-script log files
|
||||
setup-scripts/serverload.log
|
||||
setup-scripts/serverload.json
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
## Latest Setup Documentation
|
||||
|
||||
Latest Skynet Webportal setup documentation and the setup process Skynet Labs
|
||||
supports is located at https://docs.siasky.net/webportal-management/overview.
|
||||
supports is located at https://portal-docs.skynetlabs.com/.
|
||||
|
||||
Some scripts and setup documentation contained in this repository
|
||||
(`skynet-webportal`) may be outdated and generally should not be used.
|
||||
|
|
|
@ -10,7 +10,7 @@ services:
|
|||
abuse-scanner:
|
||||
# uncomment "build" and comment out "image" to build from sources
|
||||
# build: https://github.com/SkynetLabs/abuse-scanner.git#main
|
||||
image: skynetlabs/abuse-scanner
|
||||
image: skynetlabs/abuse-scanner:0.1.0
|
||||
container_name: abuse-scanner
|
||||
restart: unless-stopped
|
||||
logging: *default-logging
|
||||
|
|
|
@ -20,9 +20,11 @@ services:
|
|||
- ACCOUNTS_LIMIT_ACCESS=${ACCOUNTS_LIMIT_ACCESS:-authenticated} # default to authenticated access only
|
||||
|
||||
accounts:
|
||||
# uncomment "build" and comment out "image" to build from sources
|
||||
# build: https://github.com/SkynetLabs/skynet-accounts.git#main
|
||||
image: skynetlabs/skynet-accounts
|
||||
build:
|
||||
context: ./docker/accounts
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
branch: main
|
||||
container_name: accounts
|
||||
restart: unless-stopped
|
||||
logging: *default-logging
|
||||
|
@ -55,9 +57,11 @@ services:
|
|||
- mongo
|
||||
|
||||
dashboard:
|
||||
build:
|
||||
context: ./packages/dashboard
|
||||
dockerfile: Dockerfile
|
||||
# uncomment "build" and comment out "image" to build from sources
|
||||
# build:
|
||||
# context: https://github.com/SkynetLabs/skynet-webportal.git#master
|
||||
# dockerfile: ./packages/dashboard/Dockerfile
|
||||
image: skynetlabs/dashboard
|
||||
container_name: dashboard
|
||||
restart: unless-stopped
|
||||
logging: *default-logging
|
||||
|
@ -78,8 +82,8 @@ services:
|
|||
|
||||
dashboard-v2:
|
||||
build:
|
||||
context: ./packages/dashboard-v2
|
||||
dockerfile: Dockerfile
|
||||
context: .
|
||||
dockerfile: packages/dashboard-v2/Dockerfile
|
||||
container_name: dashboard-v2
|
||||
restart: unless-stopped
|
||||
logging: *default-logging
|
||||
|
|
|
@ -15,7 +15,7 @@ services:
|
|||
blocker:
|
||||
# uncomment "build" and comment out "image" to build from sources
|
||||
# build: https://github.com/SkynetLabs/blocker.git#main
|
||||
image: skynetlabs/blocker
|
||||
image: skynetlabs/blocker:0.1.0
|
||||
container_name: blocker
|
||||
restart: unless-stopped
|
||||
logging: *default-logging
|
||||
|
|
|
@ -28,7 +28,7 @@ services:
|
|||
malware-scanner:
|
||||
# uncomment "build" and comment out "image" to build from sources
|
||||
# build: https://github.com/SkynetLabs/malware-scanner.git#main
|
||||
image: skynetlabs/malware-scanner
|
||||
image: skynetlabs/malware-scanner:0.1.0
|
||||
container_name: malware-scanner
|
||||
restart: unless-stopped
|
||||
logging: *default-logging
|
||||
|
|
|
@ -54,9 +54,11 @@ services:
|
|||
- ./docker/data/certbot:/etc/letsencrypt
|
||||
|
||||
nginx:
|
||||
build:
|
||||
context: ./docker/nginx
|
||||
dockerfile: Dockerfile
|
||||
# uncomment "build" and comment out "image" to build from sources
|
||||
# build:
|
||||
# context: https://github.com/SkynetLabs/skynet-webportal.git#master
|
||||
# dockerfile: ./docker/nginx/Dockerfile
|
||||
image: skynetlabs/nginx
|
||||
container_name: nginx
|
||||
restart: unless-stopped
|
||||
logging: *default-logging
|
||||
|
@ -69,6 +71,10 @@ services:
|
|||
- ./docker/data/nginx/skynet:/data/nginx/skynet:ro
|
||||
- ./docker/data/sia/apipassword:/data/sia/apipassword:ro
|
||||
- ./docker/data/certbot:/etc/letsencrypt
|
||||
- ./docker/nginx/libs:/etc/nginx/libs
|
||||
- ./docker/nginx/conf.d:/etc/nginx/conf.d
|
||||
- ./docker/nginx/conf.d.templates:/etc/nginx/templates
|
||||
- ./docker/nginx/nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf
|
||||
networks:
|
||||
shared:
|
||||
ipv4_address: 10.10.10.30
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
FROM golang:1.16.7
|
||||
LABEL maintainer="SkynetLabs <devs@siasky.net>"
|
||||
|
||||
ENV GOOS linux
|
||||
ENV GOARCH amd64
|
||||
|
||||
ARG branch=main
|
||||
|
||||
WORKDIR /root
|
||||
|
||||
RUN git clone --single-branch --branch ${branch} https://github.com/SkynetLabs/skynet-accounts.git && \
|
||||
cd skynet-accounts && \
|
||||
go mod download && \
|
||||
make release
|
||||
|
||||
ENV SKYNET_DB_HOST="localhost"
|
||||
ENV SKYNET_DB_PORT="27017"
|
||||
ENV SKYNET_DB_USER="username"
|
||||
ENV SKYNET_DB_PASS="password"
|
||||
ENV SKYNET_ACCOUNTS_PORT=3000
|
||||
|
||||
ENTRYPOINT ["skynet-accounts"]
|
|
@ -2,25 +2,20 @@ FROM openresty/openresty:1.19.9.1-focal
|
|||
|
||||
WORKDIR /
|
||||
|
||||
RUN luarocks install lua-resty-http && \
|
||||
luarocks install hasher && \
|
||||
openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 \
|
||||
-subj '/CN=local-certificate' \
|
||||
-keyout /etc/ssl/local-certificate.key \
|
||||
-out /etc/ssl/local-certificate.crt
|
||||
RUN apt-get update && apt-get --no-install-recommends -y install bc=1.07.1-2build1 && \
|
||||
apt-get clean && rm -rf /var/lib/apt/lists/* && \
|
||||
luarocks install lua-resty-http && \
|
||||
luarocks install hasher
|
||||
|
||||
COPY mo ./
|
||||
COPY libs /etc/nginx/libs
|
||||
COPY conf.d /etc/nginx/conf.d
|
||||
COPY conf.d.templates /etc/nginx/conf.d.templates
|
||||
COPY nginx.conf /usr/local/openresty/nginx/conf/nginx.conf
|
||||
# reload nginx every 6 hours (for reloading certificates)
|
||||
ENV NGINX_ENTRYPOINT_RELOAD_EVERY_X_HOURS 6
|
||||
|
||||
CMD [ "bash", "-c", \
|
||||
"./mo < /etc/nginx/conf.d.templates/server.account.conf > /etc/nginx/conf.d/server.account.conf ; \
|
||||
./mo < /etc/nginx/conf.d.templates/server.api.conf > /etc/nginx/conf.d/server.api.conf; \
|
||||
./mo < /etc/nginx/conf.d.templates/server.dnslink.conf > /etc/nginx/conf.d/server.dnslink.conf; \
|
||||
./mo < /etc/nginx/conf.d.templates/server.hns.conf > /etc/nginx/conf.d/server.hns.conf; \
|
||||
./mo < /etc/nginx/conf.d.templates/server.skylink.conf > /etc/nginx/conf.d/server.skylink.conf ; \
|
||||
while :; do sleep 6h & wait ${!}; /usr/local/openresty/bin/openresty -s reload; done & \
|
||||
/usr/local/openresty/bin/openresty '-g daemon off;'" \
|
||||
]
|
||||
# copy entrypoint and entrypoint scripts
|
||||
COPY docker/nginx/docker-entrypoint.sh /
|
||||
COPY docker/nginx/docker-entrypoint.d /docker-entrypoint.d
|
||||
|
||||
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||
|
||||
STOPSIGNAL SIGQUIT
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
{{#ACCOUNTS_ENABLED}}
|
||||
{{#PORTAL_DOMAIN}}
|
||||
server {
|
||||
server_name account.{{PORTAL_DOMAIN}}; # example: account.siasky.net
|
||||
|
||||
include /etc/nginx/conf.d/server/server.http;
|
||||
}
|
||||
|
||||
server {
|
||||
server_name account.{{PORTAL_DOMAIN}}; # example: account.siasky.net
|
||||
|
||||
set_by_lua_block $skynet_portal_domain { return "{{PORTAL_DOMAIN}}" }
|
||||
set_by_lua_block $skynet_server_domain {
|
||||
-- fall back to portal domain if server domain is not defined
|
||||
if "{{SERVER_DOMAIN}}" == "" then
|
||||
return "{{PORTAL_DOMAIN}}"
|
||||
end
|
||||
return "{{SERVER_DOMAIN}}"
|
||||
}
|
||||
|
||||
include /etc/nginx/conf.d/server/server.account;
|
||||
}
|
||||
{{/PORTAL_DOMAIN}}
|
||||
|
||||
{{#SERVER_DOMAIN}}
|
||||
server {
|
||||
server_name account.{{SERVER_DOMAIN}}; # example: account.eu-ger-1.siasky.net
|
||||
|
||||
include /etc/nginx/conf.d/server/server.http;
|
||||
|
||||
set_by_lua_block $server_alias { return string.match("{{SERVER_DOMAIN}}", "^([^.]+)") }
|
||||
}
|
||||
|
||||
server {
|
||||
server_name account.{{SERVER_DOMAIN}}; # example: account.eu-ger-1.siasky.net
|
||||
|
||||
set_by_lua_block $skynet_portal_domain { return "{{SERVER_DOMAIN}}" }
|
||||
set_by_lua_block $skynet_server_domain { return "{{SERVER_DOMAIN}}" }
|
||||
|
||||
include /etc/nginx/conf.d/server/server.account;
|
||||
|
||||
set_by_lua_block $server_alias { return string.match("{{SERVER_DOMAIN}}", "^([^.]+)") }
|
||||
}
|
||||
{{/SERVER_DOMAIN}}
|
||||
{{/ACCOUNTS_ENABLED}}
|
|
@ -0,0 +1,44 @@
|
|||
server {
|
||||
server_name account.${PORTAL_DOMAIN}; # example: account.siasky.net
|
||||
|
||||
include /etc/nginx/conf.d/server/server.http;
|
||||
}
|
||||
|
||||
server {
|
||||
server_name account.${PORTAL_DOMAIN}; # example: account.siasky.net
|
||||
|
||||
set_by_lua_block $skynet_portal_domain { return "${PORTAL_DOMAIN}" }
|
||||
set_by_lua_block $skynet_server_domain {
|
||||
-- fall back to portal domain if server domain is not defined
|
||||
if "${SERVER_DOMAIN}" == "" then
|
||||
return "${PORTAL_DOMAIN}"
|
||||
end
|
||||
return "${SERVER_DOMAIN}"
|
||||
}
|
||||
|
||||
include /etc/nginx/conf.d/server/server.account;
|
||||
}
|
||||
|
||||
server {
|
||||
server_name account.${SERVER_DOMAIN}; # example: account.eu-ger-1.siasky.net
|
||||
|
||||
include /etc/nginx/conf.d/server/server.http;
|
||||
|
||||
set_by_lua_block $server_alias { return string.match("${SERVER_DOMAIN}", "^([^.]+)") }
|
||||
}
|
||||
|
||||
server {
|
||||
server_name account.${SERVER_DOMAIN}; # example: account.eu-ger-1.siasky.net
|
||||
|
||||
set_by_lua_block $skynet_portal_domain {
|
||||
-- when accessing portal directly through server domain, portal domain should be set to server domain
|
||||
-- motivation: skynet-js uses Skynet-Portal-Api header (that is set to $skynet_portal_domain) to detect current
|
||||
-- portal address and it should be server domain when accessing specific server by its domain address
|
||||
return "${SERVER_DOMAIN}"
|
||||
}
|
||||
set_by_lua_block $skynet_server_domain { return "${SERVER_DOMAIN}" }
|
||||
|
||||
include /etc/nginx/conf.d/server/server.account;
|
||||
|
||||
set_by_lua_block $server_alias { return string.match("${SERVER_DOMAIN}", "^([^.]+)") }
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
{{#PORTAL_DOMAIN}}
|
||||
server {
|
||||
server_name {{PORTAL_DOMAIN}}; # example: siasky.net
|
||||
|
||||
include /etc/nginx/conf.d/server/server.http;
|
||||
}
|
||||
|
||||
server {
|
||||
server_name {{PORTAL_DOMAIN}}; # example: siasky.net
|
||||
|
||||
set_by_lua_block $skynet_portal_domain { return "{{PORTAL_DOMAIN}}" }
|
||||
set_by_lua_block $skynet_server_domain {
|
||||
-- fall back to portal domain if server domain is not defined
|
||||
if "{{SERVER_DOMAIN}}" == "" then
|
||||
return "{{PORTAL_DOMAIN}}"
|
||||
end
|
||||
return "{{SERVER_DOMAIN}}"
|
||||
}
|
||||
|
||||
include /etc/nginx/conf.d/server/server.api;
|
||||
}
|
||||
{{/PORTAL_DOMAIN}}
|
||||
|
||||
{{#SERVER_DOMAIN}}
|
||||
server {
|
||||
server_name {{SERVER_DOMAIN}}; # example: eu-ger-1.siasky.net
|
||||
|
||||
include /etc/nginx/conf.d/server/server.http;
|
||||
|
||||
set_by_lua_block $server_alias { return string.match("{{SERVER_DOMAIN}}", "^([^.]+)") }
|
||||
}
|
||||
|
||||
server {
|
||||
server_name {{SERVER_DOMAIN}}; # example: eu-ger-1.siasky.net
|
||||
|
||||
set_by_lua_block $skynet_portal_domain { return "{{SERVER_DOMAIN}}" }
|
||||
set_by_lua_block $skynet_server_domain { return "{{SERVER_DOMAIN}}" }
|
||||
|
||||
include /etc/nginx/conf.d/server/server.api;
|
||||
|
||||
set_by_lua_block $server_alias { return string.match("{{SERVER_DOMAIN}}", "^([^.]+)") }
|
||||
}
|
||||
{{/SERVER_DOMAIN}}
|
|
@ -0,0 +1,44 @@
|
|||
server {
|
||||
server_name ${PORTAL_DOMAIN}; # example: siasky.net
|
||||
|
||||
include /etc/nginx/conf.d/server/server.http;
|
||||
}
|
||||
|
||||
server {
|
||||
server_name ${PORTAL_DOMAIN}; # example: siasky.net
|
||||
|
||||
set_by_lua_block $skynet_portal_domain { return "${PORTAL_DOMAIN}" }
|
||||
set_by_lua_block $skynet_server_domain {
|
||||
-- fall back to portal domain if server domain is not defined
|
||||
if "${SERVER_DOMAIN}" == "" then
|
||||
return "${PORTAL_DOMAIN}"
|
||||
end
|
||||
return "${SERVER_DOMAIN}"
|
||||
}
|
||||
|
||||
include /etc/nginx/conf.d/server/server.api;
|
||||
}
|
||||
|
||||
server {
|
||||
server_name ${SERVER_DOMAIN}; # example: eu-ger-1.siasky.net
|
||||
|
||||
include /etc/nginx/conf.d/server/server.http;
|
||||
|
||||
set_by_lua_block $server_alias { return string.match("${SERVER_DOMAIN}", "^([^.]+)") }
|
||||
}
|
||||
|
||||
server {
|
||||
server_name ${SERVER_DOMAIN}; # example: eu-ger-1.siasky.net
|
||||
|
||||
set_by_lua_block $skynet_portal_domain {
|
||||
-- when accessing portal directly through server domain, portal domain should be set to server domain
|
||||
-- motivation: skynet-js uses Skynet-Portal-Api header (that is set to $skynet_portal_domain) to detect current
|
||||
-- portal address and it should be server domain when accessing specific server by its domain address
|
||||
return "${SERVER_DOMAIN}"
|
||||
}
|
||||
set_by_lua_block $skynet_server_domain { return "${SERVER_DOMAIN}" }
|
||||
|
||||
include /etc/nginx/conf.d/server/server.api;
|
||||
|
||||
set_by_lua_block $server_alias { return string.match("${SERVER_DOMAIN}", "^([^.]+)") }
|
||||
}
|
|
@ -12,13 +12,13 @@ server {
|
|||
ssl_certificate /etc/ssl/local-certificate.crt;
|
||||
ssl_certificate_key /etc/ssl/local-certificate.key;
|
||||
|
||||
set_by_lua_block $skynet_portal_domain { return "{{PORTAL_DOMAIN}}" }
|
||||
set_by_lua_block $skynet_portal_domain { return "${PORTAL_DOMAIN}" }
|
||||
set_by_lua_block $skynet_server_domain {
|
||||
-- fall back to portal domain if server domain is not defined
|
||||
if "{{SERVER_DOMAIN}}" == "" then
|
||||
return "{{PORTAL_DOMAIN}}"
|
||||
if "${SERVER_DOMAIN}" == "" then
|
||||
return "${PORTAL_DOMAIN}"
|
||||
end
|
||||
return "{{SERVER_DOMAIN}}"
|
||||
return "${SERVER_DOMAIN}"
|
||||
}
|
||||
|
||||
include /etc/nginx/conf.d/server/server.dnslink;
|
|
@ -1,45 +0,0 @@
|
|||
{{#PORTAL_DOMAIN}}
|
||||
server {
|
||||
server_name *.hns.{{PORTAL_DOMAIN}}; # example: *.hns.siasky.net
|
||||
|
||||
include /etc/nginx/conf.d/server/server.http;
|
||||
}
|
||||
|
||||
server {
|
||||
server_name *.hns.{{PORTAL_DOMAIN}}; # example: *.hns.siasky.net
|
||||
|
||||
set_by_lua_block $skynet_portal_domain { return "{{PORTAL_DOMAIN}}" }
|
||||
set_by_lua_block $skynet_server_domain {
|
||||
-- fall back to portal domain if server domain is not defined
|
||||
if "{{SERVER_DOMAIN}}" == "" then
|
||||
return "{{PORTAL_DOMAIN}}"
|
||||
end
|
||||
return "{{SERVER_DOMAIN}}"
|
||||
}
|
||||
|
||||
proxy_set_header Host {{PORTAL_DOMAIN}};
|
||||
include /etc/nginx/conf.d/server/server.hns;
|
||||
}
|
||||
{{/PORTAL_DOMAIN}}
|
||||
|
||||
{{#SERVER_DOMAIN}}
|
||||
server {
|
||||
server_name *.hns.{{SERVER_DOMAIN}}; # example: *.hns.eu-ger-1.siasky.net
|
||||
|
||||
include /etc/nginx/conf.d/server/server.http;
|
||||
|
||||
set_by_lua_block $server_alias { return string.match("{{SERVER_DOMAIN}}", "^([^.]+)") }
|
||||
}
|
||||
|
||||
server {
|
||||
server_name *.hns.{{SERVER_DOMAIN}}; # example: *.hns.eu-ger-1.siasky.net
|
||||
|
||||
set_by_lua_block $skynet_portal_domain { return "{{SERVER_DOMAIN}}" }
|
||||
set_by_lua_block $skynet_server_domain { return "{{SERVER_DOMAIN}}" }
|
||||
|
||||
proxy_set_header Host {{SERVER_DOMAIN}};
|
||||
include /etc/nginx/conf.d/server/server.hns;
|
||||
|
||||
set_by_lua_block $server_alias { return string.match("{{SERVER_DOMAIN}}", "^([^.]+)") }
|
||||
}
|
||||
{{/SERVER_DOMAIN}}
|
|
@ -0,0 +1,46 @@
|
|||
server {
|
||||
server_name *.hns.${PORTAL_DOMAIN}; # example: *.hns.siasky.net
|
||||
|
||||
include /etc/nginx/conf.d/server/server.http;
|
||||
}
|
||||
|
||||
server {
|
||||
server_name *.hns.${PORTAL_DOMAIN}; # example: *.hns.siasky.net
|
||||
|
||||
set_by_lua_block $skynet_portal_domain { return "${PORTAL_DOMAIN}" }
|
||||
set_by_lua_block $skynet_server_domain {
|
||||
-- fall back to portal domain if server domain is not defined
|
||||
if "${SERVER_DOMAIN}" == "" then
|
||||
return "${PORTAL_DOMAIN}"
|
||||
end
|
||||
return "${SERVER_DOMAIN}"
|
||||
}
|
||||
|
||||
proxy_set_header Host ${PORTAL_DOMAIN};
|
||||
include /etc/nginx/conf.d/server/server.hns;
|
||||
}
|
||||
|
||||
server {
|
||||
server_name *.hns.${SERVER_DOMAIN}; # example: *.hns.eu-ger-1.siasky.net
|
||||
|
||||
include /etc/nginx/conf.d/server/server.http;
|
||||
|
||||
set_by_lua_block $server_alias { return string.match("${SERVER_DOMAIN}", "^([^.]+)") }
|
||||
}
|
||||
|
||||
server {
|
||||
server_name *.hns.${SERVER_DOMAIN}; # example: *.hns.eu-ger-1.siasky.net
|
||||
|
||||
set_by_lua_block $skynet_portal_domain {
|
||||
-- when accessing portal directly through server domain, portal domain should be set to server domain
|
||||
-- motivation: skynet-js uses Skynet-Portal-Api header (that is set to $skynet_portal_domain) to detect current
|
||||
-- portal address and it should be server domain when accessing specific server by its domain address
|
||||
return "${SERVER_DOMAIN}"
|
||||
}
|
||||
set_by_lua_block $skynet_server_domain { return "${SERVER_DOMAIN}" }
|
||||
|
||||
proxy_set_header Host ${SERVER_DOMAIN};
|
||||
include /etc/nginx/conf.d/server/server.hns;
|
||||
|
||||
set_by_lua_block $server_alias { return string.match("${SERVER_DOMAIN}", "^([^.]+)") }
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
{{#PORTAL_DOMAIN}}
|
||||
server {
|
||||
server_name *.{{PORTAL_DOMAIN}}; # example: *.siasky.net
|
||||
|
||||
include /etc/nginx/conf.d/server/server.http;
|
||||
}
|
||||
|
||||
server {
|
||||
server_name *.{{PORTAL_DOMAIN}}; # example: *.siasky.net
|
||||
|
||||
set_by_lua_block $skynet_portal_domain { return "{{PORTAL_DOMAIN}}" }
|
||||
set_by_lua_block $skynet_server_domain {
|
||||
-- fall back to portal domain if server domain is not defined
|
||||
if "{{SERVER_DOMAIN}}" == "" then
|
||||
return "{{PORTAL_DOMAIN}}"
|
||||
end
|
||||
return "{{SERVER_DOMAIN}}"
|
||||
}
|
||||
|
||||
include /etc/nginx/conf.d/server/server.skylink;
|
||||
}
|
||||
{{/PORTAL_DOMAIN}}
|
||||
|
||||
{{#SERVER_DOMAIN}}
|
||||
server {
|
||||
server_name *.{{SERVER_DOMAIN}}; # example: *.eu-ger-1.siasky.net
|
||||
|
||||
include /etc/nginx/conf.d/server/server.http;
|
||||
|
||||
set_by_lua_block $server_alias { return string.match("{{SERVER_DOMAIN}}", "^([^.]+)") }
|
||||
}
|
||||
|
||||
server {
|
||||
server_name *.{{SERVER_DOMAIN}}; # example: *.eu-ger-1.siasky.net
|
||||
|
||||
set_by_lua_block $skynet_portal_domain { return "{{SERVER_DOMAIN}}" }
|
||||
set_by_lua_block $skynet_server_domain { return "{{SERVER_DOMAIN}}" }
|
||||
|
||||
include /etc/nginx/conf.d/server/server.skylink;
|
||||
|
||||
set_by_lua_block $server_alias { return string.match("{{SERVER_DOMAIN}}", "^([^.]+)") }
|
||||
}
|
||||
{{/SERVER_DOMAIN}}
|
|
@ -0,0 +1,44 @@
|
|||
server {
|
||||
server_name *.${PORTAL_DOMAIN}; # example: *.siasky.net
|
||||
|
||||
include /etc/nginx/conf.d/server/server.http;
|
||||
}
|
||||
|
||||
server {
|
||||
server_name *.${PORTAL_DOMAIN}; # example: *.siasky.net
|
||||
|
||||
set_by_lua_block $skynet_portal_domain { return "${PORTAL_DOMAIN}" }
|
||||
set_by_lua_block $skynet_server_domain {
|
||||
-- fall back to portal domain if server domain is not defined
|
||||
if "${SERVER_DOMAIN}" == "" then
|
||||
return "${PORTAL_DOMAIN}"
|
||||
end
|
||||
return "${SERVER_DOMAIN}"
|
||||
}
|
||||
|
||||
include /etc/nginx/conf.d/server/server.skylink;
|
||||
}
|
||||
|
||||
server {
|
||||
server_name *.${SERVER_DOMAIN}; # example: *.eu-ger-1.siasky.net
|
||||
|
||||
include /etc/nginx/conf.d/server/server.http;
|
||||
|
||||
set_by_lua_block $server_alias { return string.match("${SERVER_DOMAIN}", "^([^.]+)") }
|
||||
}
|
||||
|
||||
server {
|
||||
server_name *.${SERVER_DOMAIN}; # example: *.eu-ger-1.siasky.net
|
||||
|
||||
set_by_lua_block $skynet_portal_domain {
|
||||
-- when accessing portal directly through server domain, portal domain should be set to server domain
|
||||
-- motivation: skynet-js uses Skynet-Portal-Api header (that is set to $skynet_portal_domain) to detect current
|
||||
-- portal address and it should be server domain when accessing specific server by its domain address
|
||||
return "${SERVER_DOMAIN}"
|
||||
}
|
||||
set_by_lua_block $skynet_server_domain { return "${SERVER_DOMAIN}" }
|
||||
|
||||
include /etc/nginx/conf.d/server/server.skylink;
|
||||
|
||||
set_by_lua_block $server_alias { return string.match("${SERVER_DOMAIN}", "^([^.]+)") }
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
include /etc/nginx/conf.d/include/cors;
|
||||
include /etc/nginx/conf.d/include/track-download;
|
||||
|
||||
limit_conn downloads_by_ip 100; # ddos protection: max 100 downloads at a time
|
||||
|
||||
|
@ -37,3 +36,18 @@ proxy_read_timeout 600;
|
|||
proxy_set_header User-Agent: Sia-Agent;
|
||||
|
||||
proxy_pass http://sia:9980/skynet/skylink/$skylink$path$is_args$args;
|
||||
|
||||
log_by_lua_block {
|
||||
local skynet_account = require("skynet.account")
|
||||
local skynet_modules = require("skynet.modules")
|
||||
local skynet_scanner = require("skynet.scanner")
|
||||
local skynet_tracker = require("skynet.tracker")
|
||||
|
||||
if skynet_modules.is_enabled("a") then
|
||||
skynet_tracker.track_download(ngx.header["Skynet-Skylink"], ngx.status, skynet_account.get_auth_headers(), ngx.var.body_bytes_sent)
|
||||
end
|
||||
|
||||
if skynet_modules.is_enabled("s") then
|
||||
skynet_scanner.scan_skylink(ngx.header["Skynet-Skylink"])
|
||||
end
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
include /etc/nginx/conf.d/include/cors;
|
||||
include /etc/nginx/conf.d/include/sia-auth;
|
||||
include /etc/nginx/conf.d/include/track-registry;
|
||||
|
||||
limit_req zone=registry_access_by_ip burst=600 nodelay;
|
||||
limit_req zone=registry_access_by_ip_throttled burst=200 nodelay;
|
||||
|
@ -30,3 +29,10 @@ access_by_lua_block {
|
|||
end
|
||||
end
|
||||
}
|
||||
|
||||
log_by_lua_block {
|
||||
local skynet_account = require("skynet.account")
|
||||
local skynet_tracker = require("skynet.tracker")
|
||||
|
||||
skynet_tracker.track_registry(ngx.status, skynet_account.get_auth_headers(), ngx.req.get_method())
|
||||
}
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
log_by_lua_block {
|
||||
local skynet_account = require("skynet.account")
|
||||
|
||||
-- tracking runs only when request comes from authenticated user
|
||||
if skynet_account.is_authenticated() then
|
||||
local function track(premature, skylink, status, body_bytes_sent, auth_headers)
|
||||
if premature then return end
|
||||
|
||||
local httpc = require("resty.http").new()
|
||||
local query = table.concat({ "status=" .. status, "bytes=" .. body_bytes_sent }, "&")
|
||||
|
||||
-- 10.10.10.70 points to accounts service (alias not available when using resty-http)
|
||||
local res, err = httpc:request_uri("http://10.10.10.70:3000/track/download/" .. skylink .. "?" .. query, {
|
||||
method = "POST",
|
||||
headers = auth_headers,
|
||||
})
|
||||
|
||||
if err or (res and res.status ~= ngx.HTTP_NO_CONTENT) then
|
||||
local error_response = err or ("[HTTP " .. res.status .. "] " .. res.body)
|
||||
ngx.log(ngx.ERR, "Failed accounts service request /track/download/" .. skylink .. ": ", error_response)
|
||||
end
|
||||
end
|
||||
|
||||
if ngx.header["Skynet-Skylink"] and ngx.status >= ngx.HTTP_OK and ngx.status < ngx.HTTP_SPECIAL_RESPONSE then
|
||||
local auth_headers = skynet_account.get_auth_headers()
|
||||
local ok, err = ngx.timer.at(0, track, ngx.header["Skynet-Skylink"], ngx.status, ngx.var.body_bytes_sent, auth_headers)
|
||||
if err then ngx.log(ngx.ERR, "Failed to create timer: ", err) end
|
||||
end
|
||||
end
|
||||
|
||||
-- this block runs only when scanner module is enabled
|
||||
if os.getenv("PORTAL_MODULES"):match("s") then
|
||||
local function scan(premature, skylink)
|
||||
if premature then return end
|
||||
|
||||
local httpc = require("resty.http").new()
|
||||
|
||||
-- 10.10.10.101 points to malware-scanner service (alias not available when using resty-http)
|
||||
local res, err = httpc:request_uri("http://10.10.10.101:4000/scan/" .. skylink, {
|
||||
method = "POST",
|
||||
})
|
||||
|
||||
if err or (res and res.status ~= ngx.HTTP_OK) then
|
||||
local error_response = err or ("[HTTP " .. res.status .. "] " .. res.body)
|
||||
ngx.log(ngx.ERR, "Failed malware-scanner request /scan/" .. skylink .. ": ", error_response)
|
||||
end
|
||||
end
|
||||
|
||||
-- scan all skylinks but make sure to only run if skylink is present (empty if request failed)
|
||||
if ngx.header["Skynet-Skylink"] then
|
||||
local ok, err = ngx.timer.at(0, scan, ngx.header["Skynet-Skylink"])
|
||||
if err then ngx.log(ngx.ERR, "Failed to create timer: ", err) end
|
||||
end
|
||||
end
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
log_by_lua_block {
|
||||
local skynet_account = require("skynet.account")
|
||||
|
||||
-- tracking runs only when request comes from authenticated user
|
||||
if skynet_account.is_authenticated() then
|
||||
local function track(premature, request_method, auth_headers)
|
||||
if premature then return end
|
||||
|
||||
local httpc = require("resty.http").new()
|
||||
|
||||
-- based on request method we assign a registry action string used
|
||||
-- in track endpoint namely "read" for GET and "write" for POST
|
||||
local registry_action = request_method == "GET" and "read" or "write"
|
||||
|
||||
-- 10.10.10.70 points to accounts service (alias not available when using resty-http)
|
||||
local res, err = httpc:request_uri("http://10.10.10.70:3000/track/registry/" .. registry_action, {
|
||||
method = "POST",
|
||||
headers = auth_headers,
|
||||
})
|
||||
|
||||
if err or (res and res.status ~= ngx.HTTP_NO_CONTENT) then
|
||||
local error_response = err or ("[HTTP " .. res.status .. "] " .. res.body)
|
||||
ngx.log(ngx.ERR, "Failed accounts service request /track/registry/" .. registry_action .. ": ", error_response)
|
||||
end
|
||||
end
|
||||
|
||||
if ngx.status == ngx.HTTP_OK or ngx.status == ngx.HTTP_NOT_FOUND then
|
||||
local auth_headers = skynet_account.get_auth_headers()
|
||||
local ok, err = ngx.timer.at(0, track, ngx.req.get_method(), auth_headers)
|
||||
if err then ngx.log(ngx.ERR, "Failed to create timer: ", err) end
|
||||
end
|
||||
end
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
log_by_lua_block {
|
||||
local skynet_account = require("skynet.account")
|
||||
|
||||
-- tracking runs only when request comes from authenticated user
|
||||
if skynet_account.is_authenticated() then
|
||||
local function track(premature, skylink, auth_headers)
|
||||
if premature then return end
|
||||
|
||||
local httpc = require("resty.http").new()
|
||||
|
||||
-- 10.10.10.70 points to accounts service (alias not available when using resty-http)
|
||||
local res, err = httpc:request_uri("http://10.10.10.70:3000/track/upload/" .. skylink, {
|
||||
method = "POST",
|
||||
headers = auth_headers,
|
||||
})
|
||||
|
||||
if err or (res and res.status ~= ngx.HTTP_NO_CONTENT) then
|
||||
local error_response = err or ("[HTTP " .. res.status .. "] " .. res.body)
|
||||
ngx.log(ngx.ERR, "Failed accounts service request /track/upload/" .. skylink .. ": ", error_response)
|
||||
end
|
||||
end
|
||||
|
||||
-- report all skylinks (header empty if request failed) but only if jwt is preset (user is authenticated)
|
||||
if ngx.header["Skynet-Skylink"] then
|
||||
local auth_headers = skynet_account.get_auth_headers()
|
||||
local ok, err = ngx.timer.at(0, track, ngx.header["Skynet-Skylink"], auth_headers)
|
||||
if err then ngx.log(ngx.ERR, "Failed to create timer: ", err) end
|
||||
end
|
||||
end
|
||||
|
||||
-- this block runs only when scanner module is enabled
|
||||
if os.getenv("PORTAL_MODULES"):match("s") then
|
||||
local function scan(premature, skylink)
|
||||
if premature then return end
|
||||
|
||||
local httpc = require("resty.http").new()
|
||||
|
||||
-- 10.10.10.101 points to malware-scanner service (alias not available when using resty-http)
|
||||
local res, err = httpc:request_uri("http://10.10.10.101:4000/scan/" .. skylink, {
|
||||
method = "POST",
|
||||
})
|
||||
|
||||
if err or (res and res.status ~= ngx.HTTP_OK) then
|
||||
local error_response = err or ("[HTTP " .. res.status .. "] " .. res.body)
|
||||
ngx.log(ngx.ERR, "Failed malware-scanner request /scan/" .. skylink .. ": ", error_response)
|
||||
end
|
||||
end
|
||||
|
||||
-- scan all skylinks but make sure to only run if skylink is present (empty if request failed)
|
||||
if ngx.header["Skynet-Skylink"] then
|
||||
local ok, err = ngx.timer.at(0, scan, ngx.header["Skynet-Skylink"])
|
||||
if err then ngx.log(ngx.ERR, "Failed to create timer: ", err) end
|
||||
end
|
||||
end
|
||||
}
|
|
@ -3,6 +3,11 @@ listen 443 ssl http2;
|
|||
include /etc/nginx/conf.d/include/ssl-settings;
|
||||
include /etc/nginx/conf.d/include/init-optional-variables;
|
||||
|
||||
# Uncomment to launch new Dashboard under /v2 path
|
||||
# location /v2 {
|
||||
# proxy_pass http://dashboard-v2:9000;
|
||||
# }
|
||||
|
||||
location / {
|
||||
proxy_pass http://dashboard:3000;
|
||||
}
|
||||
|
|
|
@ -206,7 +206,6 @@ location /skynet/registry/subscription {
|
|||
location /skynet/skyfile {
|
||||
include /etc/nginx/conf.d/include/cors;
|
||||
include /etc/nginx/conf.d/include/sia-auth;
|
||||
include /etc/nginx/conf.d/include/track-upload;
|
||||
include /etc/nginx/conf.d/include/generate-siapath;
|
||||
include /etc/nginx/conf.d/include/portal-access-check;
|
||||
|
||||
|
@ -228,12 +227,26 @@ location /skynet/skyfile {
|
|||
|
||||
# proxy this call to siad endpoint (make sure the ip is correct)
|
||||
proxy_pass http://sia:9980/skynet/skyfile/$dir1/$dir2/$dir3$is_args$args;
|
||||
|
||||
log_by_lua_block {
|
||||
local skynet_account = require("skynet.account")
|
||||
local skynet_modules = require("skynet.modules")
|
||||
local skynet_scanner = require("skynet.scanner")
|
||||
local skynet_tracker = require("skynet.tracker")
|
||||
|
||||
if skynet_modules.is_enabled("a") then
|
||||
skynet_tracker.track_upload(ngx.header["Skynet-Skylink"], ngx.status, skynet_account.get_auth_headers())
|
||||
end
|
||||
|
||||
if skynet_modules.is_enabled("s") then
|
||||
skynet_scanner.scan_skylink(ngx.header["Skynet-Skylink"])
|
||||
end
|
||||
}
|
||||
}
|
||||
|
||||
# endpoint implementing resumable file uploads open protocol https://tus.io
|
||||
location /skynet/tus {
|
||||
include /etc/nginx/conf.d/include/cors-headers; # include cors headers but do not overwrite OPTIONS response
|
||||
include /etc/nginx/conf.d/include/track-upload;
|
||||
|
||||
limit_req zone=uploads_by_ip burst=10 nodelay;
|
||||
limit_req zone=uploads_by_ip_throttled;
|
||||
|
@ -294,12 +307,26 @@ location /skynet/tus {
|
|||
end
|
||||
end
|
||||
}
|
||||
|
||||
log_by_lua_block {
|
||||
local skynet_account = require("skynet.account")
|
||||
local skynet_modules = require("skynet.modules")
|
||||
local skynet_scanner = require("skynet.scanner")
|
||||
local skynet_tracker = require("skynet.tracker")
|
||||
|
||||
if skynet_modules.is_enabled("a") then
|
||||
skynet_tracker.track_upload(ngx.header["Skynet-Skylink"], ngx.status, skynet_account.get_auth_headers())
|
||||
end
|
||||
|
||||
if skynet_modules.is_enabled("s") then
|
||||
skynet_scanner.scan_skylink(ngx.header["Skynet-Skylink"])
|
||||
end
|
||||
}
|
||||
}
|
||||
|
||||
location /skynet/pin {
|
||||
include /etc/nginx/conf.d/include/cors;
|
||||
include /etc/nginx/conf.d/include/sia-auth;
|
||||
include /etc/nginx/conf.d/include/track-upload;
|
||||
include /etc/nginx/conf.d/include/generate-siapath;
|
||||
include /etc/nginx/conf.d/include/portal-access-check;
|
||||
|
||||
|
@ -311,6 +338,21 @@ location /skynet/pin {
|
|||
|
||||
proxy_set_header User-Agent: Sia-Agent;
|
||||
proxy_pass http://sia:9980$uri?siapath=$dir1/$dir2/$dir3&$args;
|
||||
|
||||
log_by_lua_block {
|
||||
local skynet_account = require("skynet.account")
|
||||
local skynet_modules = require("skynet.modules")
|
||||
local skynet_scanner = require("skynet.scanner")
|
||||
local skynet_tracker = require("skynet.tracker")
|
||||
|
||||
if skynet_modules.is_enabled("a") then
|
||||
skynet_tracker.track_upload(ngx.header["Skynet-Skylink"], ngx.status, skynet_account.get_auth_headers())
|
||||
end
|
||||
|
||||
if skynet_modules.is_enabled("s") then
|
||||
skynet_scanner.scan_skylink(ngx.header["Skynet-Skylink"])
|
||||
end
|
||||
}
|
||||
}
|
||||
|
||||
location /skynet/metadata {
|
||||
|
@ -357,7 +399,6 @@ location ~ "^/file/(([a-zA-Z0-9-_]{46}|[a-z0-9]{55})(/.*)?)$" {
|
|||
|
||||
location /skynet/trustless/basesector {
|
||||
include /etc/nginx/conf.d/include/cors;
|
||||
include /etc/nginx/conf.d/include/track-download;
|
||||
|
||||
limit_conn downloads_by_ip 100; # ddos protection: max 100 downloads at a time
|
||||
|
||||
|
@ -391,6 +432,21 @@ location /skynet/trustless/basesector {
|
|||
|
||||
proxy_set_header User-Agent: Sia-Agent;
|
||||
proxy_pass http://sia:9980;
|
||||
|
||||
log_by_lua_block {
|
||||
local skynet_account = require("skynet.account")
|
||||
local skynet_modules = require("skynet.modules")
|
||||
local skynet_scanner = require("skynet.scanner")
|
||||
local skynet_tracker = require("skynet.tracker")
|
||||
|
||||
if skynet_modules.is_enabled("a") then
|
||||
skynet_tracker.track_download(ngx.header["Skynet-Skylink"], ngx.status, skynet_account.get_auth_headers(), ngx.var.body_bytes_sent)
|
||||
end
|
||||
|
||||
if skynet_modules.is_enabled("s") then
|
||||
skynet_scanner.scan_skylink(ngx.header["Skynet-Skylink"])
|
||||
end
|
||||
}
|
||||
}
|
||||
|
||||
location /__internal/do/not/use/accounts {
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
#!/bin/sh
|
||||
|
||||
# https://github.com/nginxinc/docker-nginx/blob/master/entrypoint/20-envsubst-on-templates.sh
|
||||
# https://github.com/nginxinc/docker-nginx/blob/master/LICENSE
|
||||
|
||||
# Copyright (C) 2011-2016 Nginx, Inc.
|
||||
# All rights reserved.
|
||||
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
|
||||
set -e
|
||||
|
||||
ME=$(basename $0)
|
||||
|
||||
auto_envsubst() {
|
||||
local template_dir="${NGINX_ENVSUBST_TEMPLATE_DIR:-/etc/nginx/templates}"
|
||||
local suffix="${NGINX_ENVSUBST_TEMPLATE_SUFFIX:-.template}"
|
||||
local output_dir="${NGINX_ENVSUBST_OUTPUT_DIR:-/etc/nginx/conf.d}"
|
||||
|
||||
local template defined_envs relative_path output_path subdir
|
||||
defined_envs=$(printf '${%s} ' $(env | cut -d= -f1))
|
||||
[ -d "$template_dir" ] || return 0
|
||||
if [ ! -w "$output_dir" ]; then
|
||||
echo >&3 "$ME: ERROR: $template_dir exists, but $output_dir is not writable"
|
||||
return 0
|
||||
fi
|
||||
find "$template_dir" -follow -type f -name "*$suffix" -print | while read -r template; do
|
||||
relative_path="${template#$template_dir/}"
|
||||
output_path="$output_dir/${relative_path%$suffix}"
|
||||
subdir=$(dirname "$relative_path")
|
||||
# create a subdirectory where the template file exists
|
||||
mkdir -p "$output_dir/$subdir"
|
||||
echo >&3 "$ME: Running envsubst on $template to $output_path"
|
||||
envsubst "$defined_envs" < "$template" > "$output_path"
|
||||
done
|
||||
}
|
||||
|
||||
auto_envsubst
|
||||
|
||||
exit 0
|
|
@ -0,0 +1,20 @@
|
|||
#!/bin/sh
|
||||
|
||||
# source: https://github.com/nginxinc/docker-nginx/pull/509
|
||||
|
||||
set -e
|
||||
|
||||
ME=$(basename $0)
|
||||
|
||||
[ "${NGINX_ENTRYPOINT_RELOAD_EVERY_X_HOURS:-}" ] || exit 0
|
||||
if [ $(echo "$NGINX_ENTRYPOINT_RELOAD_EVERY_X_HOURS > 0" | bc) = 0 ]; then
|
||||
echo >&3 "$ME: Error. Provide integer or floating point number greater that 0. See 'man sleep'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
start_background_reload() {
|
||||
echo >&3 "$ME: Reloading Nginx every $NGINX_ENTRYPOINT_RELOAD_EVERY_X_HOURS hour(s)"
|
||||
while :; do sleep ${NGINX_ENTRYPOINT_RELOAD_EVERY_X_HOURS}h; echo >&3 "$ME: Reloading Nginx ..." && nginx -s reload; done &
|
||||
}
|
||||
|
||||
start_background_reload
|
|
@ -0,0 +1,18 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Generate locally signed ssl certificate to be used on routes
|
||||
# that do not require certificate issued by trusted CA
|
||||
|
||||
set -e
|
||||
|
||||
ME=$(basename $0)
|
||||
|
||||
generate_local_certificate() {
|
||||
echo >&3 "$ME: Generating locally signed ssl certificate"
|
||||
openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 \
|
||||
-subj '/CN=local-certificate' \
|
||||
-keyout /etc/ssl/local-certificate.key \
|
||||
-out /etc/ssl/local-certificate.crt
|
||||
}
|
||||
|
||||
generate_local_certificate
|
|
@ -0,0 +1,65 @@
|
|||
#!/bin/sh
|
||||
# vim:sw=4:ts=4:et
|
||||
|
||||
# https://github.com/nginxinc/docker-nginx/blob/master/entrypoint/docker-entrypoint.sh
|
||||
# https://github.com/nginxinc/docker-nginx/blob/master/LICENSE
|
||||
|
||||
# Copyright (C) 2011-2016 Nginx, Inc.
|
||||
# All rights reserved.
|
||||
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
|
||||
set -e
|
||||
|
||||
if [ -z "${NGINX_ENTRYPOINT_QUIET_LOGS:-}" ]; then
|
||||
exec 3>&1
|
||||
else
|
||||
exec 3>/dev/null
|
||||
fi
|
||||
|
||||
if [ "$1" = "nginx" -o "$1" = "nginx-debug" ]; then
|
||||
if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then
|
||||
echo >&3 "$0: /docker-entrypoint.d/ is not empty, will attempt to perform configuration"
|
||||
|
||||
echo >&3 "$0: Looking for shell scripts in /docker-entrypoint.d/"
|
||||
find "/docker-entrypoint.d/" -follow -type f -print | sort -V | while read -r f; do
|
||||
case "$f" in
|
||||
*.sh)
|
||||
if [ -x "$f" ]; then
|
||||
echo >&3 "$0: Launching $f";
|
||||
"$f"
|
||||
else
|
||||
# warn on shell scripts without exec bit
|
||||
echo >&3 "$0: Ignoring $f, not executable";
|
||||
fi
|
||||
;;
|
||||
*) echo >&3 "$0: Ignoring $f";;
|
||||
esac
|
||||
done
|
||||
|
||||
echo >&3 "$0: Configuration complete; ready for start up"
|
||||
else
|
||||
echo >&3 "$0: No files found in /docker-entrypoint.d/, skipping configuration"
|
||||
fi
|
||||
fi
|
||||
|
||||
exec "$@"
|
|
@ -59,7 +59,9 @@ function _M.exit_access_forbidden(message)
|
|||
end
|
||||
|
||||
function _M.accounts_enabled()
|
||||
return os.getenv("PORTAL_MODULES"):match("a") ~= nil
|
||||
local skynet_modules = require("skynet.modules")
|
||||
|
||||
return skynet_modules.is_enabled("a")
|
||||
end
|
||||
|
||||
function _M.get_account_limits()
|
||||
|
@ -74,9 +76,16 @@ function _M.get_account_limits()
|
|||
|
||||
if ngx.var.account_limits == "" then
|
||||
local httpc = require("resty.http").new()
|
||||
local uri = "http://10.10.10.70:3000/user/limits"
|
||||
|
||||
-- include skylink if it is available in the context of request
|
||||
-- todo: this should not rely on skylink variable to be defined
|
||||
if ngx.var.skylink ~= nil and ngx.var.skylink ~= "" then
|
||||
uri = uri .. "/" .. ngx.var.skylink
|
||||
end
|
||||
|
||||
-- 10.10.10.70 points to accounts service (alias not available when using resty-http)
|
||||
local res, err = httpc:request_uri("http://10.10.10.70:3000/user/limits?unit=byte", {
|
||||
local res, err = httpc:request_uri(uri .. "?unit=byte", {
|
||||
headers = auth_headers,
|
||||
})
|
||||
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
local _M = {}
|
||||
|
||||
local utils = require("utils")
|
||||
|
||||
function _M.is_enabled(module_abbr)
|
||||
if type(module_abbr) ~= "string" or module_abbr:len() ~= 1 then
|
||||
error("Module abbreviation '" .. tostring(module_abbr) .. "' should be exactly one character long string")
|
||||
end
|
||||
|
||||
local enabled_modules = utils.getenv("PORTAL_MODULES")
|
||||
|
||||
if not enabled_modules then
|
||||
return false
|
||||
end
|
||||
|
||||
return enabled_modules:find(module_abbr) ~= nil
|
||||
end
|
||||
|
||||
function _M.is_disabled(module_abbr)
|
||||
return not _M.is_enabled(module_abbr)
|
||||
end
|
||||
|
||||
return _M
|
|
@ -0,0 +1,95 @@
|
|||
-- luacheck: ignore os
|
||||
|
||||
local skynet_modules = require("skynet.modules")
|
||||
|
||||
describe("is_enabled", function()
|
||||
before_each(function()
|
||||
stub(os, "getenv")
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
os.getenv:revert()
|
||||
end)
|
||||
|
||||
it("should return false if PORTAL_MODULES are not defined", function()
|
||||
os.getenv.on_call_with("PORTAL_MODULES").returns(nil)
|
||||
|
||||
assert.is_false(skynet_modules.is_enabled("a"))
|
||||
end)
|
||||
|
||||
it("should return false if PORTAL_MODULES are empty", function()
|
||||
os.getenv.on_call_with("PORTAL_MODULES").returns("")
|
||||
|
||||
assert.is_false(skynet_modules.is_enabled("a"))
|
||||
end)
|
||||
|
||||
it("should return false if module is not enabled", function()
|
||||
os.getenv.on_call_with("PORTAL_MODULES").returns("qwerty")
|
||||
|
||||
assert.is_false(skynet_modules.is_enabled("a"))
|
||||
end)
|
||||
|
||||
it("should return true if module is enabled", function()
|
||||
os.getenv.on_call_with("PORTAL_MODULES").returns("asdfg")
|
||||
|
||||
assert.is_true(skynet_modules.is_enabled("a"))
|
||||
end)
|
||||
|
||||
it("should throw an error for empty module", function()
|
||||
assert.has_error(function()
|
||||
skynet_modules.is_enabled()
|
||||
end, "Module abbreviation 'nil' should be exactly one character long string")
|
||||
end)
|
||||
|
||||
it("should throw an error for too long module", function()
|
||||
assert.has_error(function()
|
||||
skynet_modules.is_enabled("gandalf")
|
||||
end, "Module abbreviation 'gandalf' should be exactly one character long string")
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("is_disabled", function()
|
||||
before_each(function()
|
||||
stub(os, "getenv")
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
os.getenv:revert()
|
||||
end)
|
||||
|
||||
it("should return true if PORTAL_MODULES are not defined", function()
|
||||
os.getenv.on_call_with("PORTAL_MODULES").returns(nil)
|
||||
|
||||
assert.is_true(skynet_modules.is_disabled("a"))
|
||||
end)
|
||||
|
||||
it("should return true if PORTAL_MODULES are empty", function()
|
||||
os.getenv.on_call_with("PORTAL_MODULES").returns("")
|
||||
|
||||
assert.is_true(skynet_modules.is_disabled("a"))
|
||||
end)
|
||||
|
||||
it("should return true if module is not enabled", function()
|
||||
os.getenv.on_call_with("PORTAL_MODULES").returns("qwerty")
|
||||
|
||||
assert.is_true(skynet_modules.is_disabled("a"))
|
||||
end)
|
||||
|
||||
it("should return false if module is enabled", function()
|
||||
os.getenv.on_call_with("PORTAL_MODULES").returns("asdfg")
|
||||
|
||||
assert.is_false(skynet_modules.is_disabled("a"))
|
||||
end)
|
||||
|
||||
it("should throw an error for empty module", function()
|
||||
assert.has_error(function()
|
||||
skynet_modules.is_disabled()
|
||||
end, "Module abbreviation 'nil' should be exactly one character long string")
|
||||
end)
|
||||
|
||||
it("should throw an error for too long module", function()
|
||||
assert.has_error(function()
|
||||
skynet_modules.is_disabled("gandalf")
|
||||
end, "Module abbreviation 'gandalf' should be exactly one character long string")
|
||||
end)
|
||||
end)
|
|
@ -0,0 +1,26 @@
|
|||
local _M = {}
|
||||
|
||||
function _M.scan_skylink_timer(premature, skylink)
|
||||
if premature then return end
|
||||
|
||||
local httpc = require("resty.http").new()
|
||||
|
||||
-- 10.10.10.101 points to malware-scanner service (alias not available when using resty-http)
|
||||
local res, err = httpc:request_uri("http://10.10.10.101:4000/scan/" .. skylink, {
|
||||
method = "POST",
|
||||
})
|
||||
|
||||
if err or (res and res.status ~= ngx.HTTP_OK) then
|
||||
local error_response = err or ("[HTTP " .. res.status .. "] " .. res.body)
|
||||
ngx.log(ngx.ERR, "Failed malware-scanner request /scan/" .. skylink .. ": ", error_response)
|
||||
end
|
||||
end
|
||||
|
||||
function _M.scan_skylink(skylink)
|
||||
if not skylink then return end
|
||||
|
||||
local ok, err = ngx.timer.at(0, _M.scan_skylink_timer, skylink)
|
||||
if not ok then ngx.log(ngx.ERR, "Failed to create timer: ", err) end
|
||||
end
|
||||
|
||||
return _M
|
|
@ -0,0 +1,119 @@
|
|||
-- luacheck: ignore ngx
|
||||
|
||||
local skynet_scanner = require("skynet.scanner")
|
||||
local skylink = "AQBG8n_sgEM_nlEp3G0w3vLjmdvSZ46ln8ZXHn-eObZNjA"
|
||||
|
||||
describe("scan_skylink", function()
|
||||
before_each(function()
|
||||
stub(ngx.timer, "at")
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
ngx.timer.at:revert()
|
||||
end)
|
||||
|
||||
it("should schedule a timer when skylink is provided", function()
|
||||
ngx.timer.at.invokes(function() return true, nil end)
|
||||
|
||||
skynet_scanner.scan_skylink(skylink)
|
||||
|
||||
assert.stub(ngx.timer.at).was_called_with(0, skynet_scanner.scan_skylink_timer, skylink)
|
||||
end)
|
||||
|
||||
it("should log an error if timer failed to create", function()
|
||||
stub(ngx, "log")
|
||||
|
||||
ngx.timer.at.invokes(function() return false, "such a failure" end)
|
||||
|
||||
skynet_scanner.scan_skylink(skylink)
|
||||
|
||||
assert.stub(ngx.timer.at).was_called_with(0, skynet_scanner.scan_skylink_timer, skylink)
|
||||
assert.stub(ngx.log).was_called_with(ngx.ERR, "Failed to create timer: ", "such a failure")
|
||||
|
||||
ngx.log:revert()
|
||||
end)
|
||||
|
||||
it("should not schedule a timer if skylink is not provided", function()
|
||||
skynet_scanner.scan_skylink()
|
||||
|
||||
assert.stub(ngx.timer.at).was_not_called()
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("scan_skylink_timer", function()
|
||||
before_each(function()
|
||||
stub(ngx, "log")
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
local resty_http = require("resty.http")
|
||||
|
||||
ngx.log:revert()
|
||||
resty_http.new:revert()
|
||||
end)
|
||||
|
||||
it("should exit early on premature", function()
|
||||
local resty_http = require("resty.http")
|
||||
local request_uri = spy.new()
|
||||
local httpc = mock({ request_uri = request_uri })
|
||||
stub(resty_http, "new").returns(httpc)
|
||||
|
||||
skynet_scanner.scan_skylink_timer(true, skylink)
|
||||
|
||||
assert.stub(request_uri).was_not_called()
|
||||
assert.stub(ngx.log).was_not_called()
|
||||
end)
|
||||
|
||||
it("should make a post request with skylink to scanner service", function()
|
||||
local resty_http = require("resty.http")
|
||||
local request_uri = spy.new(function()
|
||||
return { status = 200 } -- return 200 success
|
||||
end)
|
||||
local httpc = mock({ request_uri = request_uri })
|
||||
stub(resty_http, "new").returns(httpc)
|
||||
|
||||
skynet_scanner.scan_skylink_timer(false, skylink)
|
||||
|
||||
local uri = "http://10.10.10.101:4000/scan/" .. skylink
|
||||
assert.stub(request_uri).was_called_with(httpc, uri, { method = "POST" })
|
||||
assert.stub(ngx.log).was_not_called()
|
||||
end)
|
||||
|
||||
it("should log message on scanner request failure with response code", function()
|
||||
local resty_http = require("resty.http")
|
||||
local request_uri = spy.new(function()
|
||||
return { status = 404, body = "baz" } -- return 404 failure
|
||||
end)
|
||||
local httpc = mock({ request_uri = request_uri })
|
||||
stub(resty_http, "new").returns(httpc)
|
||||
|
||||
skynet_scanner.scan_skylink_timer(false, skylink)
|
||||
|
||||
local uri = "http://10.10.10.101:4000/scan/" .. skylink
|
||||
assert.stub(request_uri).was_called_with(httpc, uri, { method = "POST" })
|
||||
assert.stub(ngx.log).was_called_with(
|
||||
ngx.ERR,
|
||||
"Failed malware-scanner request /scan/AQBG8n_sgEM_nlEp3G0w3vLjmdvSZ46ln8ZXHn-eObZNjA: ",
|
||||
"[HTTP 404] baz"
|
||||
)
|
||||
end)
|
||||
|
||||
it("should log message on scanner request error", function()
|
||||
local resty_http = require("resty.http")
|
||||
local request_uri = spy.new(function()
|
||||
return nil, "foo != bar" -- return error
|
||||
end)
|
||||
local httpc = mock({ request_uri = request_uri })
|
||||
stub(resty_http, "new").returns(httpc)
|
||||
|
||||
skynet_scanner.scan_skylink_timer(false, skylink)
|
||||
|
||||
local uri = "http://10.10.10.101:4000/scan/" .. skylink
|
||||
assert.stub(request_uri).was_called_with(httpc, uri, { method = "POST" })
|
||||
assert.stub(ngx.log).was_called_with(
|
||||
ngx.ERR,
|
||||
"Failed malware-scanner request /scan/AQBG8n_sgEM_nlEp3G0w3vLjmdvSZ46ln8ZXHn-eObZNjA: ",
|
||||
"foo != bar"
|
||||
)
|
||||
end)
|
||||
end)
|
|
@ -0,0 +1,90 @@
|
|||
local _M = {}
|
||||
|
||||
local utils = require("utils")
|
||||
|
||||
function _M.track_download_timer(premature, skylink, status, auth_headers, body_bytes_sent)
|
||||
if premature then return end
|
||||
|
||||
local httpc = require("resty.http").new()
|
||||
local query = table.concat({ "status=" .. status, "bytes=" .. body_bytes_sent }, "&")
|
||||
|
||||
-- 10.10.10.70 points to accounts service (alias not available when using resty-http)
|
||||
local res, err = httpc:request_uri("http://10.10.10.70:3000/track/download/" .. skylink .. "?" .. query, {
|
||||
method = "POST",
|
||||
headers = auth_headers,
|
||||
})
|
||||
|
||||
if err or (res and res.status ~= 204) then
|
||||
local error_response = err or ("[HTTP " .. res.status .. "] " .. res.body)
|
||||
ngx.log(ngx.ERR, "Failed accounts service request /track/download/" .. skylink .. ": ", error_response)
|
||||
end
|
||||
end
|
||||
|
||||
function _M.track_download(skylink, status_code, auth_headers, body_bytes_sent)
|
||||
local has_auth_headers = not utils.is_table_empty(auth_headers)
|
||||
local status_success = status_code >= 200 and status_code <= 299
|
||||
|
||||
if skylink and status_success and has_auth_headers then
|
||||
local ok, err = ngx.timer.at(0, _M.track_download_timer, skylink, status_code, auth_headers, body_bytes_sent)
|
||||
if not ok then ngx.log(ngx.ERR, "Failed to create timer: ", err) end
|
||||
end
|
||||
end
|
||||
|
||||
function _M.track_upload_timer(premature, skylink, auth_headers)
|
||||
if premature then return end
|
||||
|
||||
local httpc = require("resty.http").new()
|
||||
|
||||
-- 10.10.10.70 points to accounts service (alias not available when using resty-http)
|
||||
local res, err = httpc:request_uri("http://10.10.10.70:3000/track/upload/" .. skylink, {
|
||||
method = "POST",
|
||||
headers = auth_headers,
|
||||
})
|
||||
|
||||
if err or (res and res.status ~= 204) then
|
||||
local error_response = err or ("[HTTP " .. res.status .. "] " .. res.body)
|
||||
ngx.log(ngx.ERR, "Failed accounts service request /track/upload/" .. skylink .. ": ", error_response)
|
||||
end
|
||||
end
|
||||
|
||||
function _M.track_upload(skylink, status_code, auth_headers)
|
||||
local status_success = status_code >= 200 and status_code <= 299
|
||||
|
||||
if skylink and status_success then
|
||||
local ok, err = ngx.timer.at(0, _M.track_upload_timer, skylink, auth_headers)
|
||||
if not ok then ngx.log(ngx.ERR, "Failed to create timer: ", err) end
|
||||
end
|
||||
end
|
||||
|
||||
function _M.track_registry_timer(premature, auth_headers, request_method)
|
||||
if premature then return end
|
||||
|
||||
local httpc = require("resty.http").new()
|
||||
|
||||
-- based on request method we assign a registry action string used
|
||||
-- in track endpoint namely "read" for GET and "write" for POST
|
||||
local registry_action = request_method == "GET" and "read" or "write"
|
||||
|
||||
-- 10.10.10.70 points to accounts service (alias not available when using resty-http)
|
||||
local res, err = httpc:request_uri("http://10.10.10.70:3000/track/registry/" .. registry_action, {
|
||||
method = "POST",
|
||||
headers = auth_headers,
|
||||
})
|
||||
|
||||
if err or (res and res.status ~= 204) then
|
||||
local error_response = err or ("[HTTP " .. res.status .. "] " .. res.body)
|
||||
ngx.log(ngx.ERR, "Failed accounts service request /track/registry/" .. registry_action .. ": ", error_response)
|
||||
end
|
||||
end
|
||||
|
||||
function _M.track_registry(status_code, auth_headers, request_method)
|
||||
local has_auth_headers = not utils.is_table_empty(auth_headers)
|
||||
local tracked_status = status_code == 200 or status_code == 404
|
||||
|
||||
if tracked_status and has_auth_headers then
|
||||
local ok, err = ngx.timer.at(0, _M.track_registry_timer, auth_headers, request_method)
|
||||
if not ok then ngx.log(ngx.ERR, "Failed to create timer: ", err) end
|
||||
end
|
||||
end
|
||||
|
||||
return _M
|
|
@ -0,0 +1,555 @@
|
|||
-- luacheck: ignore ngx
|
||||
|
||||
local skynet_tracker = require("skynet.tracker")
|
||||
|
||||
local valid_skylink = "AQBG8n_sgEM_nlEp3G0w3vLjmdvSZ46ln8ZXHn-eObZNjA"
|
||||
local valid_status_code = 200
|
||||
local valid_auth_headers = { ["Skynet-Api-Key"] = "foo" }
|
||||
|
||||
describe("track_download", function()
|
||||
local valid_body_bytes_sent = 12345
|
||||
|
||||
before_each(function()
|
||||
stub(ngx.timer, "at")
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
ngx.timer.at:revert()
|
||||
end)
|
||||
|
||||
it("should schedule a timer when conditions are met", function()
|
||||
ngx.timer.at.invokes(function() return true, nil end)
|
||||
|
||||
skynet_tracker.track_download(valid_skylink, valid_status_code, valid_auth_headers, valid_body_bytes_sent)
|
||||
|
||||
assert.stub(ngx.timer.at).was_called_with(
|
||||
0,
|
||||
skynet_tracker.track_download_timer,
|
||||
valid_skylink,
|
||||
valid_status_code,
|
||||
valid_auth_headers,
|
||||
valid_body_bytes_sent
|
||||
)
|
||||
end)
|
||||
|
||||
it("should not schedule a timer if skylink is empty", function()
|
||||
ngx.timer.at.invokes(function() return true, nil end)
|
||||
|
||||
skynet_tracker.track_download(nil, valid_status_code, valid_auth_headers, valid_body_bytes_sent)
|
||||
|
||||
assert.stub(ngx.timer.at).was_not_called()
|
||||
end)
|
||||
|
||||
it("should not schedule a timer if status code is not in 2XX range", function()
|
||||
ngx.timer.at.invokes(function() return true, nil end)
|
||||
|
||||
-- couple of example of 4XX and 5XX codes
|
||||
skynet_tracker.track_download(valid_skylink, 401, valid_auth_headers, valid_body_bytes_sent)
|
||||
skynet_tracker.track_download(valid_skylink, 403, valid_auth_headers, valid_body_bytes_sent)
|
||||
skynet_tracker.track_download(valid_skylink, 490, valid_auth_headers, valid_body_bytes_sent)
|
||||
skynet_tracker.track_download(valid_skylink, 500, valid_auth_headers, valid_body_bytes_sent)
|
||||
skynet_tracker.track_download(valid_skylink, 502, valid_auth_headers, valid_body_bytes_sent)
|
||||
|
||||
assert.stub(ngx.timer.at).was_not_called()
|
||||
end)
|
||||
|
||||
it("should not schedule a timer if auth headers are empty", function()
|
||||
ngx.timer.at.invokes(function() return true, nil end)
|
||||
|
||||
skynet_tracker.track_download(valid_skylink, valid_status_code, {}, valid_body_bytes_sent)
|
||||
|
||||
assert.stub(ngx.timer.at).was_not_called()
|
||||
end)
|
||||
|
||||
it("should log an error if timer failed to create", function()
|
||||
stub(ngx, "log")
|
||||
ngx.timer.at.invokes(function() return false, "such a failure" end)
|
||||
|
||||
skynet_tracker.track_download(valid_skylink, valid_status_code, valid_auth_headers, valid_body_bytes_sent)
|
||||
|
||||
assert.stub(ngx.timer.at).was_called_with(
|
||||
0,
|
||||
skynet_tracker.track_download_timer,
|
||||
valid_skylink,
|
||||
valid_status_code,
|
||||
valid_auth_headers,
|
||||
valid_body_bytes_sent
|
||||
)
|
||||
assert.stub(ngx.log).was_called_with(ngx.ERR, "Failed to create timer: ", "such a failure")
|
||||
|
||||
ngx.log:revert()
|
||||
end)
|
||||
|
||||
describe("track_download_timer", function()
|
||||
before_each(function()
|
||||
stub(ngx, "log")
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
local resty_http = require("resty.http")
|
||||
|
||||
ngx.log:revert()
|
||||
resty_http.new:revert()
|
||||
end)
|
||||
|
||||
it("should exit early on premature", function()
|
||||
local resty_http = require("resty.http")
|
||||
local request_uri = spy.new(function()
|
||||
return { status = 200 } -- return 200 success
|
||||
end)
|
||||
local httpc = mock({ request_uri = request_uri })
|
||||
stub(resty_http, "new").returns(httpc)
|
||||
|
||||
skynet_tracker.track_download_timer(
|
||||
true,
|
||||
valid_skylink,
|
||||
valid_status_code,
|
||||
valid_auth_headers,
|
||||
valid_body_bytes_sent
|
||||
)
|
||||
|
||||
assert.stub(request_uri).was_not_called()
|
||||
assert.stub(ngx.log).was_not_called()
|
||||
end)
|
||||
|
||||
it("should make a post request to tracker service", function()
|
||||
local resty_http = require("resty.http")
|
||||
local request_uri = spy.new(function()
|
||||
return { status = 204 } -- return 204 success
|
||||
end)
|
||||
local httpc = mock({ request_uri = request_uri })
|
||||
stub(resty_http, "new").returns(httpc)
|
||||
|
||||
skynet_tracker.track_download_timer(
|
||||
false,
|
||||
valid_skylink,
|
||||
valid_status_code,
|
||||
valid_auth_headers,
|
||||
valid_body_bytes_sent
|
||||
)
|
||||
|
||||
local uri_params = "status=" .. valid_status_code .. "&bytes=" .. valid_body_bytes_sent
|
||||
local uri = "http://10.10.10.70:3000/track/download/" .. valid_skylink .. "?" .. uri_params
|
||||
assert.stub(request_uri).was_called_with(httpc, uri, { method = "POST", headers = valid_auth_headers })
|
||||
assert.stub(ngx.log).was_not_called()
|
||||
end)
|
||||
|
||||
it("should log message on tracker request failure with response code", function()
|
||||
local resty_http = require("resty.http")
|
||||
local request_uri = spy.new(function()
|
||||
return { status = 404, body = "baz" } -- return 404 failure
|
||||
end)
|
||||
local httpc = mock({ request_uri = request_uri })
|
||||
stub(resty_http, "new").returns(httpc)
|
||||
|
||||
skynet_tracker.track_download_timer(
|
||||
false,
|
||||
valid_skylink,
|
||||
valid_status_code,
|
||||
valid_auth_headers,
|
||||
valid_body_bytes_sent
|
||||
)
|
||||
|
||||
local uri_params = "status=" .. valid_status_code .. "&bytes=" .. valid_body_bytes_sent
|
||||
local uri = "http://10.10.10.70:3000/track/download/" .. valid_skylink .. "?" .. uri_params
|
||||
assert.stub(request_uri).was_called_with(httpc, uri, { method = "POST", headers = valid_auth_headers })
|
||||
assert.stub(ngx.log).was_called_with(
|
||||
ngx.ERR,
|
||||
"Failed accounts service request /track/download/" .. valid_skylink .. ": ",
|
||||
"[HTTP 404] baz"
|
||||
)
|
||||
end)
|
||||
|
||||
it("should log message on tracker request error", function()
|
||||
local resty_http = require("resty.http")
|
||||
local request_uri = spy.new(function()
|
||||
return nil, "foo != bar" -- return error
|
||||
end)
|
||||
local httpc = mock({ request_uri = request_uri })
|
||||
stub(resty_http, "new").returns(httpc)
|
||||
|
||||
skynet_tracker.track_download_timer(
|
||||
false,
|
||||
valid_skylink,
|
||||
valid_status_code,
|
||||
valid_auth_headers,
|
||||
valid_body_bytes_sent
|
||||
)
|
||||
|
||||
local uri_params = "status=" .. valid_status_code .. "&bytes=" .. valid_body_bytes_sent
|
||||
local uri = "http://10.10.10.70:3000/track/download/" .. valid_skylink .. "?" .. uri_params
|
||||
assert.stub(request_uri).was_called_with(httpc, uri, { method = "POST", headers = valid_auth_headers })
|
||||
assert.stub(ngx.log).was_called_with(
|
||||
ngx.ERR,
|
||||
"Failed accounts service request /track/download/" .. valid_skylink .. ": ",
|
||||
"foo != bar"
|
||||
)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("track_upload", function()
|
||||
before_each(function()
|
||||
stub(ngx.timer, "at")
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
ngx.timer.at:revert()
|
||||
end)
|
||||
|
||||
it("should schedule a timer when conditions are met", function()
|
||||
ngx.timer.at.invokes(function() return true, nil end)
|
||||
|
||||
skynet_tracker.track_upload(valid_skylink, valid_status_code, valid_auth_headers)
|
||||
|
||||
assert.stub(ngx.timer.at).was_called_with(
|
||||
0,
|
||||
skynet_tracker.track_upload_timer,
|
||||
valid_skylink,
|
||||
valid_auth_headers
|
||||
)
|
||||
end)
|
||||
|
||||
it("should not schedule a timer if skylink is empty", function()
|
||||
ngx.timer.at.invokes(function() return true, nil end)
|
||||
|
||||
skynet_tracker.track_upload(nil, valid_status_code, valid_auth_headers)
|
||||
|
||||
assert.stub(ngx.timer.at).was_not_called()
|
||||
end)
|
||||
|
||||
it("should not schedule a timer if status code is not in 2XX range", function()
|
||||
ngx.timer.at.invokes(function() return true, nil end)
|
||||
|
||||
-- couple of example of 4XX and 5XX codes
|
||||
skynet_tracker.track_upload(valid_skylink, 401, valid_auth_headers)
|
||||
skynet_tracker.track_upload(valid_skylink, 403, valid_auth_headers)
|
||||
skynet_tracker.track_upload(valid_skylink, 490, valid_auth_headers)
|
||||
skynet_tracker.track_upload(valid_skylink, 500, valid_auth_headers)
|
||||
skynet_tracker.track_upload(valid_skylink, 502, valid_auth_headers)
|
||||
|
||||
assert.stub(ngx.timer.at).was_not_called()
|
||||
end)
|
||||
|
||||
it("should schedule a timer if auth headers are empty", function()
|
||||
ngx.timer.at.invokes(function() return true, nil end)
|
||||
|
||||
skynet_tracker.track_upload(valid_skylink, valid_status_code, {})
|
||||
|
||||
assert.stub(ngx.timer.at).was_called_with(
|
||||
0,
|
||||
skynet_tracker.track_upload_timer,
|
||||
valid_skylink,
|
||||
{}
|
||||
)
|
||||
end)
|
||||
|
||||
it("should log an error if timer failed to create", function()
|
||||
stub(ngx, "log")
|
||||
ngx.timer.at.invokes(function() return false, "such a failure" end)
|
||||
|
||||
skynet_tracker.track_upload(valid_skylink, valid_status_code, valid_auth_headers)
|
||||
|
||||
assert.stub(ngx.timer.at).was_called_with(
|
||||
0,
|
||||
skynet_tracker.track_upload_timer,
|
||||
valid_skylink,
|
||||
valid_auth_headers
|
||||
)
|
||||
assert.stub(ngx.log).was_called_with(ngx.ERR, "Failed to create timer: ", "such a failure")
|
||||
|
||||
ngx.log:revert()
|
||||
end)
|
||||
|
||||
describe("track_upload_timer", function()
|
||||
before_each(function()
|
||||
stub(ngx, "log")
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
local resty_http = require("resty.http")
|
||||
|
||||
ngx.log:revert()
|
||||
resty_http.new:revert()
|
||||
end)
|
||||
|
||||
it("should exit early on premature", function()
|
||||
local resty_http = require("resty.http")
|
||||
local request_uri = spy.new(function()
|
||||
return { status = 200 } -- return 200 success
|
||||
end)
|
||||
local httpc = mock({ request_uri = request_uri })
|
||||
stub(resty_http, "new").returns(httpc)
|
||||
|
||||
skynet_tracker.track_upload_timer(
|
||||
true,
|
||||
valid_skylink,
|
||||
valid_auth_headers
|
||||
)
|
||||
|
||||
assert.stub(request_uri).was_not_called()
|
||||
assert.stub(ngx.log).was_not_called()
|
||||
end)
|
||||
|
||||
it("should make a post request to tracker service", function()
|
||||
local resty_http = require("resty.http")
|
||||
local request_uri = spy.new(function()
|
||||
return { status = 204 } -- return 204 success
|
||||
end)
|
||||
local httpc = mock({ request_uri = request_uri })
|
||||
stub(resty_http, "new").returns(httpc)
|
||||
|
||||
skynet_tracker.track_upload_timer(
|
||||
false,
|
||||
valid_skylink,
|
||||
valid_auth_headers
|
||||
)
|
||||
|
||||
local uri = "http://10.10.10.70:3000/track/upload/" .. valid_skylink
|
||||
assert.stub(request_uri).was_called_with(httpc, uri, { method = "POST", headers = valid_auth_headers })
|
||||
assert.stub(ngx.log).was_not_called()
|
||||
end)
|
||||
|
||||
it("should log message on tracker request failure with response code", function()
|
||||
local resty_http = require("resty.http")
|
||||
local request_uri = spy.new(function()
|
||||
return { status = 404, body = "baz" } -- return 404 failure
|
||||
end)
|
||||
local httpc = mock({ request_uri = request_uri })
|
||||
stub(resty_http, "new").returns(httpc)
|
||||
|
||||
skynet_tracker.track_upload_timer(
|
||||
false,
|
||||
valid_skylink,
|
||||
valid_auth_headers
|
||||
)
|
||||
|
||||
local uri = "http://10.10.10.70:3000/track/upload/" .. valid_skylink
|
||||
assert.stub(request_uri).was_called_with(httpc, uri, { method = "POST", headers = valid_auth_headers })
|
||||
assert.stub(ngx.log).was_called_with(
|
||||
ngx.ERR,
|
||||
"Failed accounts service request /track/upload/" .. valid_skylink .. ": ",
|
||||
"[HTTP 404] baz"
|
||||
)
|
||||
end)
|
||||
|
||||
it("should log message on tracker request error", function()
|
||||
local resty_http = require("resty.http")
|
||||
local request_uri = spy.new(function()
|
||||
return nil, "foo != bar" -- return error
|
||||
end)
|
||||
local httpc = mock({ request_uri = request_uri })
|
||||
stub(resty_http, "new").returns(httpc)
|
||||
|
||||
skynet_tracker.track_upload_timer(
|
||||
false,
|
||||
valid_skylink,
|
||||
valid_auth_headers
|
||||
)
|
||||
|
||||
local uri = "http://10.10.10.70:3000/track/upload/" .. valid_skylink
|
||||
assert.stub(request_uri).was_called_with(httpc, uri, { method = "POST", headers = valid_auth_headers })
|
||||
assert.stub(ngx.log).was_called_with(
|
||||
ngx.ERR,
|
||||
"Failed accounts service request /track/upload/" .. valid_skylink .. ": ",
|
||||
"foo != bar"
|
||||
)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("track_registry", function()
|
||||
local status_code_ok = 200
|
||||
local status_code_not_found = 404
|
||||
local request_method_write = "POST"
|
||||
local request_method_read = "GET"
|
||||
|
||||
before_each(function()
|
||||
stub(ngx.timer, "at")
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
ngx.timer.at:revert()
|
||||
end)
|
||||
|
||||
it("should schedule a timer when status code was 200", function()
|
||||
ngx.timer.at.invokes(function() return true, nil end)
|
||||
|
||||
skynet_tracker.track_registry(status_code_ok, valid_auth_headers, request_method_write)
|
||||
|
||||
assert.stub(ngx.timer.at).was_called_with(
|
||||
0,
|
||||
skynet_tracker.track_registry_timer,
|
||||
valid_auth_headers,
|
||||
request_method_write
|
||||
)
|
||||
end)
|
||||
|
||||
it("should schedule a timer when status code was 404", function()
|
||||
ngx.timer.at.invokes(function() return true, nil end)
|
||||
|
||||
skynet_tracker.track_registry(status_code_not_found, valid_auth_headers, request_method_write)
|
||||
|
||||
assert.stub(ngx.timer.at).was_called_with(
|
||||
0,
|
||||
skynet_tracker.track_registry_timer,
|
||||
valid_auth_headers,
|
||||
request_method_write
|
||||
)
|
||||
end)
|
||||
|
||||
it("should not schedule a timer if status code is not in 200 or 404", function()
|
||||
ngx.timer.at.invokes(function() return true, nil end)
|
||||
|
||||
-- couple of example of invalid 2XX, 4XX and 5XX codes
|
||||
skynet_tracker.track_registry(204, valid_auth_headers, request_method_write)
|
||||
skynet_tracker.track_registry(206, valid_auth_headers, request_method_write)
|
||||
skynet_tracker.track_registry(401, valid_auth_headers, request_method_write)
|
||||
skynet_tracker.track_registry(403, valid_auth_headers, request_method_write)
|
||||
skynet_tracker.track_registry(490, valid_auth_headers, request_method_write)
|
||||
skynet_tracker.track_registry(500, valid_auth_headers, request_method_write)
|
||||
skynet_tracker.track_registry(502, valid_auth_headers, request_method_write)
|
||||
|
||||
assert.stub(ngx.timer.at).was_not_called()
|
||||
end)
|
||||
|
||||
it("should not schedule a timer if auth headers are empty", function()
|
||||
ngx.timer.at.invokes(function() return true, nil end)
|
||||
|
||||
skynet_tracker.track_registry(status_code_ok, {}, request_method_write)
|
||||
|
||||
assert.stub(ngx.timer.at).was_not_called()
|
||||
end)
|
||||
|
||||
it("should log an error if timer failed to create", function()
|
||||
stub(ngx, "log")
|
||||
ngx.timer.at.invokes(function() return false, "such a failure" end)
|
||||
|
||||
skynet_tracker.track_registry(status_code_ok, valid_auth_headers, request_method_write)
|
||||
|
||||
assert.stub(ngx.timer.at).was_called_with(
|
||||
0,
|
||||
skynet_tracker.track_registry_timer,
|
||||
valid_auth_headers,
|
||||
request_method_write
|
||||
)
|
||||
assert.stub(ngx.log).was_called_with(ngx.ERR, "Failed to create timer: ", "such a failure")
|
||||
|
||||
ngx.log:revert()
|
||||
end)
|
||||
|
||||
describe("track_registry_timer", function()
|
||||
before_each(function()
|
||||
stub(ngx, "log")
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
local resty_http = require("resty.http")
|
||||
|
||||
ngx.log:revert()
|
||||
resty_http.new:revert()
|
||||
end)
|
||||
|
||||
it("should exit early on premature", function()
|
||||
local resty_http = require("resty.http")
|
||||
local request_uri = spy.new(function()
|
||||
return { status = 200 } -- return 200 success
|
||||
end)
|
||||
local httpc = mock({ request_uri = request_uri })
|
||||
stub(resty_http, "new").returns(httpc)
|
||||
|
||||
skynet_tracker.track_registry_timer(
|
||||
true,
|
||||
valid_auth_headers,
|
||||
request_method_write
|
||||
)
|
||||
|
||||
assert.stub(request_uri).was_not_called()
|
||||
assert.stub(ngx.log).was_not_called()
|
||||
end)
|
||||
|
||||
it("should make a post request to registry write tracker service", function()
|
||||
local resty_http = require("resty.http")
|
||||
local request_uri = spy.new(function()
|
||||
return { status = 204 } -- return 204 success
|
||||
end)
|
||||
local httpc = mock({ request_uri = request_uri })
|
||||
stub(resty_http, "new").returns(httpc)
|
||||
|
||||
skynet_tracker.track_registry_timer(
|
||||
false,
|
||||
valid_auth_headers,
|
||||
request_method_write
|
||||
)
|
||||
|
||||
local uri = "http://10.10.10.70:3000/track/registry/write"
|
||||
assert.stub(request_uri).was_called_with(httpc, uri, { method = "POST", headers = valid_auth_headers })
|
||||
assert.stub(ngx.log).was_not_called()
|
||||
end)
|
||||
|
||||
it("should make a post request to registry read tracker service", function()
|
||||
local resty_http = require("resty.http")
|
||||
local request_uri = spy.new(function()
|
||||
return { status = 204 } -- return 204 success
|
||||
end)
|
||||
local httpc = mock({ request_uri = request_uri })
|
||||
stub(resty_http, "new").returns(httpc)
|
||||
|
||||
skynet_tracker.track_registry_timer(
|
||||
false,
|
||||
valid_auth_headers,
|
||||
request_method_read
|
||||
)
|
||||
|
||||
local uri = "http://10.10.10.70:3000/track/registry/read"
|
||||
assert.stub(request_uri).was_called_with(httpc, uri, { method = "POST", headers = valid_auth_headers })
|
||||
assert.stub(ngx.log).was_not_called()
|
||||
end)
|
||||
|
||||
it("should log message on tracker request failure with response code", function()
|
||||
local resty_http = require("resty.http")
|
||||
local request_uri = spy.new(function()
|
||||
return { status = 404, body = "baz" } -- return 404 failure
|
||||
end)
|
||||
local httpc = mock({ request_uri = request_uri })
|
||||
stub(resty_http, "new").returns(httpc)
|
||||
|
||||
skynet_tracker.track_registry_timer(
|
||||
false,
|
||||
valid_auth_headers,
|
||||
request_method_write
|
||||
)
|
||||
|
||||
local uri = "http://10.10.10.70:3000/track/registry/write"
|
||||
assert.stub(request_uri).was_called_with(httpc, uri, { method = "POST", headers = valid_auth_headers })
|
||||
assert.stub(ngx.log).was_called_with(
|
||||
ngx.ERR,
|
||||
"Failed accounts service request /track/registry/write: ",
|
||||
"[HTTP 404] baz"
|
||||
)
|
||||
end)
|
||||
|
||||
it("should log message on tracker request error", function()
|
||||
local resty_http = require("resty.http")
|
||||
local request_uri = spy.new(function()
|
||||
return nil, "foo != bar" -- return error
|
||||
end)
|
||||
local httpc = mock({ request_uri = request_uri })
|
||||
stub(resty_http, "new").returns(httpc)
|
||||
|
||||
skynet_tracker.track_registry_timer(
|
||||
false,
|
||||
valid_auth_headers,
|
||||
request_method_write
|
||||
)
|
||||
|
||||
local uri = "http://10.10.10.70:3000/track/registry/write"
|
||||
assert.stub(request_uri).was_called_with(httpc, uri, { method = "POST", headers = valid_auth_headers })
|
||||
assert.stub(ngx.log).was_called_with(
|
||||
ngx.ERR,
|
||||
"Failed accounts service request /track/registry/write: ",
|
||||
"foo != bar"
|
||||
)
|
||||
end)
|
||||
end)
|
||||
end)
|
|
@ -1,13 +1,20 @@
|
|||
local _M = {}
|
||||
|
||||
local ngx_base64 = require("ngx.base64")
|
||||
local utils = require("utils")
|
||||
|
||||
function _M.authorization_header()
|
||||
-- read api password from env variable
|
||||
local apipassword = os.getenv("SIA_API_PASSWORD")
|
||||
local apipassword = utils.getenv("SIA_API_PASSWORD")
|
||||
-- if api password is not available as env variable, read it from disk
|
||||
if apipassword == nil or apipassword == "" then
|
||||
if not apipassword then
|
||||
-- open apipassword file for reading (b flag is required for some reason)
|
||||
-- (file /etc/.sia/apipassword has to be mounted from the host system)
|
||||
local apipassword_file = io.open("/data/sia/apipassword", "rb")
|
||||
-- make sure to throw a meaningful error if apipassword file does not exist
|
||||
if not apipassword_file then
|
||||
error("Error reading /data/sia/apipassword file")
|
||||
end
|
||||
-- read apipassword file contents and trim newline (important)
|
||||
apipassword = apipassword_file:read("*all"):gsub("%s+", "")
|
||||
-- make sure to close file after reading the password
|
||||
|
@ -15,7 +22,7 @@ function _M.authorization_header()
|
|||
end
|
||||
-- encode the user:password authorization string
|
||||
-- (in our case user is empty so it is just :password)
|
||||
local content = require("ngx.base64").encode_base64url(":" .. apipassword)
|
||||
local content = ngx_base64.encode_base64url(":" .. apipassword)
|
||||
-- set authorization header with proper base64 encoded string
|
||||
return "Basic " .. content
|
||||
end
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
-- luacheck: ignore io
|
||||
|
||||
local utils = require('utils')
|
||||
local skynet_utils = require('skynet.utils')
|
||||
|
||||
describe("authorization_header", function()
|
||||
local apipassword = "ddd0c1430fbf2708"
|
||||
local expected_header = "Basic OmRkZDBjMTQzMGZiZjI3MDg"
|
||||
|
||||
it("reads SIA_API_PASSWORD from env variable and returns a header", function()
|
||||
-- stub getenv on SIA_API_PASSWORD
|
||||
stub(utils, "getenv")
|
||||
utils.getenv.on_call_with("SIA_API_PASSWORD").returns(apipassword)
|
||||
|
||||
local header = skynet_utils.authorization_header()
|
||||
|
||||
assert.is_equal(header, expected_header)
|
||||
|
||||
-- revert stub to original function
|
||||
utils.getenv:revert()
|
||||
end)
|
||||
|
||||
it("uses /data/sia/apipassword file if SIA_API_PASSWORD env var is missing", function()
|
||||
-- stub /data/sia/apipassword file
|
||||
stub(io, "open")
|
||||
io.open.on_call_with("/data/sia/apipassword", "rb").returns(mock({
|
||||
read = spy.new(function() return apipassword end),
|
||||
close = spy.new()
|
||||
}))
|
||||
|
||||
local header = skynet_utils.authorization_header()
|
||||
|
||||
assert.is_equal(header, expected_header)
|
||||
|
||||
-- revert stub to original function
|
||||
io.open:revert()
|
||||
end)
|
||||
|
||||
it("should choose env variable over file if both are available", function()
|
||||
-- stub getenv on SIA_API_PASSWORD
|
||||
stub(utils, "getenv")
|
||||
utils.getenv.on_call_with("SIA_API_PASSWORD").returns(apipassword)
|
||||
|
||||
-- stub /data/sia/apipassword file
|
||||
stub(io, "open")
|
||||
io.open.on_call_with("/data/sia/apipassword", "rb").returns(mock({
|
||||
read = spy.new(function() return "foooooooooooooo" end),
|
||||
close = spy.new()
|
||||
}))
|
||||
|
||||
local header = skynet_utils.authorization_header()
|
||||
|
||||
assert.is_equal(header, "Basic OmRkZDBjMTQzMGZiZjI3MDg")
|
||||
|
||||
-- revert stubs to original function
|
||||
utils.getenv:revert()
|
||||
io.open:revert()
|
||||
end)
|
||||
|
||||
it("should error out if neither env variable is available nor file exists", function()
|
||||
assert.has_error(function()
|
||||
skynet_utils.authorization_header()
|
||||
end, "Error reading /data/sia/apipassword file")
|
||||
end)
|
||||
end)
|
|
@ -42,4 +42,42 @@ function _M.extract_cookie_value(cookie_string, name_matcher)
|
|||
return string.sub(cookie, value_start)
|
||||
end
|
||||
|
||||
-- utility function that builds on os.getenv to get environment variable value
|
||||
-- * will always return nil for both unset and empty env vars
|
||||
-- * parse "boolean": "true" and "1" as true, "false" and "0" as false, throws for others
|
||||
-- * parse "integer": any numerical string gets converted, otherwise returns nil
|
||||
function _M.getenv(name, parse)
|
||||
local value = os.getenv(name)
|
||||
|
||||
-- treat empty string value as nil to simplify comparisons
|
||||
if value == nil or value == "" then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- do not parse the value
|
||||
if parse == nil then
|
||||
return value
|
||||
end
|
||||
|
||||
-- try to parse as boolean
|
||||
if parse == "boolean" then
|
||||
if string.lower(value) == "true" or value == "1" then
|
||||
return true
|
||||
end
|
||||
|
||||
if string.lower(value) == "false" or value == "0" then
|
||||
return false
|
||||
end
|
||||
|
||||
error("utils.getenv: Parsing value '" .. tostring(value) .. "' to boolean is not supported")
|
||||
end
|
||||
|
||||
-- try to parse as integer
|
||||
if parse == "integer" then
|
||||
return tonumber(value)
|
||||
end
|
||||
|
||||
error("utils.getenv: Parsing to '" .. parse .. "' is not supported")
|
||||
end
|
||||
|
||||
return _M
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
-- luacheck: ignore os
|
||||
|
||||
local utils = require('utils')
|
||||
|
||||
describe("is_table_empty", function()
|
||||
|
@ -77,3 +79,137 @@ describe("extract_cookie_value", function()
|
|||
assert.are.equals(value, "MTY0NzUyr8jD-ytiWtspm0tGabKfooxeIDuWcXhJ3lnY0eEw==")
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("getenv", function()
|
||||
before_each(function()
|
||||
stub(os, "getenv")
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
os.getenv:revert()
|
||||
end)
|
||||
|
||||
it("should return nil for not existing env var", function()
|
||||
os.getenv.on_call_with("foo").returns(nil)
|
||||
|
||||
assert.is_nil(utils.getenv("foo"))
|
||||
end)
|
||||
|
||||
it("should return nil for env var that is an empty string", function()
|
||||
os.getenv.on_call_with("foo").returns("")
|
||||
|
||||
assert.is_nil(utils.getenv("foo"))
|
||||
end)
|
||||
|
||||
it("should return the value as is when it is non empty string", function()
|
||||
os.getenv.on_call_with("foo").returns("bar")
|
||||
|
||||
assert.is_equal(utils.getenv("foo"), "bar")
|
||||
end)
|
||||
|
||||
describe("parse", function()
|
||||
it("should throw on not supported parser", function()
|
||||
os.getenv.on_call_with("foo").returns("test")
|
||||
|
||||
assert.has_error(function()
|
||||
utils.getenv("foo", "starwars")
|
||||
end, "utils.getenv: Parsing to 'starwars' is not supported")
|
||||
end)
|
||||
|
||||
describe("as boolean", function()
|
||||
it("should return nil for not existing env var", function()
|
||||
os.getenv.on_call_with("foo").returns(nil)
|
||||
|
||||
assert.is_nil(utils.getenv("foo", "boolean"))
|
||||
end)
|
||||
|
||||
it("should return nil for env var that is an empty string", function()
|
||||
os.getenv.on_call_with("foo").returns("")
|
||||
|
||||
assert.is_nil(utils.getenv("foo", "boolean"))
|
||||
end)
|
||||
|
||||
it("should parse 'true' string as true", function()
|
||||
os.getenv.on_call_with("foo").returns("true")
|
||||
|
||||
assert.is_true(utils.getenv("foo", "boolean"))
|
||||
end)
|
||||
|
||||
it("should parse 'True' string as true", function()
|
||||
os.getenv.on_call_with("foo").returns("True")
|
||||
|
||||
assert.is_true(utils.getenv("foo", "boolean"))
|
||||
end)
|
||||
|
||||
it("should parse '1' string as true", function()
|
||||
os.getenv.on_call_with("foo").returns("1")
|
||||
|
||||
assert.is_true(utils.getenv("foo", "boolean"))
|
||||
end)
|
||||
|
||||
it("should parse 'false' string as false", function()
|
||||
os.getenv.on_call_with("foo").returns("false")
|
||||
|
||||
assert.is_false(utils.getenv("foo", "boolean"))
|
||||
end)
|
||||
|
||||
it("should parse 'False' string as false", function()
|
||||
os.getenv.on_call_with("foo").returns("False")
|
||||
|
||||
assert.is_false(utils.getenv("foo", "boolean"))
|
||||
end)
|
||||
|
||||
it("should parse '0' string as false", function()
|
||||
os.getenv.on_call_with("foo").returns("0")
|
||||
|
||||
assert.is_false(utils.getenv("foo", "boolean"))
|
||||
end)
|
||||
|
||||
it("should throw an error for not supported string", function()
|
||||
os.getenv.on_call_with("foo").returns("mandalorian")
|
||||
|
||||
assert.has_error(function()
|
||||
utils.getenv("foo", "boolean")
|
||||
end, "utils.getenv: Parsing value 'mandalorian' to boolean is not supported")
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("as integer", function()
|
||||
it("should return nil for not existing env var", function()
|
||||
os.getenv.on_call_with("foo").returns(nil)
|
||||
|
||||
assert.is_nil(utils.getenv("foo", "integer"))
|
||||
end)
|
||||
|
||||
it("should return nil for env var that is an empty string", function()
|
||||
os.getenv.on_call_with("foo").returns("")
|
||||
|
||||
assert.is_nil(utils.getenv("foo", "integer"))
|
||||
end)
|
||||
|
||||
it("should parse '0' string as 0", function()
|
||||
os.getenv.on_call_with("foo").returns("0")
|
||||
|
||||
assert.equals(utils.getenv("foo", "integer"), 0)
|
||||
end)
|
||||
|
||||
it("should parse '1' string as 1", function()
|
||||
os.getenv.on_call_with("foo").returns("1")
|
||||
|
||||
assert.equals(utils.getenv("foo", "integer"), 1)
|
||||
end)
|
||||
|
||||
it("should parse '-1' string as -1", function()
|
||||
os.getenv.on_call_with("foo").returns("-1")
|
||||
|
||||
assert.equals(utils.getenv("foo", "integer"), -1)
|
||||
end)
|
||||
|
||||
it("should return nil for non numerical string", function()
|
||||
os.getenv.on_call_with("foo").returns("test")
|
||||
|
||||
assert.is_nil(utils.getenv("foo", "integer"))
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
|
1106
docker/nginx/mo
1106
docker/nginx/mo
File diff suppressed because it is too large
Load Diff
|
@ -19,6 +19,9 @@
|
|||
user root;
|
||||
worker_processes auto;
|
||||
|
||||
# Enables the use of JIT for regular expressions to speed-up their processing.
|
||||
pcre_jit on;
|
||||
|
||||
#error_log logs/error.log;
|
||||
#error_log logs/error.log notice;
|
||||
#error_log logs/error.log info;
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
exclude = {
|
||||
"/usr/local/openresty", -- internal openresty libraries
|
||||
"rbusted", -- busted executable
|
||||
"basexx", -- external library https://github.com/aiq/basexx
|
||||
}
|
||||
includeuntestedfiles = true
|
|
@ -0,0 +1,11 @@
|
|||
FROM openresty/openresty:1.19.9.1-focal
|
||||
|
||||
WORKDIR /etc/nginx
|
||||
|
||||
RUN luarocks install lua-resty-http && \
|
||||
luarocks install hasher && \
|
||||
luarocks install busted
|
||||
|
||||
COPY rbusted /etc/nginx/
|
||||
|
||||
CMD ["/etc/nginx/rbusted", "--verbose", "--pattern=spec", "/usr/local/openresty/site/lualib"]
|
|
@ -0,0 +1,3 @@
|
|||
# Running tests locally
|
||||
|
||||
`docker run -v $(pwd)/docker/nginx/libs:/usr/local/openresty/site/lualib --rm -it $(docker build -q docker/nginx/testing)`
|
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env resty
|
||||
|
||||
setmetatable(_G, nil)
|
||||
|
||||
pcall(require, "luarocks.loader")
|
||||
|
||||
-- Busted command-line runner
|
||||
require "busted.runner"({ standalone = false })
|
|
@ -2,13 +2,17 @@ FROM node:16.14.2-alpine
|
|||
|
||||
WORKDIR /usr/app
|
||||
|
||||
COPY package.json yarn.lock ./
|
||||
COPY packages/dashboard-v2/package.json \
|
||||
packages/dashboard-v2/yarn.lock \
|
||||
./
|
||||
|
||||
RUN yarn --frozen-lockfile
|
||||
|
||||
COPY static ./static
|
||||
COPY src ./src
|
||||
COPY gatsby*.js ./
|
||||
COPY postcss.config.js tailwind.config.js ./
|
||||
COPY packages/dashboard-v2/static ./static
|
||||
COPY packages/dashboard-v2/src ./src
|
||||
COPY packages/dashboard-v2/gatsby*.js \
|
||||
packages/dashboard-v2/postcss.config.js \
|
||||
packages/dashboard-v2/tailwind.config.js \
|
||||
./
|
||||
|
||||
CMD ["sh", "-c", "yarn build && yarn serve --host 0.0.0.0 -p 9000"]
|
||||
|
|
|
@ -11,15 +11,20 @@ This is a Gatsby application. To run it locally, all you need is:
|
|||
|
||||
## Accessing remote APIs
|
||||
|
||||
To be able to log in on a local environment with your production credentials, you'll need to make the browser believe you're actually on the same domain, otherwise the browser will block the session cookie.
|
||||
To have a fully functioning local environment, you'll need to make the browser believe you're actually on the same domain as a working API (i.e. a remote dev or production server) -- otherwise the browser will block the session cookie.
|
||||
To do the trick, configure proper environment variables in the `.env.development` file.
|
||||
This file allows to easily control which domain name you want to use locally and which API you'd like to access.
|
||||
|
||||
To do the trick, edit your `/etc/hosts` file and add a record like this:
|
||||
Example:
|
||||
|
||||
```
|
||||
127.0.0.1 local.skynetpro.net
|
||||
```env
|
||||
GATSBY_PORTAL_DOMAIN=skynetfree.net # Use skynetfree.net APIs
|
||||
GATSBY_HOST=local.skynetfree.net # Address of your local build
|
||||
```
|
||||
|
||||
then run `yarn develop:secure` -- it will run `gatsby develop` with `--https --host=local.skynetpro.net -p=443` options.
|
||||
If you're on macOS, you may need to `sudo` the command to successfully bind to port `443`.
|
||||
> It's recommended to keep the 2LD the same, so any cookies dispatched by the API work without issues.
|
||||
|
||||
> **NOTE:** This should become easier once we have a docker image for the new dashboard.
|
||||
With the file configured, run `yarn develop:secure` -- it will run `gatsby develop` with `--https -p=443` options.
|
||||
If you're on macOS, you may need to `sudo` the command to successfully bind to port `443` (https).
|
||||
|
||||
Gatsby will automatically add a proper entry to your `/etc/hosts` file and clean it up when process exits.
|
||||
|
|
|
@ -1,10 +1,17 @@
|
|||
require("dotenv").config({
|
||||
path: `.env.${process.env.NODE_ENV}`,
|
||||
});
|
||||
|
||||
const { createProxyMiddleware } = require("http-proxy-middleware");
|
||||
|
||||
const { GATSBY_PORTAL_DOMAIN } = process.env;
|
||||
|
||||
module.exports = {
|
||||
siteMetadata: {
|
||||
title: "Skynet Account",
|
||||
siteUrl: `https://account.${process.env.GATSBY_PORTAL_DOMAIN}/`,
|
||||
title: `Account Dashboard`,
|
||||
siteUrl: `https://account.${GATSBY_PORTAL_DOMAIN}`,
|
||||
},
|
||||
pathPrefix: "/v2",
|
||||
trailingSlash: "never",
|
||||
plugins: [
|
||||
"gatsby-plugin-image",
|
||||
|
@ -24,13 +31,27 @@ module.exports = {
|
|||
},
|
||||
],
|
||||
developMiddleware: (app) => {
|
||||
// Proxy Accounts service API requests:
|
||||
app.use(
|
||||
"/api/",
|
||||
createProxyMiddleware({
|
||||
target: "https://account.skynetpro.net",
|
||||
target: `https://account.${GATSBY_PORTAL_DOMAIN}`,
|
||||
secure: false, // Do not reject self-signed certificates.
|
||||
changeOrigin: true,
|
||||
})
|
||||
);
|
||||
|
||||
// Proxy /skynet requests (e.g. uploads)
|
||||
app.use(
|
||||
["/skynet", "/__internal/"],
|
||||
createProxyMiddleware({
|
||||
target: `https://${GATSBY_PORTAL_DOMAIN}`,
|
||||
secure: false, // Do not reject self-signed certificates.
|
||||
changeOrigin: true,
|
||||
pathRewrite: {
|
||||
"^/skynet": "",
|
||||
},
|
||||
})
|
||||
);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
],
|
||||
"scripts": {
|
||||
"develop": "gatsby develop",
|
||||
"develop:secure": "gatsby develop --https --host=local.skynetpro.net -p=443",
|
||||
"develop:secure": "dotenv -e .env.development -- gatsby develop --https -p=443",
|
||||
"start": "gatsby develop",
|
||||
"build": "gatsby build",
|
||||
"serve": "gatsby serve",
|
||||
"build": "gatsby build --prefix-paths",
|
||||
"serve": "gatsby serve --prefix-paths",
|
||||
"clean": "gatsby clean",
|
||||
"lint": "eslint .",
|
||||
"prettier": "prettier .",
|
||||
|
@ -60,6 +60,8 @@
|
|||
"babel-loader": "^8.2.3",
|
||||
"babel-plugin-preval": "^5.1.0",
|
||||
"babel-plugin-styled-components": "^2.0.2",
|
||||
"dotenv": "^16.0.0",
|
||||
"dotenv-cli": "^5.1.0",
|
||||
"eslint": "^8.9.0",
|
||||
"eslint-config-react-app": "^7.0.0",
|
||||
"eslint-plugin-storybook": "^0.5.6",
|
||||
|
|
|
@ -4,7 +4,7 @@ import { useCallback, useState } from "react";
|
|||
|
||||
import { Alert } from "../Alert";
|
||||
import { Button } from "../Button";
|
||||
import { AddSkylinkToAPIKeyForm } from "../forms/AddSkylinkToAPIKeyForm";
|
||||
import { AddSkylinkToSponsorKeyForm } from "../forms/AddSkylinkToSponsorKeyForm";
|
||||
import { CogIcon, TrashIcon } from "../Icons";
|
||||
import { Modal } from "../Modal";
|
||||
|
||||
|
@ -13,7 +13,7 @@ import { useAPIKeyRemoval } from "./useAPIKeyRemoval";
|
|||
|
||||
export const APIKey = ({ apiKey, onRemoved, onEdited, onRemovalError }) => {
|
||||
const { id, name, createdAt, skylinks } = apiKey;
|
||||
const isPublic = apiKey.public === "true";
|
||||
const isSponsorKey = apiKey.public === "true";
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
const onSkylinkListEdited = useCallback(() => {
|
||||
|
@ -53,9 +53,9 @@ export const APIKey = ({ apiKey, onRemoved, onEdited, onRemovalError }) => {
|
|||
}, [abortEdit]);
|
||||
|
||||
const skylinksNumber = skylinks?.length ?? 0;
|
||||
const isNotConfigured = isPublic && skylinksNumber === 0;
|
||||
const isNotConfigured = isSponsorKey && skylinksNumber === 0;
|
||||
const skylinksPhrasePrefix = skylinksNumber === 0 ? "No" : skylinksNumber;
|
||||
const skylinksPhrase = `${skylinksPhrasePrefix} ${skylinksNumber === 1 ? "skylink" : "skylinks"} configured`;
|
||||
const skylinksPhrase = `${skylinksPhrasePrefix} ${skylinksNumber === 1 ? "skylink" : "skylinks"} sponsored`;
|
||||
|
||||
return (
|
||||
<li
|
||||
|
@ -66,21 +66,23 @@ export const APIKey = ({ apiKey, onRemoved, onEdited, onRemovalError }) => {
|
|||
<span className="col-span-2 sm:col-span-1 flex items-center">
|
||||
<span className="flex flex-col">
|
||||
<span className={cn("truncate", { "text-palette-300": !name })}>{name || "unnamed key"}</span>
|
||||
<button
|
||||
onClick={promptEdit}
|
||||
className={cn("text-xs hover:underline decoration-dotted", {
|
||||
"text-error": isNotConfigured,
|
||||
"text-palette-400": !isNotConfigured,
|
||||
})}
|
||||
>
|
||||
{skylinksPhrase}
|
||||
</button>
|
||||
{isSponsorKey && (
|
||||
<button
|
||||
onClick={promptEdit}
|
||||
className={cn("text-xs hover:underline decoration-dotted", {
|
||||
"text-error": isNotConfigured,
|
||||
"text-palette-400": !isNotConfigured,
|
||||
})}
|
||||
>
|
||||
{skylinksPhrase}
|
||||
</button>
|
||||
)}
|
||||
</span>
|
||||
</span>
|
||||
<span className="col-span-2 my-4 border-t border-t-palette-200/50 sm:hidden" />
|
||||
<span className="text-palette-400">{dayjs(createdAt).format("MMM DD, YYYY")}</span>
|
||||
<span className="flex items-center justify-end">
|
||||
{isPublic && (
|
||||
{isSponsorKey && (
|
||||
<button
|
||||
title="Add or remove skylinks"
|
||||
aria-label="Add or remove skylinks"
|
||||
|
@ -119,7 +121,7 @@ export const APIKey = ({ apiKey, onRemoved, onEdited, onRemovalError }) => {
|
|||
)}
|
||||
{editInitiated && (
|
||||
<Modal onClose={closeEditModal} className="flex flex-col gap-4 text-center sm:px-8 sm:py-6">
|
||||
<h4>Covered skylinks</h4>
|
||||
<h4>Sponsored skylinks</h4>
|
||||
{skylinks?.length > 0 ? (
|
||||
<ul className="text-xs flex flex-col gap-2">
|
||||
{skylinks.map((skylink) => (
|
||||
|
@ -143,7 +145,7 @@ export const APIKey = ({ apiKey, onRemoved, onEdited, onRemovalError }) => {
|
|||
|
||||
<div className="flex flex-col gap-4">
|
||||
{error && <Alert $variant="error">{error}</Alert>}
|
||||
<AddSkylinkToAPIKeyForm addSkylink={addSkylink} />
|
||||
<AddSkylinkToSponsorKeyForm addSkylink={addSkylink} />
|
||||
</div>
|
||||
<div className="flex gap-4 justify-center mt-4">
|
||||
<Button onClick={closeEditModal}>Close</Button>
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import { useEffect, useState } from "react";
|
||||
|
||||
import { useUser } from "../../contexts/user";
|
||||
import { SimpleUploadIcon } from "../Icons";
|
||||
// import { SimpleUploadIcon } from "../Icons";
|
||||
|
||||
const AVATAR_PLACEHOLDER = "/images/avatar-placeholder.svg";
|
||||
import avatarPlaceholder from "../../../static/images/avatar-placeholder.svg";
|
||||
|
||||
export const AvatarUploader = (props) => {
|
||||
const { user } = useUser();
|
||||
const [imageUrl, setImageUrl] = useState(AVATAR_PLACEHOLDER);
|
||||
const [imageUrl, setImageUrl] = useState(avatarPlaceholder);
|
||||
|
||||
useEffect(() => {
|
||||
setImageUrl(user.avatarUrl ?? AVATAR_PLACEHOLDER);
|
||||
setImageUrl(user.avatarUrl ?? avatarPlaceholder);
|
||||
}, [user]);
|
||||
|
||||
return (
|
||||
|
@ -20,6 +20,7 @@ export const AvatarUploader = (props) => {
|
|||
>
|
||||
<img src={imageUrl} className="w-[160px]" alt="" />
|
||||
</div>
|
||||
{/* TODO: uncomment when avatar uploads work
|
||||
<div className="flex justify-center">
|
||||
<button
|
||||
className="flex items-center gap-4 hover:underline decoration-1 decoration-dashed underline-offset-2 decoration-gray-400"
|
||||
|
@ -28,8 +29,8 @@ export const AvatarUploader = (props) => {
|
|||
>
|
||||
<SimpleUploadIcon size={20} className="shrink-0" /> Upload profile picture
|
||||
</button>
|
||||
{/* TODO: actual uploading */}
|
||||
</div>
|
||||
*/}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import dayjs from "dayjs";
|
||||
import relativeTime from "dayjs/plugin/relativeTime";
|
||||
import prettyBytes from "pretty-bytes";
|
||||
|
||||
import { useUser } from "../../contexts/user";
|
||||
import useActivePlan from "../../hooks/useActivePlan";
|
||||
|
@ -28,17 +29,20 @@ const CurrentPlan = () => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex flex-col h-full">
|
||||
<h4>{activePlan.name}</h4>
|
||||
<div className="text-palette-400">
|
||||
{activePlan.price === 0 && <p>100GB without paying a dime! 🎉</p>}
|
||||
<div className="text-palette-400 justify-between flex flex-col grow">
|
||||
{activePlan.price === 0 && activePlan.limits && (
|
||||
<p>{prettyBytes(activePlan.limits.storageLimit, { binary: true })} without paying a dime! 🎉</p>
|
||||
)}
|
||||
{activePlan.price !== 0 &&
|
||||
(user.subscriptionCancelAtPeriodEnd ? (
|
||||
<p>Your subscription expires {dayjs(user.subscribedUntil).fromNow()}</p>
|
||||
) : (
|
||||
<p className="first-letter:uppercase">{dayjs(user.subscribedUntil).fromNow(true)} until the next payment</p>
|
||||
))}
|
||||
<LatestPayment user={user} />
|
||||
|
||||
{user.subscriptionStatus && <LatestPayment user={user} />}
|
||||
<SuggestedPlan plans={plans} activePlan={activePlan} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { useEffect, useMemo, useState } from "react";
|
||||
import fileSize from "pretty-bytes";
|
||||
import { Link } from "gatsby";
|
||||
import cn from "classnames";
|
||||
import useSWR from "swr";
|
||||
|
||||
import { useUser } from "../../contexts/user";
|
||||
|
@ -44,7 +45,7 @@ const useUsageData = () => {
|
|||
};
|
||||
|
||||
const size = (bytes) => {
|
||||
const text = fileSize(bytes ?? 0, { maximumFractionDigits: 0 });
|
||||
const text = fileSize(bytes ?? 0, { maximumFractionDigits: 0, binary: true });
|
||||
const [value, unit] = text.split(" ");
|
||||
|
||||
return {
|
||||
|
@ -62,7 +63,9 @@ const ErrorMessage = () => (
|
|||
);
|
||||
|
||||
export default function CurrentUsage() {
|
||||
const { activePlan, plans } = useActivePlan();
|
||||
const { usage, error, loading } = useUsageData();
|
||||
const nextPlan = useMemo(() => plans.find(({ tier }) => tier > activePlan?.tier), [plans, activePlan]);
|
||||
const storageUsage = size(usage.storageUsed);
|
||||
const storageLimit = size(usage.storageLimit);
|
||||
const filesUsedLabel = useMemo(() => ({ value: usage.filesUsed, unit: "files" }), [usage.filesUsed]);
|
||||
|
@ -89,7 +92,7 @@ export default function CurrentUsage() {
|
|||
<span>{storageLimit.text}</span>
|
||||
</div>
|
||||
<UsageGraph>
|
||||
<GraphBar value={usage.storageUsed} limit={usage.storageLimit} label={storageUsage} />
|
||||
<GraphBar value={usage.storageUsed} limit={usage.storageLimit} label={storageUsage} className="normal-case" />
|
||||
<GraphBar value={usage.filesUsed} limit={usage.filesLimit} label={filesUsedLabel} />
|
||||
</UsageGraph>
|
||||
<div className="flex place-content-between">
|
||||
|
@ -97,7 +100,10 @@ export default function CurrentUsage() {
|
|||
<span className="inline-flex place-content-between w-[37%]">
|
||||
<Link
|
||||
to="/upgrade"
|
||||
className="text-primary underline-offset-3 decoration-dotted hover:text-primary-light hover:underline"
|
||||
className={cn(
|
||||
"text-primary underline-offset-3 decoration-dotted hover:text-primary-light hover:underline",
|
||||
{ invisible: !nextPlan }
|
||||
)}
|
||||
>
|
||||
UPGRADE
|
||||
</Link>{" "}
|
||||
|
|
|
@ -21,11 +21,11 @@ const BarLabel = styled.span.attrs({
|
|||
`}
|
||||
`;
|
||||
|
||||
export const GraphBar = ({ value, limit, label }) => {
|
||||
export const GraphBar = ({ value, limit, label, className }) => {
|
||||
const percentage = typeof limit !== "number" || limit === 0 ? 0 : (value / limit) * 100;
|
||||
|
||||
return (
|
||||
<div className="relative flex items-center">
|
||||
<div className={`relative flex items-center ${className}`}>
|
||||
<Bar $percentage={percentage}>
|
||||
<BarTip />
|
||||
</Bar>
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import styled from "styled-components";
|
||||
|
||||
import usageGraphBg from "../../../static/images/usage-graph-bg.svg";
|
||||
|
||||
export const UsageGraph = styled.div.attrs({
|
||||
className: "w-full my-3 grid grid-flow-row grid-rows-2",
|
||||
})`
|
||||
height: 146px;
|
||||
background: url(/images/usage-graph-bg.svg) no-repeat;
|
||||
background: url(${usageGraphBg}) no-repeat;
|
||||
background-size: cover;
|
||||
`;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { useMemo } from "react";
|
||||
import prettyBytes from "pretty-bytes";
|
||||
import dayjs from "dayjs";
|
||||
import { DATE_FORMAT } from "../../lib/config";
|
||||
|
||||
const parseFileName = (fileName) => {
|
||||
const lastDotIndex = Math.max(0, fileName.lastIndexOf(".")) || Infinity;
|
||||
|
@ -10,7 +11,7 @@ const parseFileName = (fileName) => {
|
|||
|
||||
const formatItem = ({ size, name: rawFileName, uploadedOn, downloadedOn, ...rest }) => {
|
||||
const [name, type] = parseFileName(rawFileName);
|
||||
const date = dayjs(uploadedOn || downloadedOn).format("MM/DD/YYYY; HH:MM");
|
||||
const date = dayjs(uploadedOn || downloadedOn).format(DATE_FORMAT);
|
||||
|
||||
return {
|
||||
...rest,
|
||||
|
|
|
@ -1,8 +1,19 @@
|
|||
import * as React from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { PageContainer } from "../PageContainer";
|
||||
|
||||
const FooterLink = styled.a.attrs({
|
||||
className: "text-palette-400 underline decoration-dotted decoration-offset-4 decoration-1",
|
||||
rel: "noreferrer",
|
||||
target: "_blank",
|
||||
})``;
|
||||
|
||||
export const Footer = () => (
|
||||
<PageContainer className="font-content text-palette-300 py-4">
|
||||
<p>© Skynet Labs Inc. All rights reserved.</p>
|
||||
<p>
|
||||
Made by <FooterLink href="https://skynetlabs.com">Skynet Labs</FooterLink>. Open-sourced{" "}
|
||||
<FooterLink href="https://github.com/SkynetLabs/skynet-webportal">on Github</FooterLink>.
|
||||
</p>
|
||||
</PageContainer>
|
||||
);
|
||||
|
|
|
@ -2,5 +2,5 @@ import { Link } from "gatsby";
|
|||
import styled from "styled-components";
|
||||
|
||||
export default styled(Link).attrs({
|
||||
className: "text-primary underline-offset-3 decoration-dotted hover:text-primary-light hover:underline",
|
||||
className: "text-primary underline-offset-2 decoration-1 decoration-dotted hover:text-primary-light hover:underline",
|
||||
})``;
|
||||
|
|
|
@ -3,13 +3,13 @@ import useSWR from "swr";
|
|||
|
||||
import { Table, TableBody, TableCell, TableRow } from "../Table";
|
||||
import { ContainerLoadingIndicator } from "../LoadingIndicator";
|
||||
import useFormattedFilesData from "../FileList/useFormattedFilesData";
|
||||
|
||||
import { ViewAllLink } from "./ViewAllLink";
|
||||
import useFormattedActivityData from "./useFormattedActivityData";
|
||||
|
||||
export default function ActivityTable({ type }) {
|
||||
const { data, error } = useSWR(`user/${type}?pageSize=3`);
|
||||
const items = useFormattedActivityData(data?.items || []);
|
||||
const items = useFormattedFilesData(data?.items || []);
|
||||
|
||||
if (!items.length) {
|
||||
return (
|
||||
|
|
|
@ -1,23 +1,13 @@
|
|||
import * as React from "react";
|
||||
|
||||
import { Panel } from "../Panel";
|
||||
import { Tab, TabPanel, Tabs } from "../Tabs";
|
||||
|
||||
import ActivityTable from "./ActivityTable";
|
||||
|
||||
export default function LatestActivity() {
|
||||
return (
|
||||
<Panel title="Latest activity">
|
||||
<Tabs>
|
||||
<Tab id="uploads" title="Uploads" />
|
||||
<Tab id="downloads" title="Downloads" />
|
||||
<TabPanel tabId="uploads" className="pt-4">
|
||||
<ActivityTable type="uploads" />
|
||||
</TabPanel>
|
||||
<TabPanel tabId="downloads" className="pt-4">
|
||||
<ActivityTable type="downloads" />
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
<Panel title="Latest uploads">
|
||||
<ActivityTable type="uploads" />
|
||||
</Panel>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
import { useMemo } from "react";
|
||||
import prettyBytes from "pretty-bytes";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
const parseFileName = (fileName) => {
|
||||
const lastDotIndex = Math.max(0, fileName.lastIndexOf(".")) || Infinity;
|
||||
|
||||
return [fileName.substr(0, lastDotIndex), fileName.substr(lastDotIndex)];
|
||||
};
|
||||
|
||||
const formatItem = ({ size, name: rawFileName, uploadedOn, downloadedOn, ...rest }) => {
|
||||
const [name, type] = parseFileName(rawFileName);
|
||||
const date = dayjs(uploadedOn || downloadedOn).format("MM/DD/YYYY; HH:MM");
|
||||
|
||||
return {
|
||||
...rest,
|
||||
date,
|
||||
size: prettyBytes(size),
|
||||
type,
|
||||
name,
|
||||
};
|
||||
};
|
||||
|
||||
const useFormattedActivityData = (items) => useMemo(() => items.map(formatItem), [items]);
|
||||
|
||||
export default useFormattedActivityData;
|
|
@ -0,0 +1 @@
|
|||
export * from "./Tooltip";
|
|
@ -118,7 +118,7 @@ const Uploader = ({ mode }) => {
|
|||
</div>
|
||||
|
||||
{uploads.length > 0 && (
|
||||
<div className="flex flex-col space-y-4 py-10">
|
||||
<div className="flex flex-col space-y-4 pt-6 pb-10">
|
||||
{uploads.map((upload) => (
|
||||
<UploaderItem key={upload.id} onUploadStateChange={onUploadStateChange} upload={upload} />
|
||||
))}
|
||||
|
|
|
@ -34,8 +34,9 @@ export const AccountRemovalForm = ({ abort, onSuccess }) => {
|
|||
<Form className="flex flex-col gap-4">
|
||||
<div>
|
||||
<h4>Delete account</h4>
|
||||
<p>This will completely delete your account.</p>
|
||||
<p>
|
||||
This will completely delete your account. <strong>This process can't be undone.</strong>
|
||||
<strong>This process cannot be undone.</strong>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import * as Yup from "yup";
|
|||
import { forwardRef, useImperativeHandle, useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { Formik, Form } from "formik";
|
||||
import cn from "classnames";
|
||||
|
||||
import accountsService from "../../services/accountsService";
|
||||
|
||||
|
@ -9,7 +10,6 @@ import { Alert } from "../Alert";
|
|||
import { Button } from "../Button";
|
||||
import { CopyButton } from "../CopyButton";
|
||||
import { TextField } from "../Form/TextField";
|
||||
import { CircledProgressIcon, PlusIcon } from "../Icons";
|
||||
|
||||
const newAPIKeySchema = Yup.object().shape({
|
||||
name: Yup.string(),
|
||||
|
@ -22,7 +22,7 @@ const State = {
|
|||
};
|
||||
|
||||
export const APIKeyType = {
|
||||
Public: "public",
|
||||
Sponsor: "sponsor",
|
||||
General: "general",
|
||||
};
|
||||
|
||||
|
@ -37,10 +37,10 @@ export const AddAPIKeyForm = forwardRef(({ onSuccess, type }, ref) => {
|
|||
return (
|
||||
<div ref={ref} className="flex flex-col gap-4">
|
||||
{state === State.Success && (
|
||||
<Alert $variant="success" className="text-center">
|
||||
<Alert $variant="success">
|
||||
<strong>Success!</strong>
|
||||
<p>Please copy your new API key below. We'll never show it again!</p>
|
||||
<div className="flex items-center gap-2 mt-4 justify-center">
|
||||
<div className="flex items-center gap-2 mt-4">
|
||||
<code className="p-2 rounded border border-palette-200 text-xs selection:bg-primary/30 truncate">
|
||||
{generatedKey}
|
||||
</code>
|
||||
|
@ -62,8 +62,8 @@ export const AddAPIKeyForm = forwardRef(({ onSuccess, type }, ref) => {
|
|||
.post("user/apikeys", {
|
||||
json: {
|
||||
name,
|
||||
public: type === APIKeyType.Public ? "true" : "false",
|
||||
skylinks: type === APIKeyType.Public ? [] : null,
|
||||
public: type === APIKeyType.Sponsor ? "true" : "false",
|
||||
skylinks: type === APIKeyType.Sponsor ? [] : null,
|
||||
},
|
||||
})
|
||||
.json();
|
||||
|
@ -78,26 +78,20 @@ export const AddAPIKeyForm = forwardRef(({ onSuccess, type }, ref) => {
|
|||
}}
|
||||
>
|
||||
{({ errors, touched, isSubmitting }) => (
|
||||
<Form className="grid grid-cols-[1fr_min-content] w-full gap-y-2 gap-x-4 items-start">
|
||||
<div className="flex items-center">
|
||||
<TextField
|
||||
type="text"
|
||||
id="name"
|
||||
name="name"
|
||||
label="New API Key Name"
|
||||
placeholder="my_applications_statistics"
|
||||
error={errors.name}
|
||||
touched={touched.name}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex mt-5 justify-center">
|
||||
{isSubmitting ? (
|
||||
<CircledProgressIcon size={38} className="text-palette-300 animate-[spin_3s_linear_infinite]" />
|
||||
) : (
|
||||
<Button type="submit" className="px-2.5" aria-label="Create general API key">
|
||||
<PlusIcon size={14} />
|
||||
</Button>
|
||||
)}
|
||||
<Form className="flex flex-col gap-4">
|
||||
<TextField
|
||||
type="text"
|
||||
id="name"
|
||||
name="name"
|
||||
label="New API Key Label"
|
||||
placeholder="my_applications_statistics"
|
||||
error={errors.name}
|
||||
touched={touched.name}
|
||||
/>
|
||||
<div className="flex justify-center">
|
||||
<Button type="submit" disabled={isSubmitting} className={cn({ "cursor-wait": isSubmitting })}>
|
||||
{isSubmitting ? "Generating your API key..." : "Generate your API key"}
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
|
@ -110,5 +104,5 @@ AddAPIKeyForm.displayName = "AddAPIKeyForm";
|
|||
|
||||
AddAPIKeyForm.propTypes = {
|
||||
onSuccess: PropTypes.func.isRequired,
|
||||
type: PropTypes.oneOf([APIKeyType.Public, APIKeyType.General]).isRequired,
|
||||
type: PropTypes.oneOf([APIKeyType.Sponsor, APIKeyType.General]).isRequired,
|
||||
};
|
||||
|
|
|
@ -19,7 +19,7 @@ const newSkylinkSchema = Yup.object().shape({
|
|||
}),
|
||||
});
|
||||
|
||||
export const AddSkylinkToAPIKeyForm = ({ addSkylink }) => (
|
||||
export const AddSkylinkToSponsorKeyForm = ({ addSkylink }) => (
|
||||
<Formik
|
||||
initialValues={{
|
||||
skylink: "",
|
||||
|
@ -58,6 +58,6 @@ export const AddSkylinkToAPIKeyForm = ({ addSkylink }) => (
|
|||
</Formik>
|
||||
);
|
||||
|
||||
AddSkylinkToAPIKeyForm.propTypes = {
|
||||
AddSkylinkToSponsorKeyForm.propTypes = {
|
||||
addSkylink: PropTypes.func.isRequired,
|
||||
};
|
|
@ -25,7 +25,7 @@ const skylinkValidator = (optional) => (value) => {
|
|||
}
|
||||
};
|
||||
|
||||
const newPublicAPIKeySchema = Yup.object().shape({
|
||||
const newSponsorKeySchema = Yup.object().shape({
|
||||
name: Yup.string(),
|
||||
skylinks: Yup.array().of(Yup.string().test("skylink", "Provide a valid Skylink", skylinkValidator(false))),
|
||||
nextSkylink: Yup.string().when("skylinks", {
|
||||
|
@ -41,7 +41,7 @@ const State = {
|
|||
Failure: "FAILURE",
|
||||
};
|
||||
|
||||
export const AddPublicAPIKeyForm = forwardRef(({ onSuccess }, ref) => {
|
||||
export const AddSponsorKeyForm = forwardRef(({ onSuccess }, ref) => {
|
||||
const [state, setState] = useState(State.Pure);
|
||||
const [generatedKey, setGeneratedKey] = useState(null);
|
||||
|
||||
|
@ -52,10 +52,10 @@ export const AddPublicAPIKeyForm = forwardRef(({ onSuccess }, ref) => {
|
|||
return (
|
||||
<div ref={ref} className="flex flex-col gap-4">
|
||||
{state === State.Success && (
|
||||
<Alert $variant="success" className="text-center">
|
||||
<Alert $variant="success">
|
||||
<strong>Success!</strong>
|
||||
<p>Please copy your new API key below. We'll never show it again!</p>
|
||||
<div className="flex items-center gap-2 mt-4 justify-center">
|
||||
<div className="flex items-center gap-2 mt-4">
|
||||
<code className="p-2 rounded border border-palette-200 text-xs selection:bg-primary/30 truncate">
|
||||
{generatedKey}
|
||||
</code>
|
||||
|
@ -72,7 +72,7 @@ export const AddPublicAPIKeyForm = forwardRef(({ onSuccess }, ref) => {
|
|||
skylinks: [],
|
||||
nextSkylink: "",
|
||||
}}
|
||||
validationSchema={newPublicAPIKeySchema}
|
||||
validationSchema={newSponsorKeySchema}
|
||||
onSubmit={async ({ name, skylinks, nextSkylink }, { resetForm }) => {
|
||||
try {
|
||||
const { key } = await accountsService
|
||||
|
@ -80,7 +80,7 @@ export const AddPublicAPIKeyForm = forwardRef(({ onSuccess }, ref) => {
|
|||
json: {
|
||||
name,
|
||||
public: "true",
|
||||
skylinks: [...skylinks, nextSkylink].filter(Boolean).map(parseSkylink),
|
||||
skylinks: [...skylinks, nextSkylink].filter(Boolean).map((skylink) => parseSkylink(skylink)),
|
||||
},
|
||||
})
|
||||
.json();
|
||||
|
@ -101,14 +101,14 @@ export const AddPublicAPIKeyForm = forwardRef(({ onSuccess }, ref) => {
|
|||
type="text"
|
||||
id="name"
|
||||
name="name"
|
||||
label="Public API Key Name"
|
||||
label="Sponsor API Key Name"
|
||||
placeholder="my_applications_statistics"
|
||||
error={errors.name}
|
||||
touched={touched.name}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h6 className="text-palette-300 mb-2">Skylinks accessible with the new key</h6>
|
||||
<h6 className="text-palette-300 mb-2">Skylinks sponsored by the new key</h6>
|
||||
<FieldArray
|
||||
name="skylinks"
|
||||
render={({ push, remove }) => {
|
||||
|
@ -182,7 +182,7 @@ export const AddPublicAPIKeyForm = forwardRef(({ onSuccess }, ref) => {
|
|||
className={cn("px-2.5", { "cursor-wait": isSubmitting })}
|
||||
disabled={!isValid || isSubmitting}
|
||||
>
|
||||
{isSubmitting ? "Generating" : "Generate"} your public key
|
||||
{isSubmitting ? "Generating your sponsor key..." : "Generate your sponsor key"}
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
|
@ -192,8 +192,8 @@ export const AddPublicAPIKeyForm = forwardRef(({ onSuccess }, ref) => {
|
|||
);
|
||||
});
|
||||
|
||||
AddPublicAPIKeyForm.displayName = "AddAPIKeyForm";
|
||||
AddSponsorKeyForm.displayName = "AddSponsorKeyForm";
|
||||
|
||||
AddPublicAPIKeyForm.propTypes = {
|
||||
AddSponsorKeyForm.propTypes = {
|
||||
onSuccess: PropTypes.func.isRequired,
|
||||
};
|
|
@ -32,14 +32,16 @@ export const SignUpForm = ({ onSuccess, onFailure }) => (
|
|||
validationSchema={registrationSchema}
|
||||
onSubmit={async ({ email, password }, { setErrors }) => {
|
||||
try {
|
||||
await accountsService.post("user", {
|
||||
json: {
|
||||
email,
|
||||
password,
|
||||
},
|
||||
});
|
||||
const user = await accountsService
|
||||
.post("user", {
|
||||
json: {
|
||||
email,
|
||||
password,
|
||||
},
|
||||
})
|
||||
.json();
|
||||
|
||||
onSuccess();
|
||||
onSuccess(user);
|
||||
} catch (err) {
|
||||
let isFormErrorSet = false;
|
||||
|
||||
|
|
|
@ -19,7 +19,14 @@ const aggregatePlansAndLimits = (plans, limits, { includeFreePlan }) => {
|
|||
|
||||
// Decorate each plan with its corresponding limits data, if available.
|
||||
if (limits?.length) {
|
||||
return sortedPlans.map((plan) => ({ ...plan, limits: limits[plan.tier] || null }));
|
||||
return limits.map((limitsDescriptor, index) => {
|
||||
const asssociatedPlan = sortedPlans.find((plan) => plan.tier === index) || {};
|
||||
|
||||
return {
|
||||
...asssociatedPlan,
|
||||
limits: limitsDescriptor || null,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// If we don't have the limits data yet, set just return the plans.
|
||||
|
@ -40,10 +47,12 @@ export const PlansProvider = ({ children }) => {
|
|||
if (plansError || limitsError) {
|
||||
setLoading(false);
|
||||
setError(plansError || limitsError);
|
||||
} else if (rawPlans) {
|
||||
} else if (rawPlans || limits) {
|
||||
setLoading(false);
|
||||
setPlans(
|
||||
aggregatePlansAndLimits(rawPlans, limits?.userLimits, { includeFreePlan: !settings.isSubscriptionRequired })
|
||||
aggregatePlansAndLimits(rawPlans || [], limits?.userLimits, {
|
||||
includeFreePlan: !settings.isSubscriptionRequired,
|
||||
})
|
||||
);
|
||||
}
|
||||
}, [rawPlans, limits, plansError, limitsError, settings.isSubscriptionRequired]);
|
||||
|
|
|
@ -3,10 +3,13 @@ import styled from "styled-components";
|
|||
|
||||
import { UserProvider } from "../contexts/user";
|
||||
|
||||
import skynetLogo from "../../static/images/logo-black-text.svg";
|
||||
import authBg from "../../static/images/auth-bg.svg";
|
||||
|
||||
const Layout = styled.div.attrs({
|
||||
className: "min-h-screen w-screen bg-black flex",
|
||||
})`
|
||||
background-image: url(/images/auth-bg.svg);
|
||||
background-image: url(${authBg});
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
`;
|
||||
|
@ -36,7 +39,7 @@ const AuthLayout =
|
|||
<Content>
|
||||
<div className="bg-white px-8 py-10 md:py-32 lg:px-16 xl:px-28 min-h-screen">
|
||||
<div className="mb-4 md:mb-16">
|
||||
<img src="/images/logo-black-text.svg" alt="Skynet" className="-ml-2" />
|
||||
<img src={skynetLogo} alt="Skynet" className="-ml-2" />
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
|
|
|
@ -7,10 +7,12 @@ import { Footer } from "../components/Footer";
|
|||
import { UserProvider, useUser } from "../contexts/user";
|
||||
import { FullScreenLoadingIndicator } from "../components/LoadingIndicator";
|
||||
|
||||
import dashboardBg from "../../static/images/dashboard-bg.svg";
|
||||
|
||||
const Wrapper = styled.div.attrs({
|
||||
className: "min-h-screen overflow-hidden",
|
||||
})`
|
||||
background-image: url(/images/dashboard-bg.svg);
|
||||
background-image: url(${dashboardBg});
|
||||
background-position: center -280px;
|
||||
background-repeat: no-repeat;
|
||||
`;
|
||||
|
|
|
@ -16,8 +16,8 @@ const Sidebar = () => (
|
|||
<SidebarLink activeClassName="!border-l-primary" to="/settings/export">
|
||||
Export
|
||||
</SidebarLink>
|
||||
<SidebarLink activeClassName="!border-l-primary" to="/settings/api-keys">
|
||||
API Keys
|
||||
<SidebarLink activeClassName="!border-l-primary" to="/settings/developer-settings">
|
||||
Developer settings
|
||||
</SidebarLink>
|
||||
</nav>
|
||||
</aside>
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
export const DATE_FORMAT = "MMM D, YYYY HH:MM";
|
|
@ -1,5 +1,4 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import { navigate } from "gatsby";
|
||||
import { useCallback, useState } from "react";
|
||||
import bytes from "pretty-bytes";
|
||||
|
||||
import AuthLayout from "../../layouts/AuthLayout";
|
||||
|
@ -10,6 +9,7 @@ import { SignUpForm } from "../../components/forms/SignUpForm";
|
|||
import { usePortalSettings } from "../../contexts/portal-settings";
|
||||
import { PlansProvider, usePlans } from "../../contexts/plans";
|
||||
import { Metadata } from "../../components/Metadata";
|
||||
import { useUser } from "../../contexts/user";
|
||||
|
||||
const FreePortalHeader = () => {
|
||||
const { plans } = usePlans();
|
||||
|
@ -47,14 +47,14 @@ const State = {
|
|||
const SignUpPage = () => {
|
||||
const [state, setState] = useState(State.Pure);
|
||||
const { settings } = usePortalSettings();
|
||||
const { mutate: refreshUserState } = useUser();
|
||||
|
||||
useEffect(() => {
|
||||
if (state === State.Success) {
|
||||
const timer = setTimeout(() => navigate(settings.isSubscriptionRequired ? "/upgrade" : "/"), 3000);
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
}
|
||||
}, [state, settings.isSubscriptionRequired]);
|
||||
const onUserCreated = useCallback(
|
||||
(newUser) => {
|
||||
refreshUserState(newUser);
|
||||
},
|
||||
[refreshUserState]
|
||||
);
|
||||
|
||||
return (
|
||||
<PlansProvider>
|
||||
|
@ -70,7 +70,7 @@ const SignUpPage = () => {
|
|||
|
||||
{state !== State.Success && (
|
||||
<>
|
||||
<SignUpForm onSuccess={() => setState(State.Success)} onFailure={() => setState(State.Failure)} />
|
||||
<SignUpForm onSuccess={onUserCreated} onFailure={() => setState(State.Failure)} />
|
||||
|
||||
<p className="text-sm text-center mt-8">
|
||||
Already have an account? <HighlightedLink to="/auth/login">Sign in</HighlightedLink>
|
||||
|
@ -78,14 +78,6 @@ const SignUpPage = () => {
|
|||
</>
|
||||
)}
|
||||
|
||||
{state === State.Success && (
|
||||
<div>
|
||||
<p className="text-primary font-semibold">Please check your inbox and confirm your email address.</p>
|
||||
<p>You will be redirected to your dashboard shortly.</p>
|
||||
<HighlightedLink to="/">Click here to go there now.</HighlightedLink>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{state === State.Failure && (
|
||||
<p className="text-error text-center">Something went wrong, please try again later.</p>
|
||||
)}
|
||||
|
|
|
@ -1,32 +1,19 @@
|
|||
import * as React from "react";
|
||||
import { useSearchParam } from "react-use";
|
||||
|
||||
import DashboardLayout from "../layouts/DashboardLayout";
|
||||
|
||||
import { Panel } from "../components/Panel";
|
||||
import { Tab, TabPanel, Tabs } from "../components/Tabs";
|
||||
import { Metadata } from "../components/Metadata";
|
||||
import FileList from "../components/FileList/FileList";
|
||||
|
||||
const FilesPage = () => {
|
||||
const defaultTab = useSearchParam("tab");
|
||||
|
||||
return (
|
||||
<>
|
||||
<Metadata>
|
||||
<title>My Files</title>
|
||||
<title>Files</title>
|
||||
</Metadata>
|
||||
<Panel title="Files">
|
||||
<Tabs defaultTab={defaultTab || "uploads"}>
|
||||
<Tab id="uploads" title="Uploads" />
|
||||
<Tab id="downloads" title="Downloads" />
|
||||
<TabPanel tabId="uploads" className="pt-4">
|
||||
<FileList type="uploads" />
|
||||
</TabPanel>
|
||||
<TabPanel tabId="downloads" className="pt-4">
|
||||
<FileList type="downloads" />
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
<FileList type="uploads" />
|
||||
</Panel>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -1,110 +0,0 @@
|
|||
import useSWR from "swr";
|
||||
import { useCallback, useRef } from "react";
|
||||
|
||||
import UserSettingsLayout from "../../layouts/UserSettingsLayout";
|
||||
|
||||
import { AddAPIKeyForm, APIKeyType } from "../../components/forms/AddAPIKeyForm";
|
||||
import { APIKeyList } from "../../components/APIKeyList/APIKeyList";
|
||||
import { Alert } from "../../components/Alert";
|
||||
import { AddPublicAPIKeyForm } from "../../components/forms/AddPublicAPIKeyForm";
|
||||
import { Metadata } from "../../components/Metadata";
|
||||
|
||||
const APIKeysPage = () => {
|
||||
const { data: apiKeys = [], mutate: reloadKeys, error } = useSWR("user/apikeys");
|
||||
const generalKeys = apiKeys.filter(({ public: isPublic }) => isPublic === "false");
|
||||
const publicKeys = apiKeys.filter(({ public: isPublic }) => isPublic === "true");
|
||||
|
||||
const publicFormRef = useRef();
|
||||
const generalFormRef = useRef();
|
||||
|
||||
const refreshState = useCallback(
|
||||
(resetForms) => {
|
||||
if (resetForms) {
|
||||
publicFormRef.current?.reset();
|
||||
generalFormRef.current?.reset();
|
||||
}
|
||||
reloadKeys();
|
||||
},
|
||||
[reloadKeys]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Metadata>
|
||||
<title>API Keys</title>
|
||||
</Metadata>
|
||||
<div className="flex flex-col xl:flex-row">
|
||||
<div className="flex flex-col gap-10 lg:shrink-0 lg:max-w-[576px] xl:max-w-[524px]">
|
||||
<div>
|
||||
<h4>API Keys</h4>
|
||||
<p className="leading-relaxed">There are two types of API keys that you can generate for your account.</p>
|
||||
<p>Make sure to use the appropriate type.</p>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<section className="flex flex-col gap-2">
|
||||
<h5>Public keys</h5>
|
||||
<p className="text-palette-500">
|
||||
Public keys provide read access to a selected list of skylinks. You can share them publicly.
|
||||
</p>
|
||||
|
||||
<div className="mt-4">
|
||||
<AddPublicAPIKeyForm ref={publicFormRef} onSuccess={refreshState} />
|
||||
</div>
|
||||
|
||||
{error ? (
|
||||
<Alert $variant="error" className="mt-4">
|
||||
An error occurred while loading your API keys. Please try again later.
|
||||
</Alert>
|
||||
) : (
|
||||
<div className="mt-4">
|
||||
{publicKeys?.length > 0 ? (
|
||||
<APIKeyList title="Your public keys" keys={publicKeys} reloadKeys={() => refreshState(true)} />
|
||||
) : (
|
||||
<Alert $variant="info">No public API keys found.</Alert>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
<hr />
|
||||
|
||||
<section className="flex flex-col gap-2">
|
||||
<h5>General keys</h5>
|
||||
<p className="text-palette-500">
|
||||
These keys provide full access to <b>Accounts</b> service and are equivalent to using a JWT token.
|
||||
</p>
|
||||
<p className="underline">
|
||||
This type of API keys needs to be kept secret and should never be shared with anyone.
|
||||
</p>
|
||||
|
||||
<div className="mt-4">
|
||||
<AddAPIKeyForm ref={generalFormRef} onSuccess={refreshState} type={APIKeyType.General} />
|
||||
</div>
|
||||
|
||||
{error ? (
|
||||
<Alert $variant="error" className="mt-4">
|
||||
An error occurred while loading your API keys. Please try again later.
|
||||
</Alert>
|
||||
) : (
|
||||
<div className="mt-4">
|
||||
{generalKeys?.length > 0 ? (
|
||||
<APIKeyList title="Your general keys" keys={generalKeys} reloadKeys={() => refreshState(true)} />
|
||||
) : (
|
||||
<Alert $variant="info">No general API keys found.</Alert>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
</div>
|
||||
<div className="hidden xl:block w-full text-right pt-16 pr-5">
|
||||
<img src="/images/api-keys.svg" alt="" className="inline-block h-[150px]" />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
APIKeysPage.Layout = UserSettingsLayout;
|
||||
|
||||
export default APIKeysPage;
|
|
@ -0,0 +1,117 @@
|
|||
import useSWR from "swr";
|
||||
import { useCallback, useRef } from "react";
|
||||
|
||||
import UserSettingsLayout from "../../layouts/UserSettingsLayout";
|
||||
|
||||
import { AddAPIKeyForm, APIKeyType } from "../../components/forms/AddAPIKeyForm";
|
||||
import { APIKeyList } from "../../components/APIKeyList/APIKeyList";
|
||||
import { Alert } from "../../components/Alert";
|
||||
import { AddSponsorKeyForm } from "../../components/forms/AddSponsorKeyForm";
|
||||
import { Metadata } from "../../components/Metadata";
|
||||
import HighlightedLink from "../../components/HighlightedLink";
|
||||
|
||||
import apiKeysImg from "../../../static/images/api-keys.svg";
|
||||
|
||||
const DeveloperSettingsPage = () => {
|
||||
const { data: allKeys = [], mutate: reloadKeys, error } = useSWR("user/apikeys");
|
||||
const apiKeys = allKeys.filter(({ public: isPublic }) => isPublic === "false");
|
||||
const sponsorKeys = allKeys.filter(({ public: isPublic }) => isPublic === "true");
|
||||
|
||||
const publicFormRef = useRef();
|
||||
const generalFormRef = useRef();
|
||||
|
||||
const refreshState = useCallback(
|
||||
(resetForms) => {
|
||||
if (resetForms) {
|
||||
publicFormRef.current?.reset();
|
||||
generalFormRef.current?.reset();
|
||||
}
|
||||
reloadKeys();
|
||||
},
|
||||
[reloadKeys]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Metadata>
|
||||
<title>Developer settings</title>
|
||||
</Metadata>
|
||||
<div className="flex flex-col xl:flex-row">
|
||||
<div className="flex flex-col gap-10 lg:shrink-0 lg:max-w-[576px] xl:max-w-[524px] leading-relaxed">
|
||||
<div>
|
||||
<h4>Developer settings</h4>
|
||||
<p>API keys allow developers and applications to extend the functionality of your portal account.</p>
|
||||
<p>Skynet uses two types of API keys, explained below.</p>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<section className="flex flex-col gap-2">
|
||||
<h5>Sponsor keys</h5>
|
||||
<div className="text-palette-500"></div>
|
||||
<p>
|
||||
Sponsor keys allow users without an account on this portal to download skylinks covered by the API key.
|
||||
</p>
|
||||
<p>
|
||||
Learn more about sponsoring content with Sponsor API Keys{" "}
|
||||
<HighlightedLink as="a" href="#">
|
||||
here
|
||||
</HighlightedLink>
|
||||
.
|
||||
</p>{" "}
|
||||
{/* TODO: missing documentation link */}
|
||||
<div className="mt-4">
|
||||
<AddSponsorKeyForm ref={publicFormRef} onSuccess={refreshState} />
|
||||
</div>
|
||||
{error ? (
|
||||
<Alert $variant="error" className="mt-4">
|
||||
An error occurred while loading your sponsor keys. Please try again later.
|
||||
</Alert>
|
||||
) : (
|
||||
<div className="mt-4">
|
||||
{sponsorKeys?.length > 0 ? (
|
||||
<APIKeyList title="Your public keys" keys={sponsorKeys} reloadKeys={() => refreshState(true)} />
|
||||
) : (
|
||||
<Alert $variant="info">No sponsor keys found.</Alert>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
|
||||
<hr />
|
||||
|
||||
<section className="flex flex-col gap-2">
|
||||
<h5>API keys</h5>
|
||||
<p className="text-palette-500">
|
||||
These keys allow uploading and downloading skyfiles, as well as reading and writing to the registry.
|
||||
</p>
|
||||
<div className="mt-4">
|
||||
<AddAPIKeyForm ref={generalFormRef} onSuccess={refreshState} type={APIKeyType.General} />
|
||||
</div>
|
||||
|
||||
{error ? (
|
||||
<Alert $variant="error" className="mt-4">
|
||||
An error occurred while loading your API keys. Please try again later.
|
||||
</Alert>
|
||||
) : (
|
||||
<div className="mt-4">
|
||||
{apiKeys?.length > 0 ? (
|
||||
<APIKeyList title="Your API keys" keys={apiKeys} reloadKeys={() => refreshState(true)} />
|
||||
) : (
|
||||
<Alert $variant="info">No API keys found.</Alert>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
</div>
|
||||
<div className="hidden xl:block w-full text-right pt-16 pr-5">
|
||||
<img src={apiKeysImg} alt="" className="inline-block h-[150px]" />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
DeveloperSettingsPage.Layout = UserSettingsLayout;
|
||||
|
||||
export default DeveloperSettingsPage;
|
|
@ -6,6 +6,8 @@ import { Switch } from "../../components/Switch";
|
|||
import { Button } from "../../components/Button";
|
||||
import { Metadata } from "../../components/Metadata";
|
||||
|
||||
import exportImg from "../../../static/images/import-export.svg";
|
||||
|
||||
const useExportOptions = () => {
|
||||
const [pinnedFiles, setPinnedFiles] = useState(false);
|
||||
const [uploadHistory, setUploadHistory] = useState(false);
|
||||
|
@ -38,8 +40,8 @@ const ExportPage = () => {
|
|||
<section>
|
||||
<h4>Export</h4>
|
||||
<p>
|
||||
Et quidem exercitus quid ex eo delectu rerum, quem modo ista sis aequitate. Probabo, inquit, modo dixi,
|
||||
constituto.
|
||||
Select the items you want to export. You can use this data to migrate your account to another Skynet
|
||||
portal.
|
||||
</p>
|
||||
</section>
|
||||
<hr />
|
||||
|
@ -65,7 +67,7 @@ const ExportPage = () => {
|
|||
</section>
|
||||
</div>
|
||||
<div className="hidden xl:block w-full text-right pt-20 pr-6">
|
||||
<img src="/images/import-export.svg" alt="" className="inline-block w-[200px]" />
|
||||
<img src={exportImg} alt="" className="inline-block w-[200px]" />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
|
|
@ -8,6 +8,10 @@ import { Modal } from "../../components/Modal/Modal";
|
|||
import { AccountRemovalForm } from "../../components/forms/AccountRemovalForm";
|
||||
import { Alert } from "../../components/Alert";
|
||||
import { Metadata } from "../../components/Metadata";
|
||||
import HighlightedLink from "../../components/HighlightedLink";
|
||||
import { AvatarUploader } from "../../components/AvatarUploader/AvatarUploader";
|
||||
import { useMedia } from "react-use";
|
||||
import theme from "../../lib/theme";
|
||||
|
||||
const State = {
|
||||
Pure: "PURE",
|
||||
|
@ -19,10 +23,16 @@ const AccountPage = () => {
|
|||
const { user, mutate: reloadUser } = useUser();
|
||||
const [state, setState] = useState(State.Pure);
|
||||
const [removalInitiated, setRemovalInitiated] = useState(false);
|
||||
const isLargeScreen = useMedia(`(min-width: ${theme.screens.xl})`);
|
||||
|
||||
const prompt = () => setRemovalInitiated(true);
|
||||
const abort = () => setRemovalInitiated(false);
|
||||
|
||||
const onAccountRemoved = useCallback(async () => {
|
||||
await reloadUser(null);
|
||||
await navigate("/auth/login");
|
||||
}, [reloadUser]);
|
||||
|
||||
const onSettingsUpdated = useCallback(
|
||||
async (updatedState) => {
|
||||
try {
|
||||
|
@ -45,14 +55,7 @@ const AccountPage = () => {
|
|||
</Metadata>
|
||||
<div className="flex flex-col xl:flex-row">
|
||||
<div className="flex flex-col gap-10 lg:shrink-0 lg:max-w-[576px] xl:max-w-[524px]">
|
||||
<section>
|
||||
<h4>Account</h4>
|
||||
<p>
|
||||
Tum dicere exorsus est laborum et quasi involuta aperiri, altera prompta et expedita. Primum igitur,
|
||||
inquit, modo ista sis aequitate.
|
||||
</p>
|
||||
</section>
|
||||
<hr />
|
||||
<h4>Account</h4>
|
||||
<section className="flex flex-col gap-8">
|
||||
{state === State.Failure && (
|
||||
<Alert $variant="error">There was an error processing your request. Please try again later.</Alert>
|
||||
|
@ -63,7 +66,23 @@ const AccountPage = () => {
|
|||
<hr />
|
||||
<section>
|
||||
<h6 className="text-palette-400">Delete account</h6>
|
||||
<p>This will completely delete your account. This process can't be undone.</p>
|
||||
<div className="my-4">
|
||||
<p>
|
||||
This action will delete your account and <strong>cannot be undone</strong>.
|
||||
</p>
|
||||
<p>
|
||||
Your uploaded files will remain accessible while any portal continues to{" "}
|
||||
<HighlightedLink
|
||||
as="a"
|
||||
href="https://support.skynetlabs.com/key-concepts/faqs#what-is-pinning"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
pin
|
||||
</HighlightedLink>{" "}
|
||||
them to Skynet.
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={prompt}
|
||||
|
@ -73,9 +92,12 @@ const AccountPage = () => {
|
|||
</button>
|
||||
</section>
|
||||
</div>
|
||||
<div className="flex w-full justify-start xl:justify-end">
|
||||
{isLargeScreen && <AvatarUploader className="flex flex-col gap-4" />}
|
||||
</div>
|
||||
{removalInitiated && (
|
||||
<Modal onClose={abort} className="text-center">
|
||||
<AccountRemovalForm abort={abort} onSuccess={() => navigate("/auth/login")} />
|
||||
<AccountRemovalForm abort={abort} onSuccess={onAccountRemoved} />
|
||||
</Modal>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import * as React from "react";
|
||||
import { StaticImage } from "gatsby-plugin-image";
|
||||
|
||||
import UserSettingsLayout from "../../layouts/UserSettingsLayout";
|
||||
|
||||
import { Switch } from "../../components/Switch";
|
||||
import { Metadata } from "../../components/Metadata";
|
||||
|
||||
import inboxImg from "../../../static/images/inbox.svg";
|
||||
|
||||
const NotificationsPage = () => {
|
||||
return (
|
||||
<>
|
||||
|
@ -18,18 +19,13 @@ const NotificationsPage = () => {
|
|||
<section>
|
||||
{/* TODO: saves on change */}
|
||||
<Switch onChange={console.info.bind(console)} labelClassName="!items-start flex-col md:flex-row">
|
||||
I agreee to get the latest news, updates and special offers delivered to my email inbox.
|
||||
I agree to receive emails of the latest news, updates and offers.
|
||||
</Switch>
|
||||
</section>
|
||||
<hr />
|
||||
<section>
|
||||
<h6 className="text-palette-300">Statistics</h6>
|
||||
{/* TODO: proper content :) */}
|
||||
<p>
|
||||
Si sine causa, nollem me tamen laudandis maioribus meis corrupisti nec in malis. Si sine causa, mox
|
||||
videro.
|
||||
</p>
|
||||
|
||||
<p>Check below to be notified by email when your usage approaches your plan's limits.</p>
|
||||
<ul className="mt-7 flex flex-col gap-2">
|
||||
<li>
|
||||
{/* TODO: saves on change */}
|
||||
|
@ -37,13 +33,13 @@ const NotificationsPage = () => {
|
|||
</li>
|
||||
<li>
|
||||
{/* TODO: saves on change */}
|
||||
<Switch onChange={console.info.bind(console)}>File limit</Switch>
|
||||
<Switch onChange={console.info.bind(console)}>Files limit</Switch>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
<div className="hidden xl:block text-right w-full pr-14 pt-20">
|
||||
<StaticImage src="../../../static/images/inbox.svg" alt="" placeholder="none" />
|
||||
<div className="hidden xl:block text-right w-full pl-12 pt-20">
|
||||
<img src={inboxImg} alt="" className="w-[200px]" />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import { SkynetClient } from "skynet-js";
|
||||
|
||||
export default new SkynetClient("https://skynetpro.net"); // TODO: proper API url
|
||||
export default new SkynetClient(`https://${process.env.GATSBY_PORTAL_DOMAIN}`);
|
||||
|
|
|
@ -6735,11 +6735,31 @@ dot-prop@^5.2.0:
|
|||
dependencies:
|
||||
is-obj "^2.0.0"
|
||||
|
||||
dotenv-cli@^5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/dotenv-cli/-/dotenv-cli-5.1.0.tgz#0d2942b089082da0157f9b26bd6c5c4dd51ef48e"
|
||||
integrity sha512-NoEZAlKo9WVrG0b3i9mBxdD6INdDuGqdgR74t68t8084QcI077/1MnPerRW1odl+9uULhcdnQp2U0pYVppKHOA==
|
||||
dependencies:
|
||||
cross-spawn "^7.0.3"
|
||||
dotenv "^16.0.0"
|
||||
dotenv-expand "^8.0.1"
|
||||
minimist "^1.2.5"
|
||||
|
||||
dotenv-expand@^5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0"
|
||||
integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==
|
||||
|
||||
dotenv-expand@^8.0.1:
|
||||
version "8.0.3"
|
||||
resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-8.0.3.tgz#29016757455bcc748469c83a19b36aaf2b83dd6e"
|
||||
integrity sha512-SErOMvge0ZUyWd5B0NXMQlDkN+8r+HhVUsxgOO7IoPDOdDRD2JjExpN6y3KnFR66jsJMwSn1pqIivhU5rcJiNg==
|
||||
|
||||
dotenv@^16.0.0:
|
||||
version "16.0.0"
|
||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.0.tgz#c619001253be89ebb638d027b609c75c26e47411"
|
||||
integrity sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q==
|
||||
|
||||
dotenv@^8.0.0, dotenv@^8.6.0:
|
||||
version "8.6.0"
|
||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b"
|
||||
|
|
|
@ -2,14 +2,19 @@ FROM node:16.14.2-alpine
|
|||
|
||||
WORKDIR /usr/app
|
||||
|
||||
COPY package.json yarn.lock ./
|
||||
COPY packages/dashboard/package.json \
|
||||
packages/dashboard/yarn.lock \
|
||||
./
|
||||
|
||||
ENV NEXT_TELEMETRY_DISABLED 1
|
||||
RUN yarn --frozen-lockfile
|
||||
|
||||
COPY public ./public
|
||||
COPY src ./src
|
||||
COPY styles ./styles
|
||||
COPY .eslintrc.json postcss.config.js tailwind.config.js ./
|
||||
COPY packages/dashboard/public ./public
|
||||
COPY packages/dashboard/src ./src
|
||||
COPY packages/dashboard/styles ./styles
|
||||
COPY packages/dashboard/.eslintrc.json \
|
||||
packages/dashboard/postcss.config.js \
|
||||
packages/dashboard/tailwind.config.js \
|
||||
./
|
||||
|
||||
CMD ["sh", "-c", "env | grep -E 'NEXT_PUBLIC|STRIPE|ACCOUNTS' > .env.local && yarn build && yarn start"]
|
||||
|
|
|
@ -10,25 +10,25 @@
|
|||
"dependencies": {
|
||||
"@fontsource/sora": "4.5.5",
|
||||
"@fontsource/source-sans-pro": "4.5.6",
|
||||
"@stripe/react-stripe-js": "1.7.1",
|
||||
"@stripe/react-stripe-js": "1.7.2",
|
||||
"@stripe/stripe-js": "1.27.0",
|
||||
"classnames": "2.3.1",
|
||||
"copy-text-to-clipboard": "^3.0.1",
|
||||
"dayjs": "1.11.0",
|
||||
"express-jwt": "6.1.1",
|
||||
"dayjs": "1.11.1",
|
||||
"express-jwt": "6.1.2",
|
||||
"fast-levenshtein": "3.0.0",
|
||||
"formik": "2.2.9",
|
||||
"http-status-codes": "2.2.0",
|
||||
"ky": "0.30.0",
|
||||
"next": "12.1.4",
|
||||
"next": "12.1.5",
|
||||
"normalize.css": "8.0.1",
|
||||
"pretty-bytes": "6.0.0",
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2",
|
||||
"react-toastify": "8.2.0",
|
||||
"skynet-js": "3.0.2",
|
||||
"stripe": "8.216.0",
|
||||
"swr": "1.2.2",
|
||||
"stripe": "8.218.0",
|
||||
"swr": "1.3.0",
|
||||
"yup": "0.32.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -36,9 +36,9 @@
|
|||
"@tailwindcss/typography": "0.5.2",
|
||||
"autoprefixer": "10.4.4",
|
||||
"eslint": "8.13.0",
|
||||
"eslint-config-next": "12.1.4",
|
||||
"eslint-config-next": "12.1.5",
|
||||
"postcss": "8.4.12",
|
||||
"prettier": "2.6.2",
|
||||
"tailwindcss": "3.0.23"
|
||||
"tailwindcss": "3.0.24"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,27 +2,6 @@
|
|||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@babel/code-frame@^7.0.0":
|
||||
version "7.14.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb"
|
||||
integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==
|
||||
dependencies:
|
||||
"@babel/highlight" "^7.14.5"
|
||||
|
||||
"@babel/helper-validator-identifier@^7.14.5":
|
||||
version "7.15.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389"
|
||||
integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==
|
||||
|
||||
"@babel/highlight@^7.14.5":
|
||||
version "7.14.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9"
|
||||
integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==
|
||||
dependencies:
|
||||
"@babel/helper-validator-identifier" "^7.14.5"
|
||||
chalk "^2.0.0"
|
||||
js-tokens "^4.0.0"
|
||||
|
||||
"@babel/runtime-corejs3@^7.10.2":
|
||||
version "7.16.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.16.3.tgz#1e25de4fa994c57c18e5fdda6cc810dac70f5590"
|
||||
|
@ -77,77 +56,77 @@
|
|||
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
|
||||
integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
|
||||
|
||||
"@next/env@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/env/-/env-12.1.4.tgz#5af629b43075281ecd7f87938802b7cf5b67e94b"
|
||||
integrity sha512-7gQwotJDKnfMxxXd8xJ2vsX5AzyDxO3zou0+QOXX8/unypA6icw5+wf6A62yKZ6qQ4UZHHxS68pb6UV+wNneXg==
|
||||
"@next/env@12.1.5":
|
||||
version "12.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/env/-/env-12.1.5.tgz#a21ba6708022d630402ca2b340316e69a0296dfc"
|
||||
integrity sha512-+34yUJslfJi7Lyx6ELuN8nWcOzi27izfYnZIC1Dqv7kmmfiBVxgzR3BXhlvEMTKC2IRJhXVs2FkMY+buQe3k7Q==
|
||||
|
||||
"@next/eslint-plugin-next@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-12.1.4.tgz#9c52637af8eecab24dac3f2e5098376f6fc2dff4"
|
||||
integrity sha512-BRy565KVK6Cdy8LHaHTiwctLqBu/RT84RLpESug70BDJzBlV8QBvODyx/j7wGhvYqp9kvstM05lyb6JaTkSCcQ==
|
||||
"@next/eslint-plugin-next@12.1.5":
|
||||
version "12.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-12.1.5.tgz#273885b35e6bbcd40ff1436d2a8d0ec03fb6f6ef"
|
||||
integrity sha512-Cnb8ERC5bNKBFrnMH6203sp/b0Y78QRx1XsFu+86oBtDBmQmOFoHu7teQjHm69ER73XKK3aGaeoLiXacHoUFsg==
|
||||
dependencies:
|
||||
glob "7.1.7"
|
||||
|
||||
"@next/swc-android-arm-eabi@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.1.4.tgz#c3dae178b7c15ad627d2e9b8dfb38caecb5c4ac7"
|
||||
integrity sha512-FJg/6a3s2YrUaqZ+/DJZzeZqfxbbWrynQMT1C5wlIEq9aDLXCFpPM/PiOyJh0ahxc0XPmi6uo38Poq+GJTuKWw==
|
||||
"@next/swc-android-arm-eabi@12.1.5":
|
||||
version "12.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.1.5.tgz#36729ab3dfd7743e82cfe536b43254dcb146620c"
|
||||
integrity sha512-SKnGTdYcoN04Y2DvE0/Y7/MjkA+ltsmbuH/y/hR7Ob7tsj+8ZdOYuk+YvW1B8dY20nDPHP58XgDTSm2nA8BzzA==
|
||||
|
||||
"@next/swc-android-arm64@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.1.4.tgz#f320d60639e19ecffa1f9034829f2d95502a9a51"
|
||||
integrity sha512-LXraazvQQFBgxIg3Htny6G5V5he9EK7oS4jWtMdTGIikmD/OGByOv8ZjLuVLZLtVm3UIvaAiGtlQSLecxJoJDw==
|
||||
"@next/swc-android-arm64@12.1.5":
|
||||
version "12.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.1.5.tgz#52578f552305c92d0b9b81d603c9643fb71e0835"
|
||||
integrity sha512-YXiqgQ/9Rxg1dXp6brXbeQM1JDx9SwUY/36JiE+36FXqYEmDYbxld9qkX6GEzkc5rbwJ+RCitargnzEtwGW0mw==
|
||||
|
||||
"@next/swc-darwin-arm64@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.1.4.tgz#fd578278312613eddcf3aee26910100509941b63"
|
||||
integrity sha512-SSST/dBymecllZxcqTCcSTCu5o1NKk9I+xcvhn/O9nH6GWjgvGgGkNqLbCarCa0jJ1ukvlBA138FagyrmZ/4rQ==
|
||||
"@next/swc-darwin-arm64@12.1.5":
|
||||
version "12.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.1.5.tgz#3d5b53211484c72074f4975ba0ec2b1107db300e"
|
||||
integrity sha512-y8mhldb/WFZ6lFeowkGfi0cO/lBdiBqDk4T4LZLvCpoQp4Or/NzUN6P5NzBQZ5/b4oUHM/wQICEM+1wKA4qIVw==
|
||||
|
||||
"@next/swc-darwin-x64@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.1.4.tgz#ace5f80d8c8348efe194f6d7074c6213c52b3944"
|
||||
integrity sha512-p1lwdX0TVjaoDXQVuAkjtxVBbCL/urgxiMCBwuPDO7TikpXtSRivi+mIzBj5q7ypgICFmIAOW3TyupXeoPRAnA==
|
||||
"@next/swc-darwin-x64@12.1.5":
|
||||
version "12.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.1.5.tgz#adcabb732d226453777c0d37d58eaff9328b66fd"
|
||||
integrity sha512-wqJ3X7WQdTwSGi0kIDEmzw34QHISRIQ5uvC+VXmsIlCPFcMA+zM5723uh8NfuKGquDMiEMS31a83QgkuHMYbwQ==
|
||||
|
||||
"@next/swc-linux-arm-gnueabihf@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.1.4.tgz#2bf2c83863635f19c71c226a2df936e001cce29c"
|
||||
integrity sha512-67PZlgkCn3TDxacdVft0xqDCL7Io1/C4xbAs0+oSQ0xzp6OzN2RNpuKjHJrJgKd0DsE1XZ9sCP27Qv0591yfyg==
|
||||
"@next/swc-linux-arm-gnueabihf@12.1.5":
|
||||
version "12.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.1.5.tgz#82a7cde67482b756bc65fbebf1dfa8a782074e93"
|
||||
integrity sha512-WnhdM5duONMvt2CncAl+9pim0wBxDS2lHoo7ub/o/i1bRbs11UTzosKzEXVaTDCUkCX2c32lIDi1WcN2ZPkcdw==
|
||||
|
||||
"@next/swc-linux-arm64-gnu@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.1.4.tgz#d577190f641c9b4b463719dd6b8953b6ba9be8d9"
|
||||
integrity sha512-OnOWixhhw7aU22TQdQLYrgpgFq0oA1wGgnjAiHJ+St7MLj82KTDyM9UcymAMbGYy6nG/TFOOHdTmRMtCRNOw0g==
|
||||
"@next/swc-linux-arm64-gnu@12.1.5":
|
||||
version "12.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.1.5.tgz#f82ca014504950aab751e81f467492e9be0bad5d"
|
||||
integrity sha512-Jq2H68yQ4bLUhR/XQnbw3LDW0GMQn355qx6rU36BthDLeGue7YV7MqNPa8GKvrpPocEMW77nWx/1yI6w6J07gw==
|
||||
|
||||
"@next/swc-linux-arm64-musl@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.1.4.tgz#e70ffe70393d8f9242deecdb282ce5a8fd588b14"
|
||||
integrity sha512-UoRMzPZnsAavdWtVylYxH8DNC7Uy0i6RrvNwT4PyQVdfANBn2omsUkcH5lgS2O7oaz0nAYLk1vqyZDO7+tJotA==
|
||||
"@next/swc-linux-arm64-musl@12.1.5":
|
||||
version "12.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.1.5.tgz#f811ec9f4b12a978426c284c95ab2f515ddf7f9e"
|
||||
integrity sha512-KgPjwdbhDqXI7ghNN8V/WAiLquc9Ebe8KBrNNEL0NQr+yd9CyKJ6KqjayVkmX+hbHzbyvbui/5wh/p3CZQ9xcQ==
|
||||
|
||||
"@next/swc-linux-x64-gnu@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.1.4.tgz#91498a130387fb1961902f2bee55863f8e910cff"
|
||||
integrity sha512-nM+MA/frxlTLUKLJKorctdI20/ugfHRjVEEkcLp/58LGG7slNaP1E5d5dRA1yX6ISjPcQAkywas5VlGCg+uTvA==
|
||||
"@next/swc-linux-x64-gnu@12.1.5":
|
||||
version "12.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.1.5.tgz#d44857257e6d20dc841998951d584ab1f25772c3"
|
||||
integrity sha512-O2ErUTvCJ6DkNTSr9pbu1n3tcqykqE/ebty1rwClzIYdOgpB3T2MfEPP+K7GhUR87wmN/hlihO9ch7qpVFDGKw==
|
||||
|
||||
"@next/swc-linux-x64-musl@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.1.4.tgz#78057b03c148c121553d41521ad38f6c732762ff"
|
||||
integrity sha512-GoRHxkuW4u4yKw734B9SzxJwVdyEJosaZ62P7ifOwcujTxhgBt3y76V2nNUrsSuopcKI2ZTDjaa+2wd5zyeXbA==
|
||||
"@next/swc-linux-x64-musl@12.1.5":
|
||||
version "12.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.1.5.tgz#3cc523abadc9a2a6de680593aff06e71cc29ecef"
|
||||
integrity sha512-1eIlZmlO/VRjxxzUBcVosf54AFU3ltAzHi+BJA+9U/lPxCYIsT+R4uO3QksRzRjKWhVQMRjEnlXyyq5SKJm7BA==
|
||||
|
||||
"@next/swc-win32-arm64-msvc@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.1.4.tgz#05bbaabacac23b8edf6caa99eb86b17550a09051"
|
||||
integrity sha512-6TQkQze0ievXwHJcVUrIULwCYVe3ccX6T0JgZ1SiMeXpHxISN7VJF/O8uSCw1JvXZYZ6ud0CJ7nfC5HXivgfPg==
|
||||
"@next/swc-win32-arm64-msvc@12.1.5":
|
||||
version "12.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.1.5.tgz#c62232d869f1f9b22e8f24e4e7f05307c20f30ca"
|
||||
integrity sha512-oromsfokbEuVb0CBLLE7R9qX3KGXucZpsojLpzUh1QJjuy1QkrPJncwr8xmWQnwgtQ6ecMWXgXPB+qtvizT9Tw==
|
||||
|
||||
"@next/swc-win32-ia32-msvc@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.1.4.tgz#8fd2fb48f04a2802e51fc320878bf6b411c1c866"
|
||||
integrity sha512-CsbX/IXuZ5VSmWCpSetG2HD6VO5FTsO39WNp2IR2Ut/uom9XtLDJAZqjQEnbUTLGHuwDKFjrIO3LkhtROXLE/g==
|
||||
"@next/swc-win32-ia32-msvc@12.1.5":
|
||||
version "12.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.1.5.tgz#2bd9b28a9ba730d12a493e7d9d18e150fe89d496"
|
||||
integrity sha512-a/51L5KzBpeZSW9LbekMo3I3Cwul+V+QKwbEIMA+Qwb2qrlcn1L9h3lt8cHqNTFt2y72ce6aTwDTw1lyi5oIRA==
|
||||
|
||||
"@next/swc-win32-x64-msvc@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.1.4.tgz#a72ed44c9b1f850986a30fe36c59e01f8a79b5f3"
|
||||
integrity sha512-JtYuWzKXKLDMgE/xTcFtCm1MiCIRaAc5XYZfYX3n/ZWSI1SJS/GMm+Su0SAHJgRFavJh6U/p998YwO/iGTIgqQ==
|
||||
"@next/swc-win32-x64-msvc@12.1.5":
|
||||
version "12.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.1.5.tgz#02f377e4d41eaaacf265e34bab9bacd8efc4a351"
|
||||
integrity sha512-/SoXW1Ntpmpw3AXAzfDRaQidnd8kbZ2oSni8u5z0yw6t4RwJvmdZy1eOaAADRThWKV+2oU90++LSnXJIwBRWYQ==
|
||||
|
||||
"@nodelib/fs.scandir@2.1.5":
|
||||
version "2.1.5"
|
||||
|
@ -175,10 +154,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.0.8.tgz#be3e914e84eacf16dbebd311c0d0b44aa1174c64"
|
||||
integrity sha512-ZK5v4bJwgXldAUA8r3q9YKfCwOqoHTK/ZqRjSeRXQrBXWouoPnS4MQtgC4AXGiiBuUu5wxrRgTlv0ktmM4P1Aw==
|
||||
|
||||
"@stripe/react-stripe-js@1.7.1":
|
||||
version "1.7.1"
|
||||
resolved "https://registry.yarnpkg.com/@stripe/react-stripe-js/-/react-stripe-js-1.7.1.tgz#6e1db8f4a0eaf2193b153173d4aa7c38b681310d"
|
||||
integrity sha512-GiUPoMo0xVvmpRD6JR9JAhAZ0W3ZpnYZNi0KE+91+tzrSFVpChKZbeSsJ5InlZhHFk9NckJCt1wOYBTqNsvt3A==
|
||||
"@stripe/react-stripe-js@1.7.2":
|
||||
version "1.7.2"
|
||||
resolved "https://registry.yarnpkg.com/@stripe/react-stripe-js/-/react-stripe-js-1.7.2.tgz#87cc5464378fb28bc7390702415cf70f13a46bcd"
|
||||
integrity sha512-IAVg2nPUPoSwI//XDRCO7D8mGeK4+N3Xg63fYZHmlfEWAuFVcuaqJKTT67uzIdKYZhHZ/NMdZw/ttz+GOjP/rQ==
|
||||
dependencies:
|
||||
prop-types "^15.7.2"
|
||||
|
||||
|
@ -218,11 +197,6 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.10.1.tgz#f3647623199ca920960006b3dccf633ea905f243"
|
||||
integrity sha512-4/Z9DMPKFexZj/Gn3LylFgamNKHm4K3QDi0gz9B26Uk0c8izYf97B5fxfpspMNkWlFupblKM/nV8+NA9Ffvr+w==
|
||||
|
||||
"@types/parse-json@^4.0.0":
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
|
||||
integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
|
||||
|
||||
"@typescript-eslint/parser@5.10.1":
|
||||
version "5.10.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.10.1.tgz#4ce9633cc33fc70bc13786cb793c1a76fe5ad6bd"
|
||||
|
@ -311,13 +285,6 @@ ansi-regex@^5.0.1:
|
|||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
|
||||
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
|
||||
|
||||
ansi-styles@^3.2.1:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
|
||||
integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
|
||||
dependencies:
|
||||
color-convert "^1.9.0"
|
||||
|
||||
ansi-styles@^4.1.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
|
||||
|
@ -390,10 +357,10 @@ ast-types-flow@^0.0.7:
|
|||
resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad"
|
||||
integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0=
|
||||
|
||||
async@^1.5.0:
|
||||
version "1.5.2"
|
||||
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
|
||||
integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=
|
||||
async@^3.2.2:
|
||||
version "3.2.3"
|
||||
resolved "https://registry.yarnpkg.com/async/-/async-3.2.3.tgz#ac53dafd3f4720ee9e8a160628f18ea91df196c9"
|
||||
integrity sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==
|
||||
|
||||
autoprefixer@10.4.4:
|
||||
version "10.4.4"
|
||||
|
@ -513,16 +480,7 @@ caniuse-lite@^1.0.30001283, caniuse-lite@^1.0.30001317:
|
|||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001319.tgz#eb4da4eb3ecdd409f7ba1907820061d56096e88f"
|
||||
integrity sha512-xjlIAFHucBRSMUo1kb5D4LYgcN1M45qdKP++lhqowDpwJwGkpIRTt5qQqnhxjj1vHcI7nrJxWhCC1ATrCEBTcw==
|
||||
|
||||
chalk@^2.0.0:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
|
||||
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
||||
dependencies:
|
||||
ansi-styles "^3.2.1"
|
||||
escape-string-regexp "^1.0.5"
|
||||
supports-color "^5.3.0"
|
||||
|
||||
chalk@^4.0.0, chalk@^4.1.2:
|
||||
chalk@^4.0.0:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
|
||||
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
|
||||
|
@ -555,13 +513,6 @@ clsx@^1.1.1:
|
|||
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188"
|
||||
integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==
|
||||
|
||||
color-convert@^1.9.0:
|
||||
version "1.9.3"
|
||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
|
||||
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
|
||||
dependencies:
|
||||
color-name "1.1.3"
|
||||
|
||||
color-convert@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
|
||||
|
@ -569,11 +520,6 @@ color-convert@^2.0.1:
|
|||
dependencies:
|
||||
color-name "~1.1.4"
|
||||
|
||||
color-name@1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
|
||||
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
|
||||
|
||||
color-name@^1.1.4, color-name@~1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
||||
|
@ -594,17 +540,6 @@ core-js-pure@^3.19.0:
|
|||
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.19.1.tgz#edffc1fc7634000a55ba05e95b3f0fe9587a5aa4"
|
||||
integrity sha512-Q0Knr8Es84vtv62ei6/6jXH/7izKmOrtrxH9WJTHLCMAVeU+8TF8z8Nr08CsH4Ot0oJKzBzJJL9SJBYIv7WlfQ==
|
||||
|
||||
cosmiconfig@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d"
|
||||
integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==
|
||||
dependencies:
|
||||
"@types/parse-json" "^4.0.0"
|
||||
import-fresh "^3.2.1"
|
||||
parse-json "^5.0.0"
|
||||
path-type "^4.0.0"
|
||||
yaml "^1.10.0"
|
||||
|
||||
cross-spawn@^7.0.2:
|
||||
version "7.0.3"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
|
||||
|
@ -624,10 +559,10 @@ damerau-levenshtein@^1.0.7:
|
|||
resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz#64368003512a1a6992593741a09a9d31a836f55d"
|
||||
integrity sha512-VvdQIPGdWP0SqFXghj79Wf/5LArmreyMsGLa6FG6iC4t3j7j5s71TrwWmT/4akbDQIqjfACkLZmjXhA7g2oUZw==
|
||||
|
||||
dayjs@1.11.0:
|
||||
version "1.11.0"
|
||||
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.0.tgz#009bf7ef2e2ea2d5db2e6583d2d39a4b5061e805"
|
||||
integrity sha512-JLC809s6Y948/FuCZPm5IX8rRhQwOiyMb2TfVVQEixG7P8Lm/gt5S7yoQZmC8x1UehI9Pb7sksEt4xx14m+7Ug==
|
||||
dayjs@1.11.1:
|
||||
version "1.11.1"
|
||||
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.1.tgz#90b33a3dda3417258d48ad2771b415def6545eb0"
|
||||
integrity sha512-ER7EjqVAMkRRsxNCC5YqJ9d9VQYuWdGt7aiH2qA5R5wt8ZmWaP2dLUSIK6y/kVzLMlmh1Tvu5xUf4M/wdGJ5KA==
|
||||
|
||||
debug@^2.6.9:
|
||||
version "2.6.9"
|
||||
|
@ -729,13 +664,6 @@ emoji-regex@^9.2.2:
|
|||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
|
||||
integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
|
||||
|
||||
error-ex@^1.3.1:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
|
||||
integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
|
||||
dependencies:
|
||||
is-arrayish "^0.2.1"
|
||||
|
||||
es-abstract@^1.19.0, es-abstract@^1.19.1:
|
||||
version "1.19.1"
|
||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3"
|
||||
|
@ -776,22 +704,17 @@ escalade@^3.1.1:
|
|||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
||||
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
|
||||
|
||||
escape-string-regexp@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
||||
|
||||
escape-string-regexp@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
|
||||
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
|
||||
|
||||
eslint-config-next@12.1.4:
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-12.1.4.tgz#939ea2ff33034763300bf1e62482cea91212d274"
|
||||
integrity sha512-Uj0jrVjoQbg9qerxRjSHoOOv3PEzoZxpb8G9LYct25fsflP8xIiUq0l4WEu2KSB5owuLv5hie7wSMqPEsHj+bQ==
|
||||
eslint-config-next@12.1.5:
|
||||
version "12.1.5"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-12.1.5.tgz#658cc61194a32dfd917a3db199351396ea5db1d1"
|
||||
integrity sha512-P+DCt5ti63KhC0qNLzrAmPcwRGq8pYqgcf/NNr1E+WjCrMkWdCAXkIANTquo+kcO1adR2k1lTo5GCrNUtKy4hQ==
|
||||
dependencies:
|
||||
"@next/eslint-plugin-next" "12.1.4"
|
||||
"@next/eslint-plugin-next" "12.1.5"
|
||||
"@rushstack/eslint-patch" "1.0.8"
|
||||
"@typescript-eslint/parser" "5.10.1"
|
||||
eslint-import-resolver-node "0.3.4"
|
||||
|
@ -997,12 +920,12 @@ esutils@^2.0.2:
|
|||
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
|
||||
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
|
||||
|
||||
express-jwt@6.1.1:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/express-jwt/-/express-jwt-6.1.1.tgz#2b157fb4fa33c2d367ee71c61b5aca762de39657"
|
||||
integrity sha512-m8gkY04v5jtiFZn6bYQINYX/DVXq1DVb5nIW7H8l87qJ4BBvtQKFRpxyRE31odct7OPfHdT+B8678zJHhlMrpw==
|
||||
express-jwt@6.1.2:
|
||||
version "6.1.2"
|
||||
resolved "https://registry.yarnpkg.com/express-jwt/-/express-jwt-6.1.2.tgz#4a6cc11d1dcff6f23126dd79ec5b2b441333e78b"
|
||||
integrity sha512-l5dlf5lNM/1EODMsJGfHn1VnrhhsUYEetzrKFStJZLjFQXtR+HGdBiW+jUNZ+ISsFe+h7Wl/hQKjLrY2TX0Qkg==
|
||||
dependencies:
|
||||
async "^1.5.0"
|
||||
async "^3.2.2"
|
||||
express-unless "^1.0.0"
|
||||
jsonwebtoken "^8.1.0"
|
||||
lodash "^4.17.21"
|
||||
|
@ -1213,11 +1136,6 @@ has-bigints@^1.0.1:
|
|||
resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113"
|
||||
integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==
|
||||
|
||||
has-flag@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
|
||||
integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
|
||||
|
||||
has-flag@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
|
||||
|
@ -1264,13 +1182,6 @@ ignore@^5.1.4, ignore@^5.2.0:
|
|||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a"
|
||||
integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==
|
||||
|
||||
import-cwd@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-3.0.0.tgz#20845547718015126ea9b3676b7592fb8bd4cf92"
|
||||
integrity sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==
|
||||
dependencies:
|
||||
import-from "^3.0.0"
|
||||
|
||||
import-fresh@^3.0.0, import-fresh@^3.2.1:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
|
||||
|
@ -1279,13 +1190,6 @@ import-fresh@^3.0.0, import-fresh@^3.2.1:
|
|||
parent-module "^1.0.0"
|
||||
resolve-from "^4.0.0"
|
||||
|
||||
import-from@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/import-from/-/import-from-3.0.0.tgz#055cfec38cd5a27d8057ca51376d7d3bf0891966"
|
||||
integrity sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ==
|
||||
dependencies:
|
||||
resolve-from "^5.0.0"
|
||||
|
||||
imurmurhash@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
||||
|
@ -1313,11 +1217,6 @@ internal-slot@^1.0.3:
|
|||
has "^1.0.3"
|
||||
side-channel "^1.0.4"
|
||||
|
||||
is-arrayish@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
|
||||
integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
|
||||
|
||||
is-bigint@^1.0.1:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3"
|
||||
|
@ -1434,7 +1333,7 @@ isexe@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||
integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
|
||||
|
||||
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
|
||||
"js-tokens@^3.0.0 || ^4.0.0":
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||
|
@ -1446,11 +1345,6 @@ js-yaml@^4.1.0:
|
|||
dependencies:
|
||||
argparse "^2.0.1"
|
||||
|
||||
json-parse-even-better-errors@^2.3.0:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
|
||||
integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
|
||||
|
||||
json-schema-traverse@^0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
|
||||
|
@ -1534,15 +1428,10 @@ levn@^0.4.1:
|
|||
prelude-ls "^1.2.1"
|
||||
type-check "~0.4.0"
|
||||
|
||||
lilconfig@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.3.tgz#68f3005e921dafbd2a2afb48379986aa6d2579fd"
|
||||
integrity sha512-EHKqr/+ZvdKCifpNrJCKxBTgk5XupZA3y/aCPY9mxfgBzmgh93Mt/WqjjQ38oMxXuvDokaKiM3lAgvSH2sjtHg==
|
||||
|
||||
lines-and-columns@^1.1.6:
|
||||
version "1.1.6"
|
||||
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
|
||||
integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=
|
||||
lilconfig@^2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.5.tgz#19e57fd06ccc3848fd1891655b5a447092225b25"
|
||||
integrity sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==
|
||||
|
||||
locate-path@^2.0.0:
|
||||
version "2.0.0"
|
||||
|
@ -1686,28 +1575,28 @@ natural-compare@^1.4.0:
|
|||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
|
||||
|
||||
next@12.1.4:
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/next/-/next-12.1.4.tgz#597a9bdec7aec778b442c4f6d41afd2c64a54b23"
|
||||
integrity sha512-DA4g97BM4Z0nKtDvCTm58RxdvoQyYzeg0AeVbh0N4Y/D8ELrNu47lQeEgRGF8hV4eQ+Sal90zxrJQQG/mPQ8CQ==
|
||||
next@12.1.5:
|
||||
version "12.1.5"
|
||||
resolved "https://registry.yarnpkg.com/next/-/next-12.1.5.tgz#7a07687579ddce61ee519493e1c178d83abac063"
|
||||
integrity sha512-YGHDpyfgCfnT5GZObsKepmRnne7Kzp7nGrac07dikhutWQug7hHg85/+sPJ4ZW5Q2pDkb+n0FnmLkmd44htIJQ==
|
||||
dependencies:
|
||||
"@next/env" "12.1.4"
|
||||
"@next/env" "12.1.5"
|
||||
caniuse-lite "^1.0.30001283"
|
||||
postcss "8.4.5"
|
||||
styled-jsx "5.0.1"
|
||||
optionalDependencies:
|
||||
"@next/swc-android-arm-eabi" "12.1.4"
|
||||
"@next/swc-android-arm64" "12.1.4"
|
||||
"@next/swc-darwin-arm64" "12.1.4"
|
||||
"@next/swc-darwin-x64" "12.1.4"
|
||||
"@next/swc-linux-arm-gnueabihf" "12.1.4"
|
||||
"@next/swc-linux-arm64-gnu" "12.1.4"
|
||||
"@next/swc-linux-arm64-musl" "12.1.4"
|
||||
"@next/swc-linux-x64-gnu" "12.1.4"
|
||||
"@next/swc-linux-x64-musl" "12.1.4"
|
||||
"@next/swc-win32-arm64-msvc" "12.1.4"
|
||||
"@next/swc-win32-ia32-msvc" "12.1.4"
|
||||
"@next/swc-win32-x64-msvc" "12.1.4"
|
||||
"@next/swc-android-arm-eabi" "12.1.5"
|
||||
"@next/swc-android-arm64" "12.1.5"
|
||||
"@next/swc-darwin-arm64" "12.1.5"
|
||||
"@next/swc-darwin-x64" "12.1.5"
|
||||
"@next/swc-linux-arm-gnueabihf" "12.1.5"
|
||||
"@next/swc-linux-arm64-gnu" "12.1.5"
|
||||
"@next/swc-linux-arm64-musl" "12.1.5"
|
||||
"@next/swc-linux-x64-gnu" "12.1.5"
|
||||
"@next/swc-linux-x64-musl" "12.1.5"
|
||||
"@next/swc-win32-arm64-msvc" "12.1.5"
|
||||
"@next/swc-win32-ia32-msvc" "12.1.5"
|
||||
"@next/swc-win32-x64-msvc" "12.1.5"
|
||||
|
||||
node-releases@^2.0.2:
|
||||
version "2.0.2"
|
||||
|
@ -1734,10 +1623,10 @@ object-assign@^4.1.1:
|
|||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||
|
||||
object-hash@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5"
|
||||
integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==
|
||||
object-hash@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9"
|
||||
integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==
|
||||
|
||||
object-inspect@^1.11.0, object-inspect@^1.9.0:
|
||||
version "1.11.0"
|
||||
|
@ -1839,16 +1728,6 @@ parent-module@^1.0.0:
|
|||
dependencies:
|
||||
callsites "^3.0.0"
|
||||
|
||||
parse-json@^5.0.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
|
||||
integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.0.0"
|
||||
error-ex "^1.3.1"
|
||||
json-parse-even-better-errors "^2.3.0"
|
||||
lines-and-columns "^1.1.6"
|
||||
|
||||
path-browserify@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd"
|
||||
|
@ -1896,13 +1775,12 @@ postcss-js@^4.0.0:
|
|||
dependencies:
|
||||
camelcase-css "^2.0.1"
|
||||
|
||||
postcss-load-config@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.0.tgz#d39c47091c4aec37f50272373a6a648ef5e97829"
|
||||
integrity sha512-ipM8Ds01ZUophjDTQYSVP70slFSYg3T0/zyfII5vzhN6V57YSxMgG5syXuwi5VtS8wSf3iL30v0uBdoIVx4Q0g==
|
||||
postcss-load-config@^3.1.4:
|
||||
version "3.1.4"
|
||||
resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.4.tgz#1ab2571faf84bb078877e1d07905eabe9ebda855"
|
||||
integrity sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==
|
||||
dependencies:
|
||||
import-cwd "^3.0.0"
|
||||
lilconfig "^2.0.3"
|
||||
lilconfig "^2.0.5"
|
||||
yaml "^1.10.2"
|
||||
|
||||
postcss-nested@5.0.6:
|
||||
|
@ -1912,10 +1790,10 @@ postcss-nested@5.0.6:
|
|||
dependencies:
|
||||
postcss-selector-parser "^6.0.6"
|
||||
|
||||
postcss-selector-parser@^6.0.6, postcss-selector-parser@^6.0.9:
|
||||
version "6.0.9"
|
||||
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz#ee71c3b9ff63d9cd130838876c13a2ec1a992b2f"
|
||||
integrity sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==
|
||||
postcss-selector-parser@^6.0.10, postcss-selector-parser@^6.0.6:
|
||||
version "6.0.10"
|
||||
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d"
|
||||
integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==
|
||||
dependencies:
|
||||
cssesc "^3.0.0"
|
||||
util-deprecate "^1.0.2"
|
||||
|
@ -1925,7 +1803,7 @@ postcss-value-parser@^4.2.0:
|
|||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
|
||||
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
||||
|
||||
postcss@8.4.12, postcss@^8.4.6:
|
||||
postcss@8.4.12, postcss@^8.4.12:
|
||||
version "8.4.12"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.12.tgz#1e7de78733b28970fa4743f7da6f3763648b1905"
|
||||
integrity sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg==
|
||||
|
@ -2075,11 +1953,6 @@ resolve-from@^4.0.0:
|
|||
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
|
||||
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
|
||||
|
||||
resolve-from@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
|
||||
integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
|
||||
|
||||
resolve@^1.13.1, resolve@^1.17.0, resolve@^1.20.0, resolve@^1.22.0:
|
||||
version "1.22.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198"
|
||||
|
@ -2248,10 +2121,10 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
|
|||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
|
||||
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
|
||||
|
||||
stripe@8.216.0:
|
||||
version "8.216.0"
|
||||
resolved "https://registry.yarnpkg.com/stripe/-/stripe-8.216.0.tgz#23c047498526d13a238c3aca7b4dc8cbbd522e46"
|
||||
integrity sha512-LY8cNGizEnklIa4T82l6mZW0HS4cfzo1hNuhT+ZR9PBkmYcSUbg3ilUBVF0FCd4RP+NA44VEVfoSTTZ1Gg5+rQ==
|
||||
stripe@8.218.0:
|
||||
version "8.218.0"
|
||||
resolved "https://registry.yarnpkg.com/stripe/-/stripe-8.218.0.tgz#c63e751acd1ab4ef833a65e3d7713f8565d71d81"
|
||||
integrity sha512-cH0CAep/x+N39dnfVKJxRpgPF5ggMR26Ckn0VkHH1rtFUspJzAEu4yTApSEszD2mirMK1gD42+oihJ1uJmbnUw==
|
||||
dependencies:
|
||||
"@types/node" ">=8.1.0"
|
||||
qs "^6.10.3"
|
||||
|
@ -2261,13 +2134,6 @@ styled-jsx@5.0.1:
|
|||
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.1.tgz#78fecbbad2bf95ce6cd981a08918ce4696f5fc80"
|
||||
integrity sha512-+PIZ/6Uk40mphiQJJI1202b+/dYeTVd9ZnMPR80pgiWbjIwvN2zIp4r9et0BgqBuShh48I0gttPlAXA7WVvBxw==
|
||||
|
||||
supports-color@^5.3.0:
|
||||
version "5.5.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
|
||||
integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
|
||||
dependencies:
|
||||
has-flag "^3.0.0"
|
||||
|
||||
supports-color@^7.1.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
|
||||
|
@ -2280,34 +2146,34 @@ supports-preserve-symlinks-flag@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
|
||||
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
|
||||
|
||||
swr@1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/swr/-/swr-1.2.2.tgz#6cae09928d30593a7980d80f85823e57468fac5d"
|
||||
integrity sha512-ky0BskS/V47GpW8d6RU7CPsr6J8cr7mQD6+do5eky3bM0IyJaoi3vO8UhvrzJaObuTlGhPl2szodeB2dUd76Xw==
|
||||
swr@1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/swr/-/swr-1.3.0.tgz#c6531866a35b4db37b38b72c45a63171faf9f4e8"
|
||||
integrity sha512-dkghQrOl2ORX9HYrMDtPa7LTVHJjCTeZoB1dqTbnnEDlSvN8JEKpYIYurDfvbQFUUS8Cg8PceFVZNkW0KNNYPw==
|
||||
|
||||
tailwindcss@3.0.23:
|
||||
version "3.0.23"
|
||||
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.0.23.tgz#c620521d53a289650872a66adfcb4129d2200d10"
|
||||
integrity sha512-+OZOV9ubyQ6oI2BXEhzw4HrqvgcARY38xv3zKcjnWtMIZstEsXdI9xftd1iB7+RbOnj2HOEzkA0OyB5BaSxPQA==
|
||||
tailwindcss@3.0.24:
|
||||
version "3.0.24"
|
||||
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.0.24.tgz#22e31e801a44a78a1d9a81ecc52e13b69d85704d"
|
||||
integrity sha512-H3uMmZNWzG6aqmg9q07ZIRNIawoiEcNFKDfL+YzOPuPsXuDXxJxB9icqzLgdzKNwjG3SAro2h9SYav8ewXNgig==
|
||||
dependencies:
|
||||
arg "^5.0.1"
|
||||
chalk "^4.1.2"
|
||||
chokidar "^3.5.3"
|
||||
color-name "^1.1.4"
|
||||
cosmiconfig "^7.0.1"
|
||||
detective "^5.2.0"
|
||||
didyoumean "^1.2.2"
|
||||
dlv "^1.1.3"
|
||||
fast-glob "^3.2.11"
|
||||
glob-parent "^6.0.2"
|
||||
is-glob "^4.0.3"
|
||||
lilconfig "^2.0.5"
|
||||
normalize-path "^3.0.0"
|
||||
object-hash "^2.2.0"
|
||||
postcss "^8.4.6"
|
||||
object-hash "^3.0.0"
|
||||
picocolors "^1.0.0"
|
||||
postcss "^8.4.12"
|
||||
postcss-js "^4.0.0"
|
||||
postcss-load-config "^3.1.0"
|
||||
postcss-load-config "^3.1.4"
|
||||
postcss-nested "5.0.6"
|
||||
postcss-selector-parser "^6.0.9"
|
||||
postcss-selector-parser "^6.0.10"
|
||||
postcss-value-parser "^4.2.0"
|
||||
quick-lru "^5.1.1"
|
||||
resolve "^1.22.0"
|
||||
|
@ -2456,7 +2322,7 @@ yallist@^4.0.0:
|
|||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
||||
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
||||
|
||||
yaml@^1.10.0, yaml@^1.10.2:
|
||||
yaml@^1.10.2:
|
||||
version "1.10.2"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
|
||||
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
"http-status-codes": "^2.2.0",
|
||||
"lodash": "^4.17.21",
|
||||
"lowdb": "^1.0.0",
|
||||
"skynet-js": "^4.0.19-beta",
|
||||
"skynet-js": "^4.1.0",
|
||||
"write-file-atomic": "^4.0.1",
|
||||
"yargs": "^17.4.1"
|
||||
},
|
||||
|
|
|
@ -515,6 +515,19 @@
|
|||
dependencies:
|
||||
"@sinonjs/commons" "^1.7.0"
|
||||
|
||||
"@skynetlabs/tus-js-client@^2.3.0":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@skynetlabs/tus-js-client/-/tus-js-client-2.3.0.tgz#a14fd4197e2bc4ce8be724967a0e4c17d937cb64"
|
||||
integrity sha512-piGvPlJh+Bu3Qf08bDlc/TnFLXE81KnFoPgvnsddNwTSLyyspxPFxJmHO5ki6SYyOl3HmUtGPoix+r2M2UpFEA==
|
||||
dependencies:
|
||||
buffer-from "^0.1.1"
|
||||
combine-errors "^3.0.3"
|
||||
is-stream "^2.0.0"
|
||||
js-base64 "^2.6.1"
|
||||
lodash.throttle "^4.1.1"
|
||||
proper-lockfile "^2.0.1"
|
||||
url-parse "^1.4.3"
|
||||
|
||||
"@szmarczak/http-timer@^4.0.5":
|
||||
version "4.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807"
|
||||
|
@ -736,17 +749,24 @@ array-flatten@1.1.1:
|
|||
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
|
||||
integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
|
||||
|
||||
async-mutex@^0.3.2:
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/async-mutex/-/async-mutex-0.3.2.tgz#1485eda5bda1b0ec7c8df1ac2e815757ad1831df"
|
||||
integrity sha512-HuTK7E7MT7jZEh1P9GtRW9+aTWiDWWi9InbZ5hjxrnRa39KS4BW04+xLBhYNS2aXhHUIKZSw3gj4Pn1pj+qGAA==
|
||||
dependencies:
|
||||
tslib "^2.3.1"
|
||||
|
||||
asynckit@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
|
||||
|
||||
axios@^0.24.0:
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6"
|
||||
integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==
|
||||
axios@^0.26.0:
|
||||
version "0.26.1"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.1.tgz#1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9"
|
||||
integrity sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==
|
||||
dependencies:
|
||||
follow-redirects "^1.14.4"
|
||||
follow-redirects "^1.14.8"
|
||||
|
||||
babel-jest@^27.5.1:
|
||||
version "27.5.1"
|
||||
|
@ -1407,10 +1427,10 @@ find-up@^4.0.0, find-up@^4.1.0:
|
|||
locate-path "^5.0.0"
|
||||
path-exists "^4.0.0"
|
||||
|
||||
follow-redirects@^1.14.4:
|
||||
version "1.14.8"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc"
|
||||
integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==
|
||||
follow-redirects@^1.14.8:
|
||||
version "1.14.9"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7"
|
||||
integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==
|
||||
|
||||
form-data@^3.0.0:
|
||||
version "3.0.1"
|
||||
|
@ -2410,10 +2430,10 @@ mime@1.6.0:
|
|||
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
|
||||
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
|
||||
|
||||
mime@^2.5.2:
|
||||
version "2.5.2"
|
||||
resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe"
|
||||
integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==
|
||||
mime@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7"
|
||||
integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==
|
||||
|
||||
mimic-fn@^2.1.0:
|
||||
version "2.1.0"
|
||||
|
@ -2896,24 +2916,25 @@ sjcl@^1.0.8:
|
|||
resolved "https://registry.yarnpkg.com/sjcl/-/sjcl-1.0.8.tgz#f2ec8d7dc1f0f21b069b8914a41a8f236b0e252a"
|
||||
integrity sha512-LzIjEQ0S0DpIgnxMEayM1rq9aGwGRG4OnZhCdjx7glTaJtf4zRfpg87ImfjSJjoW9vKpagd82McDOwbRT5kQKQ==
|
||||
|
||||
skynet-js@^4.0.19-beta:
|
||||
version "4.0.19-beta"
|
||||
resolved "https://registry.yarnpkg.com/skynet-js/-/skynet-js-4.0.19-beta.tgz#d4c640898c79cf69e45aa1c3c1ed5c80aa1aeced"
|
||||
integrity sha512-d8/q3E3OjUxgCCAW28gNFvbahj0ks8ym122XTopbRyvAZKk9+/Z4ians9v8Tov36Z4k/un+Ilw/0i6DtM8c8Dw==
|
||||
skynet-js@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/skynet-js/-/skynet-js-4.1.0.tgz#eccb84d04e9f42aa4f86ecb24fb4d59ed21e44cc"
|
||||
integrity sha512-VmUjJ9QnLpfuQA2j7vzFh8JvukjQlX4QLGw1HY3VyslFPj92vPpyO8gqjPfzgbkR05TXL7CbdqZoLZr/RBDZPw==
|
||||
dependencies:
|
||||
axios "^0.24.0"
|
||||
"@skynetlabs/tus-js-client" "^2.3.0"
|
||||
async-mutex "^0.3.2"
|
||||
axios "^0.26.0"
|
||||
base32-decode "^1.0.0"
|
||||
base32-encode "^1.1.1"
|
||||
base64-js "^1.3.1"
|
||||
blakejs "^1.1.0"
|
||||
buffer "^6.0.1"
|
||||
mime "^2.5.2"
|
||||
mime "^3.0.0"
|
||||
path-browserify "^1.0.1"
|
||||
post-me "^0.4.5"
|
||||
randombytes "^2.1.0"
|
||||
sjcl "^1.0.8"
|
||||
skynet-mysky-utils "^0.3.0"
|
||||
tus-js-client "^2.2.0"
|
||||
tweetnacl "^1.0.3"
|
||||
url-join "^4.0.1"
|
||||
url-parse "^1.5.1"
|
||||
|
@ -3120,18 +3141,10 @@ tr46@^2.1.0:
|
|||
dependencies:
|
||||
punycode "^2.1.1"
|
||||
|
||||
tus-js-client@^2.2.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/tus-js-client/-/tus-js-client-2.3.0.tgz#5d76145476cea46a4e7c045a0054637cddf8dc39"
|
||||
integrity sha512-I4cSwm6N5qxqCmBqenvutwSHe9ntf81lLrtf6BmLpG2v4wTl89atCQKqGgqvkodE6Lx+iKIjMbaXmfvStTg01g==
|
||||
dependencies:
|
||||
buffer-from "^0.1.1"
|
||||
combine-errors "^3.0.3"
|
||||
is-stream "^2.0.0"
|
||||
js-base64 "^2.6.1"
|
||||
lodash.throttle "^4.1.1"
|
||||
proper-lockfile "^2.0.1"
|
||||
url-parse "^1.4.3"
|
||||
tslib@^2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
|
||||
integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==
|
||||
|
||||
tweetnacl@^1.0.3:
|
||||
version "1.0.3"
|
||||
|
|
|
@ -12,45 +12,45 @@
|
|||
"classnames": "2.3.1",
|
||||
"copy-text-to-clipboard": "3.0.1",
|
||||
"crypto-browserify": "3.12.0",
|
||||
"framer-motion": "6.2.8",
|
||||
"gatsby": "4.11.2",
|
||||
"framer-motion": "6.3.0",
|
||||
"gatsby": "4.12.1",
|
||||
"gatsby-background-image": "1.6.0",
|
||||
"gatsby-plugin-image": "2.11.1",
|
||||
"gatsby-plugin-manifest": "4.11.1",
|
||||
"gatsby-plugin-postcss": "5.10.0",
|
||||
"gatsby-plugin-react-helmet": "5.10.0",
|
||||
"gatsby-plugin-robots-txt": "1.7.0",
|
||||
"gatsby-plugin-sharp": "4.10.2",
|
||||
"gatsby-plugin-sitemap": "5.11.1",
|
||||
"gatsby-plugin-image": "2.12.1",
|
||||
"gatsby-plugin-manifest": "4.12.1",
|
||||
"gatsby-plugin-postcss": "5.12.1",
|
||||
"gatsby-plugin-react-helmet": "5.12.1",
|
||||
"gatsby-plugin-robots-txt": "1.7.1",
|
||||
"gatsby-plugin-sharp": "4.12.1",
|
||||
"gatsby-plugin-sitemap": "5.12.1",
|
||||
"gatsby-plugin-svgr": "3.0.0-beta.0",
|
||||
"gatsby-source-filesystem": "4.10.1",
|
||||
"gatsby-transformer-sharp": "4.10.0",
|
||||
"gatsby-transformer-yaml": "4.11.0",
|
||||
"gatsby-source-filesystem": "4.12.1",
|
||||
"gatsby-transformer-sharp": "4.12.1",
|
||||
"gatsby-transformer-yaml": "4.12.1",
|
||||
"gbimage-bridge": "0.2.1",
|
||||
"http-status-codes": "2.2.0",
|
||||
"ms": "2.1.3",
|
||||
"nanoid": "3.3.2",
|
||||
"nanoid": "3.3.3",
|
||||
"normalize.css": "8.0.1",
|
||||
"path-browserify": "1.0.1",
|
||||
"polished": "4.2.1",
|
||||
"polished": "4.2.2",
|
||||
"postcss": "8.4.12",
|
||||
"prop-types": "15.8.1",
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2",
|
||||
"react-dropzone": "12.0.4",
|
||||
"react-dropzone": "12.0.5",
|
||||
"react-helmet": "6.1.0",
|
||||
"react-use": "17.3.2",
|
||||
"skynet-js": "4.0.26-beta",
|
||||
"skynet-js": "4.1.0",
|
||||
"stream-browserify": "3.0.0",
|
||||
"swr": "1.2.2"
|
||||
"swr": "1.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/typography": "0.5.2",
|
||||
"autoprefixer": "10.4.4",
|
||||
"cross-env": "7.0.3",
|
||||
"cypress": "9.5.2",
|
||||
"cypress": "9.5.4",
|
||||
"prettier": "2.6.2",
|
||||
"tailwindcss": "3.0.23"
|
||||
"tailwindcss": "3.0.24"
|
||||
},
|
||||
"keywords": [
|
||||
"gatsby"
|
||||
|
|
|
@ -2594,10 +2594,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39"
|
||||
integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==
|
||||
|
||||
"@types/sharp@^0.29.5":
|
||||
version "0.29.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/sharp/-/sharp-0.29.5.tgz#9c7032d30d138ad16dde6326beaff2af757b91b3"
|
||||
integrity sha512-3TC+S3H5RwnJmLYMHrcdfNjz/CaApKmujjY9b6PU/pE6n0qfooi99YqXGWoW8frU9EWYj/XTI35Pzxa+ThAZ5Q==
|
||||
"@types/sharp@^0.30.0":
|
||||
version "0.30.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/sharp/-/sharp-0.30.2.tgz#df5ff34140b3bad165482e6f3d26b08e42a0503a"
|
||||
integrity sha512-uLCBwjDg/BTcQit0dpNGvkIjvH3wsb8zpaJePCjvONBBSfaKHoxXBIuq1MT8DMQEfk2fKYnpC9QExCgFhkGkMQ==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
|
@ -3339,23 +3339,23 @@ babel-plugin-polyfill-regenerator@^0.3.0:
|
|||
dependencies:
|
||||
"@babel/helper-define-polyfill-provider" "^0.3.1"
|
||||
|
||||
babel-plugin-remove-graphql-queries@^4.11.1:
|
||||
version "4.11.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-remove-graphql-queries/-/babel-plugin-remove-graphql-queries-4.11.1.tgz#6f107865e8c1a83807c4b48b2262f5e0e0ba537e"
|
||||
integrity sha512-Bqbeow4Xf+Vm4YhAucRGJjf9pNAXakSndYiLKfvef/W6mdtBh00SM8FMaX0U3rtR7ZUXV63RmIyOybVQ6SWCyg==
|
||||
babel-plugin-remove-graphql-queries@^4.12.1:
|
||||
version "4.12.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-remove-graphql-queries/-/babel-plugin-remove-graphql-queries-4.12.1.tgz#08e7531ed3c61aaa3c2f083ddce8040844e611d4"
|
||||
integrity sha512-z4Z0VkDpmoIW3cihPYEb+HJMgwa+RF77LnpgAC6y6ozS76ci3ENqfIry/vvdD6auys5TG3xYZ0eHpdPobXzhfA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.15.4"
|
||||
gatsby-core-utils "^3.11.1"
|
||||
gatsby-core-utils "^3.12.1"
|
||||
|
||||
babel-plugin-transform-react-remove-prop-types@^0.4.24:
|
||||
version "0.4.24"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a"
|
||||
integrity sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==
|
||||
|
||||
babel-preset-gatsby@^2.11.1:
|
||||
version "2.11.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-preset-gatsby/-/babel-preset-gatsby-2.11.1.tgz#860d8d9903df38c314fa6f0cfdb197d02555c4e4"
|
||||
integrity sha512-NGUNAIb3hzD1Mt97q5T3gSSuVuaqnYFSm7AvgByDa3Mk2ohF5Ni86sCLVPRIntIzJvgU5OWY4Qz+6rrI1SwprQ==
|
||||
babel-preset-gatsby@^2.12.1:
|
||||
version "2.12.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-preset-gatsby/-/babel-preset-gatsby-2.12.1.tgz#33d904dc54d5395e049fb346015eba1dbd62bfbf"
|
||||
integrity sha512-ozpDqxxQa32gZVeXO07S0jLJvfewzMLAytP6QHJvVlHEcDnfo7sTo/r3ZNm+2SzeHP51eTDuTFo46WWQnY5kMw==
|
||||
dependencies:
|
||||
"@babel/plugin-proposal-class-properties" "^7.14.0"
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator" "^7.14.5"
|
||||
|
@ -3370,8 +3370,8 @@ babel-preset-gatsby@^2.11.1:
|
|||
babel-plugin-dynamic-import-node "^2.3.3"
|
||||
babel-plugin-macros "^2.8.0"
|
||||
babel-plugin-transform-react-remove-prop-types "^0.4.24"
|
||||
gatsby-core-utils "^3.11.1"
|
||||
gatsby-legacy-polyfills "^2.11.0"
|
||||
gatsby-core-utils "^3.12.1"
|
||||
gatsby-legacy-polyfills "^2.12.1"
|
||||
|
||||
backo2@^1.0.2, backo2@~1.0.2:
|
||||
version "1.0.2"
|
||||
|
@ -3566,7 +3566,7 @@ braces@^2.3.1:
|
|||
split-string "^3.0.2"
|
||||
to-regex "^3.0.1"
|
||||
|
||||
braces@^3.0.1, braces@~3.0.2:
|
||||
braces@^3.0.2, braces@~3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
|
||||
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
|
||||
|
@ -4340,10 +4340,10 @@ create-ecdh@^4.0.0:
|
|||
bn.js "^4.1.0"
|
||||
elliptic "^6.5.3"
|
||||
|
||||
create-gatsby@^2.11.2:
|
||||
version "2.11.2"
|
||||
resolved "https://registry.yarnpkg.com/create-gatsby/-/create-gatsby-2.11.2.tgz#b932bb16f024c929c4597225771275d54f3541bc"
|
||||
integrity sha512-EHlULRVoiXoLM400sLYNtFRy5pemp2WoNKR6vjUlFnLBqn+BGe+TJAmKfwqHYFheXMozKqY2bW0ekuDj2x8zAg==
|
||||
create-gatsby@^2.12.1:
|
||||
version "2.12.1"
|
||||
resolved "https://registry.yarnpkg.com/create-gatsby/-/create-gatsby-2.12.1.tgz#da5ab2b6dde54d62ec853b699c5aceafb0f166a2"
|
||||
integrity sha512-dOsEy9feLJVFVzFFnA6xJL9OhfYcKewaGMqI9uUaUdifIehBjb5jdeWi+cNy49j2FQLMm38jfZ2SNSQjEK2yOw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.15.4"
|
||||
|
||||
|
@ -4613,10 +4613,10 @@ custom-error-instance@2.1.1:
|
|||
resolved "https://registry.yarnpkg.com/custom-error-instance/-/custom-error-instance-2.1.1.tgz#3cf6391487a6629a6247eb0ca0ce00081b7e361a"
|
||||
integrity sha1-PPY5FIemYppiR+sMoM4ACBt+Nho=
|
||||
|
||||
cypress@9.5.2:
|
||||
version "9.5.2"
|
||||
resolved "https://registry.yarnpkg.com/cypress/-/cypress-9.5.2.tgz#8fb6ee4a890fbc35620800810bf6fb11995927bd"
|
||||
integrity sha512-gYiQYvJozMzDOriUV1rCt6CeRM/pRK4nhwGJj3nJQyX2BoUdTCVwp30xDMKc771HiNVhBtgj5o5/iBdVDVXQUg==
|
||||
cypress@9.5.4:
|
||||
version "9.5.4"
|
||||
resolved "https://registry.yarnpkg.com/cypress/-/cypress-9.5.4.tgz#49d9272f62eba12f2314faf29c2a865610e87550"
|
||||
integrity sha512-6AyJAD8phe7IMvOL4oBsI9puRNOWxZjl8z1lgixJMcgJ85JJmyKeP6uqNA0dI1z14lmJ7Qklf2MOgP/xdAqJ/Q==
|
||||
dependencies:
|
||||
"@cypress/request" "^2.88.10"
|
||||
"@cypress/xvfb" "^1.2.4"
|
||||
|
@ -4650,7 +4650,7 @@ cypress@9.5.2:
|
|||
listr2 "^3.8.3"
|
||||
lodash "^4.17.21"
|
||||
log-symbols "^4.0.0"
|
||||
minimist "^1.2.5"
|
||||
minimist "^1.2.6"
|
||||
ospath "^1.2.2"
|
||||
pretty-bytes "^5.6.0"
|
||||
proxy-from-env "1.0.0"
|
||||
|
@ -4710,10 +4710,10 @@ debug@^3.0.0, debug@^3.1.0, debug@^3.2.6, debug@^3.2.7:
|
|||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@~4.3.1:
|
||||
version "4.3.3"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664"
|
||||
integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==
|
||||
debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@~4.3.1:
|
||||
version "4.3.4"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
|
@ -5384,15 +5384,15 @@ eslint-plugin-jsx-a11y@^6.5.1:
|
|||
language-tags "^1.0.5"
|
||||
minimatch "^3.0.4"
|
||||
|
||||
eslint-plugin-react-hooks@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz#318dbf312e06fab1c835a4abef00121751ac1172"
|
||||
integrity sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA==
|
||||
eslint-plugin-react-hooks@^4.4.0:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.4.0.tgz#71c39e528764c848d8253e1aa2c7024ed505f6c4"
|
||||
integrity sha512-U3RVIfdzJaeKDQKEJbz5p3NW8/L80PCATJAfuojwbaEL+gBjfGdhUcGde+WGUW46Q5sr/NgxevsIiDtNXrvZaQ==
|
||||
|
||||
eslint-plugin-react@^7.29.2:
|
||||
version "7.29.2"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.29.2.tgz#2d4da69d30d0a736efd30890dc6826f3e91f3f7c"
|
||||
integrity sha512-ypEBTKOy5liFQXZWMchJ3LN0JX1uPI6n7MN7OPHKacqXAxq5gYC30TdO7wqGYQyxD1OrzpobdHC3hDmlRWDg9w==
|
||||
eslint-plugin-react@^7.29.4:
|
||||
version "7.29.4"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.29.4.tgz#4717de5227f55f3801a5fd51a16a4fa22b5914d2"
|
||||
integrity sha512-CVCXajliVh509PcZYRFyu/BoUEz452+jtQJq2b3Bae4v3xBUWPLCmtmBM+ZinG4MzwmxJgJ2M5rMqhqLVn7MtQ==
|
||||
dependencies:
|
||||
array-includes "^3.1.4"
|
||||
array.prototype.flatmap "^1.2.5"
|
||||
|
@ -6068,10 +6068,10 @@ fragment-cache@^0.2.1:
|
|||
dependencies:
|
||||
map-cache "^0.2.2"
|
||||
|
||||
framer-motion@6.2.8:
|
||||
version "6.2.8"
|
||||
resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-6.2.8.tgz#02abb529191af7e2df444185fe27e932215b715d"
|
||||
integrity sha512-4PtBWFJ6NqR350zYVt9AsFDtISTqsdqna79FvSYPfYDXuuqFmiKtZdkTnYPslnsOMedTW0pEvaQ7eqjD+sA+HA==
|
||||
framer-motion@6.3.0:
|
||||
version "6.3.0"
|
||||
resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-6.3.0.tgz#0e50ef04b4fa070fca7d04bc32fb1d64027b7ea7"
|
||||
integrity sha512-Nm6l2cemuFeSC1fmq9R32sCQs1eplOuZ3r14/PxRDewpE3NUr+ul5ulGRRzk8K0Aa5p76Tedi3sfCUaTPa5fRg==
|
||||
dependencies:
|
||||
framesync "6.0.1"
|
||||
hey-listen "^1.0.8"
|
||||
|
@ -6158,10 +6158,10 @@ gatsby-background-image@1.6.0:
|
|||
short-uuid "^4.2.0"
|
||||
sort-media-queries "^0.2.2"
|
||||
|
||||
gatsby-cli@^4.11.2:
|
||||
version "4.11.2"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-cli/-/gatsby-cli-4.11.2.tgz#0bd5c218f378edb0e674f7ba7a903be202fe3620"
|
||||
integrity sha512-MypoVvMwWcDEtf5JTm1UTdGeOavRjnNRKfuUqvbhvb+q1vQ2xIFhu/pK9sdOlQfL6v6Fl8xwO2FuOfz+i53z3w==
|
||||
gatsby-cli@^4.12.1:
|
||||
version "4.12.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-cli/-/gatsby-cli-4.12.1.tgz#157d6dbe783102248af2c938816a58401afeb64b"
|
||||
integrity sha512-vlSqri0p9HpLfACFtUCJhxQArzxSvdcUkrN4Jlw8RgeJYxcJyb8VPPDJHJT3rMGRKZFeBaAeqMbqx/eK4K5F1w==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.14.0"
|
||||
"@babel/core" "^7.15.5"
|
||||
|
@ -6179,13 +6179,13 @@ gatsby-cli@^4.11.2:
|
|||
common-tags "^1.8.2"
|
||||
configstore "^5.0.1"
|
||||
convert-hrtime "^3.0.0"
|
||||
create-gatsby "^2.11.2"
|
||||
create-gatsby "^2.12.1"
|
||||
envinfo "^7.8.1"
|
||||
execa "^5.1.1"
|
||||
fs-exists-cached "^1.0.0"
|
||||
fs-extra "^10.0.0"
|
||||
gatsby-core-utils "^3.11.1"
|
||||
gatsby-telemetry "^3.11.1"
|
||||
gatsby-core-utils "^3.12.1"
|
||||
gatsby-telemetry "^3.12.1"
|
||||
hosted-git-info "^3.0.8"
|
||||
is-valid-path "^0.1.1"
|
||||
joi "^17.4.2"
|
||||
|
@ -6209,10 +6209,10 @@ gatsby-cli@^4.11.2:
|
|||
yoga-layout-prebuilt "^1.10.0"
|
||||
yurnalist "^2.1.0"
|
||||
|
||||
gatsby-core-utils@^3.10.1, gatsby-core-utils@^3.11.1, gatsby-core-utils@^3.8.2:
|
||||
version "3.11.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-core-utils/-/gatsby-core-utils-3.11.1.tgz#ea87c1d3aa45c26c9ea32b8e8b029afe6a56f8c7"
|
||||
integrity sha512-Op9/uihtcsDLlZDfRsGJ1ya2mFx2YH9Zmx93bawElZ0YpIzKjCkNTp+I5i5UANxvs5I+Fljl0WHQRudMWg+fWA==
|
||||
gatsby-core-utils@^3.12.1, gatsby-core-utils@^3.8.2:
|
||||
version "3.12.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-core-utils/-/gatsby-core-utils-3.12.1.tgz#590ec08de7168b086b7d49128732b9ada95b985f"
|
||||
integrity sha512-jBG1MfR6t2MZNIl8LQ3Cwc92F6uFNcEC091IK+qKVy9FNT0+WzcKQ6Olip6u1NSvCatfrg1FqrH0K78a6lmnLQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.15.4"
|
||||
ci-info "2.0.0"
|
||||
|
@ -6222,7 +6222,7 @@ gatsby-core-utils@^3.10.1, gatsby-core-utils@^3.11.1, gatsby-core-utils@^3.8.2:
|
|||
fs-extra "^10.0.0"
|
||||
got "^11.8.3"
|
||||
import-from "^4.0.0"
|
||||
lmdb "^2.2.4"
|
||||
lmdb "^2.2.6"
|
||||
lock "^1.1.0"
|
||||
node-object-hash "^2.3.10"
|
||||
proper-lockfile "^4.1.2"
|
||||
|
@ -6230,49 +6230,49 @@ gatsby-core-utils@^3.10.1, gatsby-core-utils@^3.11.1, gatsby-core-utils@^3.8.2:
|
|||
tmp "^0.2.1"
|
||||
xdg-basedir "^4.0.0"
|
||||
|
||||
gatsby-graphiql-explorer@^2.11.0:
|
||||
version "2.11.0"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-graphiql-explorer/-/gatsby-graphiql-explorer-2.11.0.tgz#7e886846482ad72bd49f515e7faa658a94342803"
|
||||
integrity sha512-nMNXlF/pleO/rH66t00SdXdKq3vV0/Su5EEQY7xg3yRc38ueC2UkZq10nrJiVoc05RO8Txo5o2gpoC2DP07lFg==
|
||||
gatsby-graphiql-explorer@^2.12.1:
|
||||
version "2.12.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-graphiql-explorer/-/gatsby-graphiql-explorer-2.12.1.tgz#4fad5b9a3ccbcc4871f70222e8ac1ca880ff844d"
|
||||
integrity sha512-H5phTjIGUiUZxN3C0hogH66lB+qC9HO9O4m4RpHZ3JyxVIvPemGSNmgovhL7+LydS34UY5rbT0UBFwaxrHMZpQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.15.4"
|
||||
|
||||
gatsby-legacy-polyfills@^2.11.0:
|
||||
version "2.11.0"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-legacy-polyfills/-/gatsby-legacy-polyfills-2.11.0.tgz#8b2afc4d97f44eb5767fe9b49f55ff675055ffd2"
|
||||
integrity sha512-ulkRNCitwFjwUM4f2ufljH0WjELm6QEIOGRryNRt9LKJEB9QGmdm+KUAWIv7xrFUqKq1Pn6is64wcfXDw21zSA==
|
||||
gatsby-legacy-polyfills@^2.12.1:
|
||||
version "2.12.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-legacy-polyfills/-/gatsby-legacy-polyfills-2.12.1.tgz#62ad6432b3c17f7f5640786ed00dba88da60ab22"
|
||||
integrity sha512-x2Njk0GsBKsiVBDZHI7nVWDNBPQeonQsElzFEDoSJpW47j9H8PPJDeOUZ+u5q76rtxuQQo/VXl/eD817qRBxAA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.15.4"
|
||||
core-js-compat "3.9.0"
|
||||
|
||||
gatsby-link@^4.11.1:
|
||||
version "4.11.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-link/-/gatsby-link-4.11.1.tgz#f8bfee4c7f3bf0ede255bddf87d0f13c64ed39f2"
|
||||
integrity sha512-wOhdgsnzHr4iYWo3iKadw8jj5PmIu1wbi6LUftwQzFOFvkBaJvC/br1ju8W0nbwSjWG474hTZRon43xDQX9bIw==
|
||||
gatsby-link@^4.12.1:
|
||||
version "4.12.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-link/-/gatsby-link-4.12.1.tgz#131448e9c51e0c9a65e2a342603d496e85cea2da"
|
||||
integrity sha512-ILWYNqyTlEt2bOVWgzwmbijwC+Ow4CZVbnWOyaQ/jvu5z3ZGL0z5tGGD+sjZAHc8anOMWn/JWhL0BKGVaxjMGQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.15.4"
|
||||
"@types/reach__router" "^1.3.10"
|
||||
gatsby-page-utils "^2.11.1"
|
||||
gatsby-page-utils "^2.12.1"
|
||||
prop-types "^15.7.2"
|
||||
|
||||
gatsby-page-utils@^2.11.1:
|
||||
version "2.11.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-page-utils/-/gatsby-page-utils-2.11.1.tgz#dd10f99184b64528ae76f2b654b8ed1b23cb9c39"
|
||||
integrity sha512-K1Mbk4CKYZwpJcE4zk4JAff7ZBNFXI0fC8lZwLbDAzVcqYUaouqqqnoU7WeB8HHUqDQi05CXItx1bbZFDGIymw==
|
||||
gatsby-page-utils@^2.12.1:
|
||||
version "2.12.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-page-utils/-/gatsby-page-utils-2.12.1.tgz#ee5dbd21b8e22003e5b0c7e4d86ed3b89773c0ac"
|
||||
integrity sha512-2NPfVHRoHYcqUZrGVAvHN28uqI/PTGE/DrpE79YR/blbnloEzwzpAGNbBjWitgcR0st5q5NrATJQ/Imu3M7ApA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.15.4"
|
||||
bluebird "^3.7.2"
|
||||
chokidar "^3.5.2"
|
||||
fs-exists-cached "^1.0.0"
|
||||
gatsby-core-utils "^3.11.1"
|
||||
gatsby-core-utils "^3.12.1"
|
||||
glob "^7.2.0"
|
||||
lodash "^4.17.21"
|
||||
micromatch "^4.0.4"
|
||||
micromatch "^4.0.5"
|
||||
|
||||
gatsby-parcel-config@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-parcel-config/-/gatsby-parcel-config-0.2.0.tgz#0b1795d17c825bd293c372fa0acfa987aa91111e"
|
||||
integrity sha512-BbsSm5O0R7IvCRLNSk3lBpkU8RtSOn8s7Ifa7bHF63PzTG1SUpBjwMF6301tCbvdSXWrP7n9dsfaXS6ex/TElQ==
|
||||
gatsby-parcel-config@^0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-parcel-config/-/gatsby-parcel-config-0.3.1.tgz#424c7b3d65b60e2e454cd9d61d4c5de752aad576"
|
||||
integrity sha512-Wpz6DSKiWeqVyZUNmO7EHy0h9ISG+HfUD8v2g0kN4ZcZjJtSiWvGym1+6Swgjo9bQvy59qa7bO4hKGA9gHvMVg==
|
||||
dependencies:
|
||||
"@gatsbyjs/parcel-namer-relative-to-cwd" "0.0.2"
|
||||
"@parcel/bundler-default" "^2.3.2"
|
||||
|
@ -6292,109 +6292,109 @@ gatsby-parcel-config@^0.2.0:
|
|||
"@parcel/transformer-raw" "^2.3.2"
|
||||
"@parcel/transformer-react-refresh-wrap" "^2.3.2"
|
||||
|
||||
gatsby-plugin-image@2.11.1:
|
||||
version "2.11.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-image/-/gatsby-plugin-image-2.11.1.tgz#1e800b65e8c18cc524c5855b9dbdb907745fdb0c"
|
||||
integrity sha512-4tfDdcczBVOL6ELKNWuXQ9h1V/5DhBMIVHmr6FPwm8xgL8ARqfQMXX2mzUjpNiu7WDiMlm9cWrTQQaZAARhAwg==
|
||||
gatsby-plugin-image@2.12.1:
|
||||
version "2.12.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-image/-/gatsby-plugin-image-2.12.1.tgz#302324125a1e018ff669772495f4b291bd00a832"
|
||||
integrity sha512-Azofblt5ZSk2NqCOrBI1WijcJw6dVHCKz85lz6J7qB3Fvy+YVjs/vbUODlXUwi3926Q5m7C2zdH0MQrk4T0DDQ==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.14.0"
|
||||
"@babel/parser" "^7.15.5"
|
||||
"@babel/runtime" "^7.15.4"
|
||||
"@babel/traverse" "^7.15.4"
|
||||
babel-jsx-utils "^1.1.0"
|
||||
babel-plugin-remove-graphql-queries "^4.11.1"
|
||||
babel-plugin-remove-graphql-queries "^4.12.1"
|
||||
camelcase "^5.3.1"
|
||||
chokidar "^3.5.2"
|
||||
common-tags "^1.8.2"
|
||||
fs-extra "^10.0.0"
|
||||
gatsby-core-utils "^3.11.1"
|
||||
gatsby-core-utils "^3.12.1"
|
||||
objectFitPolyfill "^2.3.5"
|
||||
prop-types "^15.7.2"
|
||||
prop-types "^15.8.1"
|
||||
|
||||
gatsby-plugin-manifest@4.11.1:
|
||||
version "4.11.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-manifest/-/gatsby-plugin-manifest-4.11.1.tgz#fb3061c2e989acb2634719c1e8645fd1388f4b3b"
|
||||
integrity sha512-m5cdi6KBc8+zmnlIfEh92sXpFEUfjuCrjM5BKc8e6v0jxJS0CqVrZOyT12mT2yq9H12UrkzFx1qaI8e2/IJiGA==
|
||||
gatsby-plugin-manifest@4.12.1:
|
||||
version "4.12.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-manifest/-/gatsby-plugin-manifest-4.12.1.tgz#25342272c03fdce95901eb42a3ece09f12e4be4a"
|
||||
integrity sha512-AZ0vtO/+khtpum4VUX/Gj/oRer6ckcEfVU/DNd3QlpG7ucHSzHKSwSLP6F5kevCHo7DS4hCMV8RixPlcv0ePWA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.15.4"
|
||||
gatsby-core-utils "^3.11.1"
|
||||
gatsby-plugin-utils "^3.5.1"
|
||||
gatsby-core-utils "^3.12.1"
|
||||
gatsby-plugin-utils "^3.6.1"
|
||||
semver "^7.3.5"
|
||||
sharp "^0.30.1"
|
||||
sharp "^0.30.3"
|
||||
|
||||
gatsby-plugin-page-creator@^4.11.1:
|
||||
version "4.11.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-page-creator/-/gatsby-plugin-page-creator-4.11.1.tgz#750f4b773684777cec6caa9266787427ed2630a6"
|
||||
integrity sha512-6XET4qYqu2yVwUU6sO44wSR62zQZdq7BoMvN9OhKpUDBZYLfve9CwufkhZZnQvq+axNZZMUmKa/RqbBXiE6/yA==
|
||||
gatsby-plugin-page-creator@^4.12.1:
|
||||
version "4.12.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-page-creator/-/gatsby-plugin-page-creator-4.12.1.tgz#36460f5308df8b04bb2b0649150cb87e3eb15c8f"
|
||||
integrity sha512-McVYpXWgneo1+3+8KGrGATgNwAYtZXbFKL8Q18lwH+bt5f2NbYP23g+xGitxT62zvhhzs0AjuEJa7BoTEmFTMQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.15.4"
|
||||
"@babel/traverse" "^7.15.4"
|
||||
"@sindresorhus/slugify" "^1.1.2"
|
||||
chokidar "^3.5.2"
|
||||
fs-exists-cached "^1.0.0"
|
||||
gatsby-core-utils "^3.11.1"
|
||||
gatsby-page-utils "^2.11.1"
|
||||
gatsby-plugin-utils "^3.5.1"
|
||||
gatsby-telemetry "^3.11.1"
|
||||
globby "^11.0.4"
|
||||
gatsby-core-utils "^3.12.1"
|
||||
gatsby-page-utils "^2.12.1"
|
||||
gatsby-plugin-utils "^3.6.1"
|
||||
gatsby-telemetry "^3.12.1"
|
||||
globby "^11.1.0"
|
||||
lodash "^4.17.21"
|
||||
|
||||
gatsby-plugin-postcss@5.10.0:
|
||||
version "5.10.0"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-postcss/-/gatsby-plugin-postcss-5.10.0.tgz#e241f1671e66f7b660826f39fd26591aae652716"
|
||||
integrity sha512-s1zzysu1kKIqR+CfQeQsG0CCdj2S7tjc4BhCY2a3V4cl7ORJtMx1HGKDUzE9gV/EXRTmr9lhE9Gl+2v8fRouvA==
|
||||
gatsby-plugin-postcss@5.12.1:
|
||||
version "5.12.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-postcss/-/gatsby-plugin-postcss-5.12.1.tgz#8be5cf7bbfbb27967cad2c5da8dbe1b8c7e576b8"
|
||||
integrity sha512-gNfMl/ZWCZpnCsy+IPzRPzqaPPStbUr/LG8eikGbyoZj1gSjom/a7Hi3z29sWx/vEd4dAHGRPS+n7bjf3iOnNw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.15.4"
|
||||
postcss-loader "^4.3.0"
|
||||
|
||||
gatsby-plugin-react-helmet@5.10.0:
|
||||
version "5.10.0"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-react-helmet/-/gatsby-plugin-react-helmet-5.10.0.tgz#d6491d35d4b4e3bb36631c1a93f4e53913f42cbb"
|
||||
integrity sha512-QcypYLqnwKoD84f9c6Yfajs/sLfVmxPSOPWwHaK+3NG1IjmmQrL42qn2CP6gs29WznGzrThGeGiwIVdA5x31JA==
|
||||
gatsby-plugin-react-helmet@5.12.1:
|
||||
version "5.12.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-react-helmet/-/gatsby-plugin-react-helmet-5.12.1.tgz#98205abb73cd7a522f2891b3a42514ae2b41ca57"
|
||||
integrity sha512-lW9uRpkccSj0NC41dunFM4AoDuQockgpWHcvLivzGWMnWYtGWPNci7zy8+NUL1+6CchQqWTr0LZEeGYgpHym+w==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.15.4"
|
||||
|
||||
gatsby-plugin-robots-txt@1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-robots-txt/-/gatsby-plugin-robots-txt-1.7.0.tgz#58ac310c9fb7e58162d6e21802884b342837b451"
|
||||
integrity sha512-Y1D8FBeXNtECoCd0g0jIkhKpSvzFzeh2xpt1xTvGluRP6xmqJq7iB3DPEv7xqGlZAcfzaSxw/j5++Y+3WLva8A==
|
||||
gatsby-plugin-robots-txt@1.7.1:
|
||||
version "1.7.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-robots-txt/-/gatsby-plugin-robots-txt-1.7.1.tgz#f956729e34f6269cc314352e9ef1cf7b4c515a68"
|
||||
integrity sha512-ZdZm8/4b7Whf+W5kf+DqjZwz/+DY+IB7xp227+m2f2rgGUsz8yVCz4RitiN5+EInGFZFry0v+IbrUKCXTpIZYg==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.16.7"
|
||||
generate-robotstxt "^8.0.3"
|
||||
|
||||
gatsby-plugin-sharp@4.10.2:
|
||||
version "4.10.2"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-sharp/-/gatsby-plugin-sharp-4.10.2.tgz#253a49c452a7409ceece4e541e4770e61a306bcc"
|
||||
integrity sha512-MWzPTYnu7HZ0kctHtkLbZOe6ZGUqSsNATO3lWlSBIFpeimxaPF5iHBiu1CX/ofz4pwt7VamtIzAV28VB6sjONw==
|
||||
gatsby-plugin-sharp@4.12.1:
|
||||
version "4.12.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-sharp/-/gatsby-plugin-sharp-4.12.1.tgz#f97cb29074f4a07b469b9ddb1058a3574928d4eb"
|
||||
integrity sha512-P6noUl5LyASwYtCRSo1rjchk/ytfJvSFTLwzgXr1TiQHgZh06SUIqR8v3UqT90EDERNd1GeEBsQjRfWkrV2nbg==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.15.4"
|
||||
async "^3.2.3"
|
||||
bluebird "^3.7.2"
|
||||
debug "^4.3.3"
|
||||
debug "^4.3.4"
|
||||
filenamify "^4.3.0"
|
||||
fs-extra "^10.0.0"
|
||||
gatsby-core-utils "^3.10.1"
|
||||
gatsby-plugin-utils "^3.4.2"
|
||||
gatsby-telemetry "^3.10.1"
|
||||
gatsby-core-utils "^3.12.1"
|
||||
gatsby-plugin-utils "^3.6.1"
|
||||
gatsby-telemetry "^3.12.1"
|
||||
got "^11.8.3"
|
||||
lodash "^4.17.21"
|
||||
mini-svg-data-uri "^1.4.3"
|
||||
mini-svg-data-uri "^1.4.4"
|
||||
potrace "^2.1.8"
|
||||
probe-image-size "^7.0.0"
|
||||
probe-image-size "^7.2.3"
|
||||
progress "^2.0.3"
|
||||
semver "^7.3.5"
|
||||
sharp "^0.30.1"
|
||||
sharp "^0.30.3"
|
||||
svgo "1.3.2"
|
||||
uuid "3.4.0"
|
||||
|
||||
gatsby-plugin-sitemap@5.11.1:
|
||||
version "5.11.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-sitemap/-/gatsby-plugin-sitemap-5.11.1.tgz#863397fe9dd5aab89bda8db09ef9b877c960150e"
|
||||
integrity sha512-tt92KLUDS+eCrqSA5oYieDGjXLyUDXfYKEwLhYKXk7KlMMjporFJWVrc4Ba8WD04bUWVnzc2rqr19/zQI0ZIpQ==
|
||||
gatsby-plugin-sitemap@5.12.1:
|
||||
version "5.12.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-sitemap/-/gatsby-plugin-sitemap-5.12.1.tgz#782a926a558d31663d4a8e66b9466c86df278568"
|
||||
integrity sha512-Njdx91OF4xiFqHSSA3Yrnzxm4qu4xHyrhkiwQniFncoIGMI6IXqk9aDoxo3E1jZDWGPsI/2gzdcd8dBNQq9juA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.15.4"
|
||||
common-tags "^1.8.2"
|
||||
minimatch "^3.0.4"
|
||||
minimatch "^3.1.2"
|
||||
sitemap "^7.0.0"
|
||||
|
||||
gatsby-plugin-svgr@3.0.0-beta.0:
|
||||
|
@ -6402,10 +6402,10 @@ gatsby-plugin-svgr@3.0.0-beta.0:
|
|||
resolved "https://registry.yarnpkg.com/gatsby-plugin-svgr/-/gatsby-plugin-svgr-3.0.0-beta.0.tgz#7e5315f51dae2663a447899322ea1487cef93dd6"
|
||||
integrity sha512-oALTh6VwO6l3khgC/vGr706aqt38EkXwdr6iXVei/auOKGxpCLEuDCQVal1a4SpYXdjHjRsEyab6bxaHL2lzsA==
|
||||
|
||||
gatsby-plugin-typescript@^4.11.1:
|
||||
version "4.11.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-typescript/-/gatsby-plugin-typescript-4.11.1.tgz#dcd96ded685f8c4a73ae5524faab342f9c9e3c1d"
|
||||
integrity sha512-6ef2wRhPqcLPyekEAU3xcoqI59r+mDnCzn/O+8hRgwJyx/2dwvF8brusetXoqdTk4Vyhk44p8dog8+gCGATckw==
|
||||
gatsby-plugin-typescript@^4.12.1:
|
||||
version "4.12.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-typescript/-/gatsby-plugin-typescript-4.12.1.tgz#8fe51b57f1fca5027f5dd558b73364a4c34a0a38"
|
||||
integrity sha512-7ZzGTL+hNGGmiIk4j4QSZYyYsy4i9EW/zgK/IJwmpSBNzoagI/Pz64ntNWpxZstfgzkuIYZfvuvj3Ao9mKF5aw==
|
||||
dependencies:
|
||||
"@babel/core" "^7.15.5"
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator" "^7.14.5"
|
||||
|
@ -6413,48 +6413,48 @@ gatsby-plugin-typescript@^4.11.1:
|
|||
"@babel/plugin-proposal-optional-chaining" "^7.14.5"
|
||||
"@babel/preset-typescript" "^7.15.0"
|
||||
"@babel/runtime" "^7.15.4"
|
||||
babel-plugin-remove-graphql-queries "^4.11.1"
|
||||
babel-plugin-remove-graphql-queries "^4.12.1"
|
||||
|
||||
gatsby-plugin-utils@^3.4.2, gatsby-plugin-utils@^3.5.1:
|
||||
version "3.5.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-utils/-/gatsby-plugin-utils-3.5.1.tgz#9aed9deec0f4ee82bfc7390f735b9455ca4f8494"
|
||||
integrity sha512-RZXUvwQjTnkukMfAGr+DCz/qZj7g6REljTmQS43MaovWO4Yf4YGvs+1Leays7J0XmqN2I3SIZGBgt4tgKCsNVQ==
|
||||
gatsby-plugin-utils@^3.6.1:
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-utils/-/gatsby-plugin-utils-3.6.1.tgz#31d742e1aded08439ad42959880821e1fc9740cd"
|
||||
integrity sha512-Ebk98v4mxaDWjGFl6VBeNv1zjeJ7UCQ29UTabzY2BpztvUCBHfLVQdMmuaAgzPRn+A3SFVOGpcl++CF0IEl+7A==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.15.4"
|
||||
fs-extra "^10.0.0"
|
||||
gatsby-core-utils "^3.11.1"
|
||||
gatsby-sharp "^0.5.0"
|
||||
gatsby-core-utils "^3.12.1"
|
||||
gatsby-sharp "^0.6.1"
|
||||
graphql-compose "^9.0.7"
|
||||
import-from "^4.0.0"
|
||||
joi "^17.4.2"
|
||||
mime "^3.0.0"
|
||||
|
||||
gatsby-react-router-scroll@^5.11.0:
|
||||
version "5.11.0"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-react-router-scroll/-/gatsby-react-router-scroll-5.11.0.tgz#866b89366146d8df3852ed699d12be1e9fce4acc"
|
||||
integrity sha512-g/lyG0X73cpI9DdYvCv5rZiV8LqHjn6q1l8Vfm/jBS7wtv8XxNR4BxUqkbMeHRcvZcX5bXku6FFSFUAOd9c3QQ==
|
||||
gatsby-react-router-scroll@^5.12.1:
|
||||
version "5.12.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-react-router-scroll/-/gatsby-react-router-scroll-5.12.1.tgz#10fdf43c1179ae53e7726c6c8d894139e7862e8f"
|
||||
integrity sha512-zZCTiicALh6eSsQAgIhSCmQm6Dl6fY6eaKmOXGMMbVtUKmiGxikh2MFN6S5J5JU9MV/piSheVqYkouyTDGXbuw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.15.4"
|
||||
prop-types "^15.7.2"
|
||||
prop-types "^15.8.1"
|
||||
|
||||
gatsby-sharp@^0.5.0:
|
||||
version "0.5.0"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-sharp/-/gatsby-sharp-0.5.0.tgz#879d3c462eefa917cb3a50c6ec891951d9740f56"
|
||||
integrity sha512-9wZS0ADZsKTCsU66sxIP/tCHgFaREyoYm53tepgtp/YSVWNrurx9/0kGf8XsFFY9OecrqIRNuk1cWe7XKCpbQA==
|
||||
gatsby-sharp@^0.6.1:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-sharp/-/gatsby-sharp-0.6.1.tgz#48805690cb020111722cc25445b4b662446da6d0"
|
||||
integrity sha512-KhBFE72QLlrAgeMWNoBV2LDp0nZ9ZOw1pY5wIohb/ktDFRUi9K5nwVCJvDJonfPn100mxtDqnZVckXirtcHVzQ==
|
||||
dependencies:
|
||||
"@types/sharp" "^0.29.5"
|
||||
sharp "^0.30.1"
|
||||
"@types/sharp" "^0.30.0"
|
||||
sharp "^0.30.3"
|
||||
|
||||
gatsby-source-filesystem@4.10.1:
|
||||
version "4.10.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-source-filesystem/-/gatsby-source-filesystem-4.10.1.tgz#c513fadb3cedb138ff28ba351ffd264524a0c28d"
|
||||
integrity sha512-qdOWS234l6QyEN0M8tfdGQF530pK9nSiaT1JfSzZV7Bl9psX9SdsuOtfZ2AV0QVt1BQB7C53E/BNGaxMLCcnUg==
|
||||
gatsby-source-filesystem@4.12.1:
|
||||
version "4.12.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-source-filesystem/-/gatsby-source-filesystem-4.12.1.tgz#86f45cc047b0b9ca06b5e4ef5c48e69fa3ec2206"
|
||||
integrity sha512-lbtKa7oR2Q+8Qa8gZych/JaRBeoIW/dk4rfy13DOrSgUJK9gZFkpLuFQ471Z0JiHitDPswienBW60HjYvymOCw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.15.4"
|
||||
chokidar "^3.5.2"
|
||||
file-type "^16.5.3"
|
||||
fs-extra "^10.0.0"
|
||||
gatsby-core-utils "^3.10.1"
|
||||
gatsby-core-utils "^3.12.1"
|
||||
got "^9.6.0"
|
||||
md5-file "^5.0.0"
|
||||
mime "^2.5.2"
|
||||
|
@ -6463,10 +6463,10 @@ gatsby-source-filesystem@4.10.1:
|
|||
valid-url "^1.0.9"
|
||||
xstate "^4.26.1"
|
||||
|
||||
gatsby-telemetry@^3.10.1, gatsby-telemetry@^3.11.1:
|
||||
version "3.11.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-telemetry/-/gatsby-telemetry-3.11.1.tgz#87caed899143276056e9af20ab38c15ad9dcdf52"
|
||||
integrity sha512-TPNKTpuYFyULOuRvhpXUtj8h2E7bvrTYsRC/aKeHoWqEchwwbzPwBSJd+3ZFjsxLHIXAa5sTAlR2wd9SYBgOlA==
|
||||
gatsby-telemetry@^3.12.1:
|
||||
version "3.12.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-telemetry/-/gatsby-telemetry-3.12.1.tgz#a3508a45d95f2c3457db7dbe2628560d00c43beb"
|
||||
integrity sha512-sAL2T9GdYpceGlFP6CymVDoy0UEhRvrJApv/mu7sU6F0gu8g8rOLvRxVYE3Y2D9RdfCzkuLIonzmscmVIduyOg==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.14.0"
|
||||
"@babel/runtime" "^7.15.4"
|
||||
|
@ -6476,48 +6476,48 @@ gatsby-telemetry@^3.10.1, gatsby-telemetry@^3.11.1:
|
|||
boxen "^4.2.0"
|
||||
configstore "^5.0.1"
|
||||
fs-extra "^10.0.0"
|
||||
gatsby-core-utils "^3.11.1"
|
||||
gatsby-core-utils "^3.12.1"
|
||||
git-up "^4.0.5"
|
||||
is-docker "^2.2.1"
|
||||
lodash "^4.17.21"
|
||||
node-fetch "^2.6.7"
|
||||
|
||||
gatsby-transformer-sharp@4.10.0:
|
||||
version "4.10.0"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-transformer-sharp/-/gatsby-transformer-sharp-4.10.0.tgz#9db793a219d0fa85b7d33cb37b32aba63df4c58a"
|
||||
integrity sha512-Gp9eRkGQOrkoD+yJgK2ZdXuVbet/opxdEnuTZ6BhLEVhfTwOnMEaui6ZqO0cKJ7/NYlptO38p+C5cyizC0FRYA==
|
||||
gatsby-transformer-sharp@4.12.1:
|
||||
version "4.12.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-transformer-sharp/-/gatsby-transformer-sharp-4.12.1.tgz#e26dc3540e97fc1c802518967c1e8d8a4ed96fae"
|
||||
integrity sha512-14AGG10Jf7ZBWxJDN2jSupAsBofoGU+p7+QJRzDrKdJrzp9v/yO/1xPB+r7UxtlW0l8cqPT6UyCITvJbWTDaww==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.15.4"
|
||||
bluebird "^3.7.2"
|
||||
common-tags "^1.8.2"
|
||||
fs-extra "^10.0.0"
|
||||
potrace "^2.1.8"
|
||||
probe-image-size "^7.0.0"
|
||||
probe-image-size "^7.2.3"
|
||||
semver "^7.3.5"
|
||||
sharp "^0.30.1"
|
||||
sharp "^0.30.3"
|
||||
|
||||
gatsby-transformer-yaml@4.11.0:
|
||||
version "4.11.0"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-transformer-yaml/-/gatsby-transformer-yaml-4.11.0.tgz#900bf446ce7aece9253f46244519ccb5bd8cf7f2"
|
||||
integrity sha512-GTCkULgOxbyRbovO9VHi0P+7iv/fEQG3uBeKiJyvMRUDD4bIQ9uIdT7hZ1RPwctu9dpt9T/X7kx+CShRzmELYw==
|
||||
gatsby-transformer-yaml@4.12.1:
|
||||
version "4.12.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-transformer-yaml/-/gatsby-transformer-yaml-4.12.1.tgz#0c372c25304d3305b3dcdc2b39c08e059d8f3d74"
|
||||
integrity sha512-mpliK4YDMDBUe+g6JO6B8qhQffbBLoJI9q/4ja4YSbY/Jaj2tv/tkhepuwxOMuUwmQcBRu+OQ5J0RNiCI1aUcQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.15.4"
|
||||
js-yaml "^3.14.1"
|
||||
lodash "^4.17.21"
|
||||
unist-util-select "^1.5.0"
|
||||
|
||||
gatsby-worker@^1.11.0:
|
||||
version "1.11.0"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-worker/-/gatsby-worker-1.11.0.tgz#bf8c3b9374390260b8335d7cfccbc332d0716727"
|
||||
integrity sha512-uJ5bNrifIrS20o0SYkmb379logfRKO35cqYxd2R0uNf9kWGaQOda0SZfm7Uw+Vdx7cO9Ra8p1ArijbHm7ZArCA==
|
||||
gatsby-worker@^1.12.1:
|
||||
version "1.12.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-worker/-/gatsby-worker-1.12.1.tgz#553a0fd5ad796567fc3ab965490270ff7b0ae680"
|
||||
integrity sha512-9slhXsK1/N4nJK+Yia84PL/zvNqV/bqD820W4R2f5jh5gEnVYrY2TcnG6A+UDbY7orhS0CLf1mMW9WKd6u6CUA==
|
||||
dependencies:
|
||||
"@babel/core" "^7.15.5"
|
||||
"@babel/runtime" "^7.15.4"
|
||||
|
||||
gatsby@4.11.2:
|
||||
version "4.11.2"
|
||||
resolved "https://registry.yarnpkg.com/gatsby/-/gatsby-4.11.2.tgz#fba8843316992e2f0eafc5ae3ee6fb37ce7aa953"
|
||||
integrity sha512-kJ2gHQzO3efV1BaynGfxi0divFOorUqxKom/QdIEnaj9VMkNRnrpNxUNsT4ljq+d9BTlq/0AAIpGNQZKC1ZgFg==
|
||||
gatsby@4.12.1:
|
||||
version "4.12.1"
|
||||
resolved "https://registry.yarnpkg.com/gatsby/-/gatsby-4.12.1.tgz#b9a72bca167662a05d7154e5e6091f31aa333efd"
|
||||
integrity sha512-/QteQShPAW1dRmG9wrjHmdfQEQxh6WfOi9jnJXAxljAx8UlRt0JFntxMc9gWGUJD6fXYKmf13Jan9izuNDQxNQ==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.14.0"
|
||||
"@babel/core" "^7.15.5"
|
||||
|
@ -6544,8 +6544,8 @@ gatsby@4.11.2:
|
|||
babel-plugin-add-module-exports "^1.0.4"
|
||||
babel-plugin-dynamic-import-node "^2.3.3"
|
||||
babel-plugin-lodash "^3.3.4"
|
||||
babel-plugin-remove-graphql-queries "^4.11.1"
|
||||
babel-preset-gatsby "^2.11.1"
|
||||
babel-plugin-remove-graphql-queries "^4.12.1"
|
||||
babel-preset-gatsby "^2.12.1"
|
||||
better-opn "^2.1.1"
|
||||
bluebird "^3.7.2"
|
||||
body-parser "^1.19.0"
|
||||
|
@ -6574,8 +6574,8 @@ gatsby@4.11.2:
|
|||
eslint-plugin-graphql "^4.0.0"
|
||||
eslint-plugin-import "^2.25.4"
|
||||
eslint-plugin-jsx-a11y "^6.5.1"
|
||||
eslint-plugin-react "^7.29.2"
|
||||
eslint-plugin-react-hooks "^4.3.0"
|
||||
eslint-plugin-react "^7.29.4"
|
||||
eslint-plugin-react-hooks "^4.4.0"
|
||||
eslint-webpack-plugin "^2.6.0"
|
||||
event-source-polyfill "^1.0.25"
|
||||
execa "^5.1.1"
|
||||
|
@ -6587,19 +6587,19 @@ gatsby@4.11.2:
|
|||
find-cache-dir "^3.3.2"
|
||||
fs-exists-cached "1.0.0"
|
||||
fs-extra "^10.0.0"
|
||||
gatsby-cli "^4.11.2"
|
||||
gatsby-core-utils "^3.11.1"
|
||||
gatsby-graphiql-explorer "^2.11.0"
|
||||
gatsby-legacy-polyfills "^2.11.0"
|
||||
gatsby-link "^4.11.1"
|
||||
gatsby-page-utils "^2.11.1"
|
||||
gatsby-parcel-config "^0.2.0"
|
||||
gatsby-plugin-page-creator "^4.11.1"
|
||||
gatsby-plugin-typescript "^4.11.1"
|
||||
gatsby-plugin-utils "^3.5.1"
|
||||
gatsby-react-router-scroll "^5.11.0"
|
||||
gatsby-telemetry "^3.11.1"
|
||||
gatsby-worker "^1.11.0"
|
||||
gatsby-cli "^4.12.1"
|
||||
gatsby-core-utils "^3.12.1"
|
||||
gatsby-graphiql-explorer "^2.12.1"
|
||||
gatsby-legacy-polyfills "^2.12.1"
|
||||
gatsby-link "^4.12.1"
|
||||
gatsby-page-utils "^2.12.1"
|
||||
gatsby-parcel-config "^0.3.1"
|
||||
gatsby-plugin-page-creator "^4.12.1"
|
||||
gatsby-plugin-typescript "^4.12.1"
|
||||
gatsby-plugin-utils "^3.6.1"
|
||||
gatsby-react-router-scroll "^5.12.1"
|
||||
gatsby-telemetry "^3.12.1"
|
||||
gatsby-worker "^1.12.1"
|
||||
glob "^7.2.0"
|
||||
globby "^11.1.0"
|
||||
got "^11.8.2"
|
||||
|
@ -6614,7 +6614,7 @@ gatsby@4.11.2:
|
|||
joi "^17.4.2"
|
||||
json-loader "^0.5.7"
|
||||
latest-version "5.1.0"
|
||||
lmdb "^2.2.3"
|
||||
lmdb "~2.2.3"
|
||||
lodash "^4.17.21"
|
||||
md5-file "^5.0.0"
|
||||
meant "^1.0.3"
|
||||
|
@ -6672,7 +6672,7 @@ gatsby@4.11.2:
|
|||
xstate "^4.26.0"
|
||||
yaml-loader "^0.6.0"
|
||||
optionalDependencies:
|
||||
gatsby-sharp "^0.5.0"
|
||||
gatsby-sharp "^0.6.1"
|
||||
|
||||
gauge@~2.7.3:
|
||||
version "2.7.4"
|
||||
|
@ -6894,7 +6894,7 @@ globby@11.0.3:
|
|||
merge2 "^1.3.0"
|
||||
slash "^3.0.0"
|
||||
|
||||
globby@^11.0.3, globby@^11.0.4, globby@^11.1.0:
|
||||
globby@^11.0.3, globby@^11.1.0:
|
||||
version "11.1.0"
|
||||
resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
|
||||
integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==
|
||||
|
@ -8072,10 +8072,10 @@ levn@^0.4.1:
|
|||
prelude-ls "^1.2.1"
|
||||
type-check "~0.4.0"
|
||||
|
||||
lilconfig@^2.0.3, lilconfig@^2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.4.tgz#f4507d043d7058b380b6a8f5cb7bcd4b34cee082"
|
||||
integrity sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==
|
||||
lilconfig@^2.0.3, lilconfig@^2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.5.tgz#19e57fd06ccc3848fd1891655b5a447092225b25"
|
||||
integrity sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==
|
||||
|
||||
lines-and-columns@^1.1.6:
|
||||
version "1.2.4"
|
||||
|
@ -8096,6 +8096,36 @@ listr2@^3.8.3:
|
|||
through "^2.3.8"
|
||||
wrap-ansi "^7.0.0"
|
||||
|
||||
lmdb-darwin-arm64@2.3.2:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/lmdb-darwin-arm64/-/lmdb-darwin-arm64-2.3.2.tgz#edcd324e4693abfcd02e7c5ba44a7f0e209f7588"
|
||||
integrity sha512-20lWWUPGKnSZRFY8FBm+vZEFx/5Deh0joz6cqJ8/0SuO/ejqRCppSsNqAxPqW87KUNR5rNfhaA2oRekMeb0cwQ==
|
||||
|
||||
lmdb-darwin-x64@2.3.2:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/lmdb-darwin-x64/-/lmdb-darwin-x64-2.3.2.tgz#6561f37d0461c3128b92fb80996c54e6243af939"
|
||||
integrity sha512-BsBnOfgK1B11Dh4RgcgBTmkmsPv3mjBPKsA4W4E+18SW9K2aRi86CAMPXqjfY/OJDUe1pSrpVf1A83b8N/C9rg==
|
||||
|
||||
lmdb-linux-arm64@2.3.2:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/lmdb-linux-arm64/-/lmdb-linux-arm64-2.3.2.tgz#feb4a52a0030feb9520543c78919c30250a85107"
|
||||
integrity sha512-DIibLZHpwwlIsP9cBRmw0xqDy6wZH+CDAnOTI+eihQ5PdWjTs+kaQs5O/x8l6/8fwCB0TPYKWTqfdUbvd/F7AA==
|
||||
|
||||
lmdb-linux-arm@2.3.2:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/lmdb-linux-arm/-/lmdb-linux-arm-2.3.2.tgz#d8ee33547cc0f671efcf63ca381306df51f972f5"
|
||||
integrity sha512-ofxfxVQqMbaC2Ygjzk8k6xgS5Dg/3cANeLcEx14T35GoU5pQKlLAWjypptyLQEeOboEmEOpZmHMoD7sWu/zakQ==
|
||||
|
||||
lmdb-linux-x64@2.3.2:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/lmdb-linux-x64/-/lmdb-linux-x64-2.3.2.tgz#1c66a012199ab5235d3fcec8c3fdad573cf3eff4"
|
||||
integrity sha512-HBUd013RRQ2KpiyBqqqSPSEwPpVUpTJZdTZGDVQFQZuxqyJumt4Wye3uh6ZgEiBtxzSelt4xvAeNjYPH0dcZSQ==
|
||||
|
||||
lmdb-win32-x64@2.3.2:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/lmdb-win32-x64/-/lmdb-win32-x64-2.3.2.tgz#e65f79bfbb9f09ebfa53d3b03959bc581ebda55a"
|
||||
integrity sha512-/hir5oU+GYm7/B6QirrpyOmIuzCKiIbWoKIJI2ebXeJlrs6Jj7UY9caPBYVkCzd79QzJnB7hIlX/F6Jx6gcUmg==
|
||||
|
||||
lmdb@2.2.4:
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/lmdb/-/lmdb-2.2.4.tgz#6494d5a1d1db152e0be759edcfa06893e4cbdb53"
|
||||
|
@ -8107,7 +8137,26 @@ lmdb@2.2.4:
|
|||
ordered-binary "^1.2.4"
|
||||
weak-lru-cache "^1.2.2"
|
||||
|
||||
lmdb@^2.0.2, lmdb@^2.2.3, lmdb@^2.2.4:
|
||||
lmdb@^2.0.2, lmdb@^2.2.6:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/lmdb/-/lmdb-2.3.3.tgz#ee0c53a5f5c2509c566b891803b3322e5a59095f"
|
||||
integrity sha512-CrooSvHOzd+jPXCXpiffu2+5m90Fe6L/cw90fg+4sCWNrw3W7/ad20CGuTkMVU7mAuwXEAJAfnUwvHN2pS9Rqg==
|
||||
dependencies:
|
||||
msgpackr "^1.5.4"
|
||||
nan "^2.14.2"
|
||||
node-addon-api "^4.3.0"
|
||||
node-gyp-build-optional-packages "^4.3.2"
|
||||
ordered-binary "^1.2.4"
|
||||
weak-lru-cache "^1.2.2"
|
||||
optionalDependencies:
|
||||
lmdb-darwin-arm64 "2.3.2"
|
||||
lmdb-darwin-x64 "2.3.2"
|
||||
lmdb-linux-arm "2.3.2"
|
||||
lmdb-linux-arm64 "2.3.2"
|
||||
lmdb-linux-x64 "2.3.2"
|
||||
lmdb-win32-x64 "2.3.2"
|
||||
|
||||
lmdb@~2.2.3:
|
||||
version "2.2.6"
|
||||
resolved "https://registry.yarnpkg.com/lmdb/-/lmdb-2.2.6.tgz#a52ef533812b8abcbe0033fc9d74d215e7dfc0a0"
|
||||
integrity sha512-UmQV0oZZcV3EN6rjcAjIiuWcc3MYZGWQ0GUYz46Ron5fuTa/dUow7WSQa6leFkvZIKVUdECBWVw96tckfEzUFQ==
|
||||
|
@ -8579,13 +8628,13 @@ micromatch@^3.1.10:
|
|||
snapdragon "^0.8.1"
|
||||
to-regex "^3.0.2"
|
||||
|
||||
micromatch@^4.0.4:
|
||||
version "4.0.4"
|
||||
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9"
|
||||
integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==
|
||||
micromatch@^4.0.4, micromatch@^4.0.5:
|
||||
version "4.0.5"
|
||||
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
|
||||
integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
|
||||
dependencies:
|
||||
braces "^3.0.1"
|
||||
picomatch "^2.2.3"
|
||||
braces "^3.0.2"
|
||||
picomatch "^2.3.1"
|
||||
|
||||
miller-rabin@^4.0.0:
|
||||
version "4.0.1"
|
||||
|
@ -8668,10 +8717,10 @@ mini-css-extract-plugin@1.6.2:
|
|||
schema-utils "^3.0.0"
|
||||
webpack-sources "^1.1.0"
|
||||
|
||||
mini-svg-data-uri@^1.4.3:
|
||||
version "1.4.3"
|
||||
resolved "https://registry.yarnpkg.com/mini-svg-data-uri/-/mini-svg-data-uri-1.4.3.tgz#43177b2e93766ba338931a3e2a84a3dfd3a222b8"
|
||||
integrity sha512-gSfqpMRC8IxghvMcxzzmMnWpXAChSA+vy4cia33RgerMS8Fex95akUyQZPbxJJmeBGiGmK7n/1OpUX8ksRjIdA==
|
||||
mini-svg-data-uri@^1.4.4:
|
||||
version "1.4.4"
|
||||
resolved "https://registry.yarnpkg.com/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz#8ab0aabcdf8c29ad5693ca595af19dd2ead09939"
|
||||
integrity sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==
|
||||
|
||||
minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
|
||||
version "1.0.1"
|
||||
|
@ -8706,7 +8755,7 @@ minimist-options@4.1.0:
|
|||
is-plain-obj "^1.1.0"
|
||||
kind-of "^6.0.3"
|
||||
|
||||
minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5:
|
||||
minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
||||
integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
|
||||
|
@ -8809,10 +8858,10 @@ nano-css@^5.3.1:
|
|||
stacktrace-js "^2.0.2"
|
||||
stylis "^4.0.6"
|
||||
|
||||
nanoid@3.3.2, nanoid@^3.3.1:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.2.tgz#c89622fafb4381cd221421c69ec58547a1eec557"
|
||||
integrity sha512-CuHBogktKwpm5g2sRgv83jEy2ijFzBwMoYA60orPDR7ynsLijJDqgsi4RDGj3OJpy3Ieb+LYwiRmIOGyytgITA==
|
||||
nanoid@3.3.3, nanoid@^3.3.1:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25"
|
||||
integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==
|
||||
|
||||
nanomatch@^1.2.9:
|
||||
version "1.2.13"
|
||||
|
@ -8919,6 +8968,11 @@ node-fetch@^2.6.1, node-fetch@^2.6.6, node-fetch@^2.6.7:
|
|||
dependencies:
|
||||
whatwg-url "^5.0.0"
|
||||
|
||||
node-gyp-build-optional-packages@^4.3.2:
|
||||
version "4.3.2"
|
||||
resolved "https://registry.yarnpkg.com/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-4.3.2.tgz#82de9bdf9b1ad042457533afb2f67469dc2264bb"
|
||||
integrity sha512-P5Ep3ISdmwcCkZIaBaQamQtWAG0facC89phWZgi5Z3hBU//J6S48OIvyZWSPPf6yQMklLZiqoosWAZUj7N+esA==
|
||||
|
||||
node-gyp-build@^4.2.3, node-gyp-build@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3"
|
||||
|
@ -9051,10 +9105,10 @@ object-copy@^0.1.0:
|
|||
define-property "^0.2.5"
|
||||
kind-of "^3.0.3"
|
||||
|
||||
object-hash@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5"
|
||||
integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==
|
||||
object-hash@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9"
|
||||
integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==
|
||||
|
||||
object-inspect@^1.11.0, object-inspect@^1.9.0:
|
||||
version "1.12.0"
|
||||
|
@ -9509,7 +9563,7 @@ picocolors@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
|
||||
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
|
||||
|
||||
picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3:
|
||||
picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
|
||||
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
||||
|
@ -9555,10 +9609,10 @@ pngjs@^3.0.0, pngjs@^3.3.3:
|
|||
resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f"
|
||||
integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==
|
||||
|
||||
polished@4.2.1:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/polished/-/polished-4.2.1.tgz#e38cdf4244b3bea63f77b0f8ab2335e22a66bd08"
|
||||
integrity sha512-vRkUnHBwVX7kIeCzCghcLCWoDenV+sV7lkItnmTc7bb6Uzbe8ogU1FxqEW8+dXCxUX8YW8vusQ0HTk2yES7bfQ==
|
||||
polished@4.2.2:
|
||||
version "4.2.2"
|
||||
resolved "https://registry.yarnpkg.com/polished/-/polished-4.2.2.tgz#2529bb7c3198945373c52e34618c8fe7b1aa84d1"
|
||||
integrity sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.17.8"
|
||||
|
||||
|
@ -9639,12 +9693,12 @@ postcss-js@^4.0.0:
|
|||
dependencies:
|
||||
camelcase-css "^2.0.1"
|
||||
|
||||
postcss-load-config@^3.1.0:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.3.tgz#21935b2c43b9a86e6581a576ca7ee1bde2bd1d23"
|
||||
integrity sha512-5EYgaM9auHGtO//ljHH+v/aC/TQ5LHXtL7bQajNAUBKUVKiYE8rYpFms7+V26D9FncaGe2zwCoPQsFKb5zF/Hw==
|
||||
postcss-load-config@^3.1.4:
|
||||
version "3.1.4"
|
||||
resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.4.tgz#1ab2571faf84bb078877e1d07905eabe9ebda855"
|
||||
integrity sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==
|
||||
dependencies:
|
||||
lilconfig "^2.0.4"
|
||||
lilconfig "^2.0.5"
|
||||
yaml "^1.10.2"
|
||||
|
||||
postcss-loader@^4.3.0:
|
||||
|
@ -9838,10 +9892,10 @@ postcss-reduce-transforms@^5.1.0:
|
|||
dependencies:
|
||||
postcss-value-parser "^4.2.0"
|
||||
|
||||
postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.6, postcss-selector-parser@^6.0.9:
|
||||
version "6.0.9"
|
||||
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz#ee71c3b9ff63d9cd130838876c13a2ec1a992b2f"
|
||||
integrity sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==
|
||||
postcss-selector-parser@^6.0.10, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.6, postcss-selector-parser@^6.0.9:
|
||||
version "6.0.10"
|
||||
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d"
|
||||
integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==
|
||||
dependencies:
|
||||
cssesc "^3.0.0"
|
||||
util-deprecate "^1.0.2"
|
||||
|
@ -9866,7 +9920,7 @@ postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0:
|
|||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
|
||||
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
||||
|
||||
postcss@8.4.12, postcss@^8.2.15, postcss@^8.2.9, postcss@^8.3.11, postcss@^8.4.6:
|
||||
postcss@8.4.12, postcss@^8.2.15, postcss@^8.2.9, postcss@^8.3.11, postcss@^8.4.12:
|
||||
version "8.4.12"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.12.tgz#1e7de78733b28970fa4743f7da6f3763648b1905"
|
||||
integrity sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg==
|
||||
|
@ -9929,7 +9983,7 @@ pretty-error@^2.1.2:
|
|||
lodash "^4.17.20"
|
||||
renderkid "^2.0.4"
|
||||
|
||||
probe-image-size@^7.0.0:
|
||||
probe-image-size@^7.2.3:
|
||||
version "7.2.3"
|
||||
resolved "https://registry.yarnpkg.com/probe-image-size/-/probe-image-size-7.2.3.tgz#d49c64be540ec8edea538f6f585f65a9b3ab4309"
|
||||
integrity sha512-HubhG4Rb2UH8YtV4ba0Vp5bQ7L78RTONYu/ujmCu5nBI8wGv24s4E9xSKBi0N1MowRpxk76pFCpJtW0KPzOK0w==
|
||||
|
@ -10209,10 +10263,10 @@ react-dom@17.0.2:
|
|||
object-assign "^4.1.1"
|
||||
scheduler "^0.20.2"
|
||||
|
||||
react-dropzone@12.0.4:
|
||||
version "12.0.4"
|
||||
resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-12.0.4.tgz#b88eeaa2c7118f7fd042404682b17a1d466f2fcf"
|
||||
integrity sha512-fcqHEYe1MzAghU6/Hz86lHDlBNsA+lO48nAcm7/wA+kIzwS6uuJbUG33tBZjksj7GAZ1iUQ6NHwjUURPmSGang==
|
||||
react-dropzone@12.0.5:
|
||||
version "12.0.5"
|
||||
resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-12.0.5.tgz#f9b557484a8afd6267f670f96a770ddd3948838b"
|
||||
integrity sha512-zUjZigD0VJ91CSm9T1h7ErxFReBLaa9sjS2dUL0+inb0RROZpSJTNDHPY1rrBES5V2NXhF8v0kghmaHc81BMFg==
|
||||
dependencies:
|
||||
attr-accept "^2.2.2"
|
||||
file-selector "^0.4.0"
|
||||
|
@ -10857,10 +10911,10 @@ shallow-compare@^1.2.2:
|
|||
resolved "https://registry.yarnpkg.com/shallow-compare/-/shallow-compare-1.2.2.tgz#fa4794627bf455a47c4f56881d8a6132d581ffdb"
|
||||
integrity sha512-LUMFi+RppPlrHzbqmFnINTrazo0lPNwhcgzuAXVVcfy/mqPDrQmHAyz5bvV0gDAuRFrk804V0HpQ6u9sZ0tBeg==
|
||||
|
||||
sharp@^0.30.1:
|
||||
version "0.30.2"
|
||||
resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.30.2.tgz#95b309b2740424702dc19b62a62595dd34a458b1"
|
||||
integrity sha512-mrMeKI5ECTdYhslPlA2TbBtU3nZXMEBcQwI6qYXjPlu1LpW4HBZLFm6xshMI1HpIdEEJ3UcYp5AKifLT/fEHZQ==
|
||||
sharp@^0.30.3:
|
||||
version "0.30.3"
|
||||
resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.30.3.tgz#315a1817423a4d1cde5119a21c99c234a7a6fb37"
|
||||
integrity sha512-rjpfJFK58ZOFSG8sxYSo3/JQb4ej095HjXp9X7gVu7gEn1aqSG8TCW29h/Rr31+PXrFADo1H/vKfw0uhMQWFtg==
|
||||
dependencies:
|
||||
color "^4.2.1"
|
||||
detect-libc "^2.0.1"
|
||||
|
@ -10963,10 +11017,10 @@ sjcl@^1.0.8:
|
|||
resolved "https://registry.yarnpkg.com/sjcl/-/sjcl-1.0.8.tgz#f2ec8d7dc1f0f21b069b8914a41a8f236b0e252a"
|
||||
integrity sha512-LzIjEQ0S0DpIgnxMEayM1rq9aGwGRG4OnZhCdjx7glTaJtf4zRfpg87ImfjSJjoW9vKpagd82McDOwbRT5kQKQ==
|
||||
|
||||
skynet-js@4.0.26-beta:
|
||||
version "4.0.26-beta"
|
||||
resolved "https://registry.yarnpkg.com/skynet-js/-/skynet-js-4.0.26-beta.tgz#5b6e924a0efa5fd6ee2c00760e1d4ce92d1ba0a9"
|
||||
integrity sha512-YPqjNyqL6AhS9jMLyJ5PoilDZ7f2YFrqqhXUnzLBrjmWxICxcDeRu2GJh9MGCJUZ2Cv35IlG1ch4eiqFbs1wqA==
|
||||
skynet-js@4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/skynet-js/-/skynet-js-4.1.0.tgz#eccb84d04e9f42aa4f86ecb24fb4d59ed21e44cc"
|
||||
integrity sha512-VmUjJ9QnLpfuQA2j7vzFh8JvukjQlX4QLGw1HY3VyslFPj92vPpyO8gqjPfzgbkR05TXL7CbdqZoLZr/RBDZPw==
|
||||
dependencies:
|
||||
"@skynetlabs/tus-js-client" "^2.3.0"
|
||||
async-mutex "^0.3.2"
|
||||
|
@ -11583,10 +11637,10 @@ svgo@^2.5.0, svgo@^2.7.0:
|
|||
picocolors "^1.0.0"
|
||||
stable "^0.1.8"
|
||||
|
||||
swr@1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/swr/-/swr-1.2.2.tgz#6cae09928d30593a7980d80f85823e57468fac5d"
|
||||
integrity sha512-ky0BskS/V47GpW8d6RU7CPsr6J8cr7mQD6+do5eky3bM0IyJaoi3vO8UhvrzJaObuTlGhPl2szodeB2dUd76Xw==
|
||||
swr@1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/swr/-/swr-1.3.0.tgz#c6531866a35b4db37b38b72c45a63171faf9f4e8"
|
||||
integrity sha512-dkghQrOl2ORX9HYrMDtPa7LTVHJjCTeZoB1dqTbnnEDlSvN8JEKpYIYurDfvbQFUUS8Cg8PceFVZNkW0KNNYPw==
|
||||
|
||||
symbol-observable@^1.0.4:
|
||||
version "1.2.0"
|
||||
|
@ -11612,29 +11666,29 @@ table@^6.0.9:
|
|||
string-width "^4.2.3"
|
||||
strip-ansi "^6.0.1"
|
||||
|
||||
tailwindcss@3.0.23:
|
||||
version "3.0.23"
|
||||
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.0.23.tgz#c620521d53a289650872a66adfcb4129d2200d10"
|
||||
integrity sha512-+OZOV9ubyQ6oI2BXEhzw4HrqvgcARY38xv3zKcjnWtMIZstEsXdI9xftd1iB7+RbOnj2HOEzkA0OyB5BaSxPQA==
|
||||
tailwindcss@3.0.24:
|
||||
version "3.0.24"
|
||||
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.0.24.tgz#22e31e801a44a78a1d9a81ecc52e13b69d85704d"
|
||||
integrity sha512-H3uMmZNWzG6aqmg9q07ZIRNIawoiEcNFKDfL+YzOPuPsXuDXxJxB9icqzLgdzKNwjG3SAro2h9SYav8ewXNgig==
|
||||
dependencies:
|
||||
arg "^5.0.1"
|
||||
chalk "^4.1.2"
|
||||
chokidar "^3.5.3"
|
||||
color-name "^1.1.4"
|
||||
cosmiconfig "^7.0.1"
|
||||
detective "^5.2.0"
|
||||
didyoumean "^1.2.2"
|
||||
dlv "^1.1.3"
|
||||
fast-glob "^3.2.11"
|
||||
glob-parent "^6.0.2"
|
||||
is-glob "^4.0.3"
|
||||
lilconfig "^2.0.5"
|
||||
normalize-path "^3.0.0"
|
||||
object-hash "^2.2.0"
|
||||
postcss "^8.4.6"
|
||||
object-hash "^3.0.0"
|
||||
picocolors "^1.0.0"
|
||||
postcss "^8.4.12"
|
||||
postcss-js "^4.0.0"
|
||||
postcss-load-config "^3.1.0"
|
||||
postcss-load-config "^3.1.4"
|
||||
postcss-nested "5.0.6"
|
||||
postcss-selector-parser "^6.0.9"
|
||||
postcss-selector-parser "^6.0.10"
|
||||
postcss-value-parser "^4.2.0"
|
||||
quick-lru "^5.1.1"
|
||||
resolve "^1.22.0"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
> :warning: This documentation is outdated and should be used for reference
|
||||
only. Portal setup documentation is located at
|
||||
https://docs.siasky.net/webportal-management/overview.
|
||||
https://portal-docs.skynetlabs.com/.
|
||||
|
||||
This directory contains a setup guide and scripts that will install and
|
||||
configure some basic requirements for running a Skynet Portal. The assumption is
|
||||
|
|
Reference in New Issue