Compare commits

..

15 Commits
2.2.2 ... 2.4.2

Author SHA1 Message Date
diced
a900daa244 2.4.2 2020-11-09 19:12:53 -08:00
diced
42dcd03428 rich content 2020-11-09 19:12:28 -08:00
diced
353122c169 2.4.1 2020-11-06 20:18:28 -08:00
diced
cea5092fd6 Lighthouse optimizations 2020-11-06 20:18:19 -08:00
diced
3d4625f531 2.4.0 2020-11-06 19:53:34 -08:00
diced
f5ab288bb3 update setup 2020-11-06 19:53:14 -08:00
diced
41565b3a62 move folders to places that make sense 2020-11-06 19:52:54 -08:00
diced
ef7fbaf1dc 2.3.1 2020-11-06 08:42:16 -08:00
diced
87cf861648 remove ioredis 2020-11-06 08:41:59 -08:00
diced
d414c85efd 2.3.0 2020-11-05 19:47:35 -08:00
diced
5b24a8e415 gravatars 2020-11-05 19:47:22 -08:00
diced
1d348db4dd 2.2.4 2020-11-05 19:20:58 -08:00
diced
ececc3ab0e fix workflow 2020-11-05 19:14:33 -08:00
diced
a71bde9730 teyest 2020-11-05 19:12:35 -08:00
diced
3417a84789 remove some useless stuff 2020-11-05 19:10:19 -08:00
25 changed files with 213 additions and 253 deletions

View File

@@ -1,68 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
# ******** NOTE ********
name: "CodeQL"
on:
push:
branches: [ next ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ next ]
schedule:
- cron: '25 2 * * 4'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more...
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@@ -23,5 +23,6 @@ jobs:
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm run build --if-present
- run: npm i -g yarn
- run: yarn
- run: yarn build

View File

@@ -10,8 +10,6 @@
![David](https://img.shields.io/david/dicedtomatoreal/zipline)
![David](https://img.shields.io/david/dev/dicedtomatoreal/zipline)
![GitHub package.json dependency version (prod)](https://img.shields.io/github/package-json/dependency-version/dicedtomatoreal/zipline/react)
![GitHub package.json dependency version (prod)](https://img.shields.io/github/package-json/dependency-version/dicedtomatoreal/zipline/next)
![GitHub package.json dependency version (prod)](https://img.shields.io/github/package-json/dependency-version/dicedtomatoreal/zipline/fastify)
# Zipline
The best and only **React + Next.js** ShareX / File Uploader you would ever want.

View File

@@ -1,6 +1,6 @@
{
"name": "zipline-next",
"version": "2.2.2",
"version": "2.4.2",
"private": true,
"dependencies": {
"@dicedtomato/colors": "^1.0.3",
@@ -23,7 +23,6 @@
"fastify-typeorm-plugin": "^2.1.2",
"figlet": "^1.5.0",
"inquirer": "^7.3.3",
"ioredis": "^4.19.2",
"material-ui-dropzone": "^3.5.0",
"next": "^9.5.4",
"pg": "^8.4.1",
@@ -48,7 +47,6 @@
"devDependencies": {
"@types/bcrypt": "^3.0.0",
"@types/crypto-js": "^3.1.47",
"@types/ioredis": "^4.17.7",
"@types/mongodb": "^3.5.27",
"@types/node": "^14.11.2",
"@types/react": "^16.9.49",

3
release.js Normal file
View File

@@ -0,0 +1,3 @@
module.exports = async (markdown) => {
return markdown;
};

View File

@@ -25,7 +25,7 @@ const base = {
'https://github.githubassets.com/images/modules/open_graph/github-mark.png',
color: '#128377'
},
core: { secret: 'my-secret', port: 3000 },
core: { secret: 'my-secret', port: 3000, host: '127.0.0.1', theme: 'dark', secure: false },
uploader: {
directory: './uploads',
route: '/u',
@@ -48,35 +48,33 @@ const base = {
{ name: 'mysql' },
{ name: 'mariadb' },
{ name: 'mssql' },
{ name: 'sqlite' },
{ name: 'sqlite3' },
{ name: 'mongodb', extra: 'No support yet' }
{ name: 'sqlite3' }
]
},
{
type: 'input',
name: 'host',
message: 'Database Host'
message: 'Database Host (leave blank if sqlite3)'
},
{
type: 'number',
name: 'port',
message: 'Database Port'
message: 'Database Port (leave blank if sqlite3)'
},
{
type: 'input',
name: 'database',
message: 'Database Name'
message: 'Database Name (db path if sqlite3)'
},
{
type: 'input',
name: 'username',
message: 'Database User'
message: 'Database User (leave blank if sqlite3)'
},
{
type: 'password',
name: 'password',
message: 'Database Password'
message: 'Database Password (leave blank if sqlite3)'
}
]);
@@ -106,7 +104,7 @@ const base = {
{
type: 'confirm',
name: 'original',
message: 'Keep Original?'
message: 'Keep Original File names?'
}
]);
@@ -138,7 +136,7 @@ const base = {
urls: { ...base.urls, ...urls }
};
writeFileSync('Zipline.toml', stringify(config));
writeFileSync('Ziplined.toml', stringify(config));
if (docker.useDocker) {
console.log('Generating docker-compose.yml...');

View File

@@ -66,29 +66,39 @@ export default function Login() {
</Alert>
</Snackbar>
<Card>
<CardContent>
<Typography variant='h4'>Login</Typography>
<TextField
label='Username'
className={classes.field}
onChange={e => setUsername(e.target.value)}
/>
<TextField
label='Password'
type='password'
className={classes.field}
onChange={e => setPassword(e.target.value)}
/>
</CardContent>
<CardActions>
<Button
color='primary'
className={classes.field}
onClick={handleLogin}
>
Login
</Button>
</CardActions>
<form>
<CardContent>
<Typography variant='h4'>Login</Typography>
<TextField
label='Username'
InputLabelProps={{
htmlFor: 'username'
}}
id='username'
className={classes.field}
onChange={e => setUsername(e.target.value)}
/>
<TextField
label='Password'
type='password'
InputLabelProps={{
htmlFor: 'password'
}}
id='password'
className={classes.field}
onChange={e => setPassword(e.target.value)}
/>
</CardContent>
<CardActions>
<Button
color='primary'
className={classes.field}
onClick={handleLogin}
>
Login
</Button>
</CardActions>
</form>
</Card>
</React.Fragment>
);

View File

@@ -34,13 +34,14 @@ export default function ManageUser() {
const [alertOpen, setAlertOpen] = useState(false);
const [username, setUsername] = useState(state.user.username);
const [password, setPassword] = useState('');
const [email, setEmail] = useState('');
const handleUpdateUser = async () => {
const d = await (
await fetch('/api/user', {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password })
body: JSON.stringify({ username, password: password.trim() === '' ? null : password, email })
})
).json();
if (!d.error) {
@@ -82,6 +83,14 @@ export default function ManageUser() {
className={classes.field}
onChange={e => setPassword(e.target.value)}
/>
<TextField
label='Email'
type='email'
helperText='Used for a Gravatar Avatar'
value={email}
className={classes.field}
onChange={e => setEmail(e.target.value)}
/>
</CardContent>
<CardActions>
<Button

View File

@@ -5,6 +5,7 @@ import Box from '@material-ui/core/Box';
import Menu from '@material-ui/core/Menu';
import MenuItem from '@material-ui/core/MenuItem';
import Drawer from '@material-ui/core/Drawer';
import Avatar from '@material-ui/core/Avatar';
import Hidden from '@material-ui/core/Hidden';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
@@ -39,6 +40,7 @@ import { makeStyles, useTheme, withStyles } from '@material-ui/core/styles';
import { useRouter } from 'next/router';
import { useDispatch } from 'react-redux';
import { store } from '../store';
import { MD5 } from 'crypto-js';
const drawerWidth = 240;
@@ -101,6 +103,7 @@ export default function UI({ children }) {
const state = store.getState();
const router = useRouter();
const dispatch = useDispatch();
const [emailHash, setEmailHash] = useState('');
const [mobileOpen, setMobileOpen] = useState(false);
const [admin, setAdmin] = useState(false);
const [anchorEl, setAnchorEl] = useState(null);
@@ -119,6 +122,8 @@ export default function UI({ children }) {
router.push('/user/login');
} else setAdmin(d.administrator);
})();
setEmailHash(MD5(state.user.email).toString());
}, []);
const handleCopyTokenThenClose = async () => {
@@ -174,16 +179,31 @@ export default function UI({ children }) {
</IconButton>
<Typography variant='h6'>Zipline</Typography>
<Box className={classes.rightButton}>
<IconButton
aria-label='account of current user'
aria-controls='menu-appbar'
aria-haspopup='true'
onClick={event => setAnchorEl(event.currentTarget)}
color='inherit'
className={classes.rightButton}
>
<AccountCircleIcon className={classes.rightButton} />
</IconButton>
{state.user.email ? (
<Button
aria-label='account of current user'
aria-controls='menu-appbar'
aria-haspopup='true'
onClick={event => setAnchorEl(event.currentTarget)}
color='inherit'
className={classes.rightButton}
>
<Avatar src={`https://www.gravatar.com/avatar/${emailHash}.jpg`}>
{state.user.username[0].toUpperCase()}
</Avatar>
</Button>
) : (
<IconButton
aria-label='account of current user'
aria-controls='menu-appbar'
aria-haspopup='true'
onClick={event => setAnchorEl(event.currentTarget)}
color='inherit'
className={classes.rightButton}
>
<AccountCircleIcon className={classes.rightButton} />
</IconButton>
)}
</Box>
<Menu

View File

@@ -11,27 +11,35 @@ import { bootstrap } from 'fastify-decorators';
import { Console } from './lib/logger';
import { AddressInfo } from 'net';
import { magenta, bold, green, reset, blue, red } from '@dicedtomato/colors';
import Redis from 'ioredis';
import { Configuration } from './lib/Config';
import { UserController } from './controllers/UserController';
import { RootController } from './controllers/RootController';
import { UserController } from './lib/api/controllers/UserController';
import { RootController } from './lib/api/controllers/RootController';
import { join } from 'path';
import { ImagesController } from './controllers/ImagesController';
import { URLSController } from './controllers/URLSController';
import { ImagesController } from './lib/api/controllers/ImagesController';
import { URLSController } from './lib/api/controllers/URLSController';
import { checkVersion } from './lib/Util';
import { readFileSync } from 'fs';
import { Image } from './entities/Image';
import { User } from './entities/User';
import { Zipline } from './entities/Zipline';
import { URL } from './entities/URL';
import { existsSync, readFileSync } from 'fs';
import { Image } from './lib/entities/Image';
import { User } from './lib/entities/User';
import { Zipline } from './lib/entities/Zipline';
import { URL } from './lib/entities/URL';
const dev = process.env.NODE_ENV !== 'production';
(async () => { if (await checkVersion()) Console.logger('Zipline').info('running an outdated version of zipline, please update soon!'); })();
(async () => {
if (await checkVersion())
Console.logger('Zipline').info(
'running an outdated version of zipline, please update soon!'
);
})();
console.log(`
${magenta(text('Zipline'))}
Version : ${blue(process.env.npm_package_version || readFileSync(join(process.cwd(), 'package.json'), 'utf8'))}
Version : ${blue(
process.env.npm_package_version ||
JSON.parse(readFileSync(join(process.cwd(), 'package.json'), 'utf8'))
.version
)}
GitHub : ${blue('https://github.com/ZiplineProject/zipline')}
Issues : ${blue('https://github.com/ZiplineProject/zipline/issues')}
Docs : ${blue('https://zipline.diced.wtf/')}
@@ -110,6 +118,33 @@ server.get(`${config.urls.route}/:id`, async function (
return reply.redirect(urlId.url);
});
server.get(`${config.uploader.rich_content_route || '/a'}/:id`, async function (
req: FastifyRequest<{ Params: { id: string } }>,
reply: FastifyReply
) {
if (!existsSync(join(config.uploader.directory, req.params.id))) {
await app.render404(req.raw, reply.raw);
return (reply.sent = true);
}
return reply.type('text/html').send(`
<html>
<head>
<meta property="theme-color" content="${config.meta.color}">
<meta property="og:title" content="${req.params.id}">
<meta property="og:url" content="${config.uploader.route}/${req.params.id}">
<meta property="og:image" content="${config.uploader.route}/${req.params.id}">
<meta property="twitter:card" content="summary_large_image">
</head>
<body>
<div style="text-align:center;vertical-align:middle;">
<img src="${config.uploader.route}/${req.params.id}" >
</div>
</body>
</html>
`);
});
server.register(fastifyMultipart);
server.register(fastifyTypeorm, {
@@ -145,22 +180,26 @@ server.register(fastifyStatic, {
server.register(fastifyFavicon);
server.listen({
port: config.core.port,
host: config.core.host
}, err => {
if (err) throw err;
const info = server.server.address() as AddressInfo;
server.listen(
{
port: config.core.port,
host: config.core.host
},
err => {
if (err) throw err;
const info = server.server.address() as AddressInfo;
Console.logger('Server').info(
`server listening on ${bold(
`${green(info.address)}${reset(':')}${bold(green(info.port.toString()))}`
)}`
);
});
Console.logger('Server').info(
`server listening on ${bold(
`${green(info.address)}${reset(':')}${bold(
green(info.port.toString())
)}`
)}`
);
}
);
server.addHook('preHandler', async (req, reply) => {
if (
config.core.blacklisted_ips &&
config.core.blacklisted_ips.includes(req.ip)
@@ -168,4 +207,4 @@ server.addHook('preHandler', async (req, reply) => {
await app.render404(req.raw, reply.raw);
return (reply.sent = true);
}
});
});

View File

@@ -23,6 +23,7 @@ export interface ConfigMeta {
export interface ConfigUploader {
directory: string;
route: string;
rich_content_route?: string;
length: number;
blacklisted: string[];
original: boolean;

View File

@@ -3,7 +3,7 @@ import { compareSync, hashSync } from 'bcrypt';
import { Configuration } from './Config';
import { Connection } from 'typeorm';
import { compare } from 'semver';
import { Zipline } from '../entities/Zipline';
import { Zipline } from './entities/Zipline';
import { readFileSync } from 'fs';
import { join } from 'path';

View File

@@ -1,6 +1,6 @@
import { Image } from '../entities/Image';
import { URL } from '../entities/URL';
import { User } from '../entities/User';
import { Image } from './entities/Image';
import { URL } from './entities/URL';
import { User } from './entities/User';
import { Config, Configuration, ConfigWebhooks } from './Config';
import { Console } from './logger';

View File

@@ -9,12 +9,12 @@ import {
DELETE
} from 'fastify-decorators';
import { Repository } from 'typeorm';
import { Image } from '../entities/Image';
import { LoginError } from '../lib/api/APIErrors';
import { Configuration, ConfigWebhooks } from '../lib/Config';
import { Console } from '../lib/logger';
import { readBaseCookie } from '../lib/Util';
import { WebhookHelper, WebhookType } from '../lib/Webhooks';
import { Image } from '../../entities/Image';
import { LoginError } from '../APIErrors';
import { Configuration, ConfigWebhooks } from '../../Config';
import { Console } from '../../logger';
import { readBaseCookie } from '../../Util';
import { WebhookHelper, WebhookType } from '../../Webhooks';
const config = Configuration.readConfig();

View File

@@ -12,18 +12,25 @@ import { join } from 'path';
import { Repository } from 'typeorm';
import { pipeline } from 'stream';
import { promisify } from 'util';
import { Image } from '../entities/Image';
import { User } from '../entities/User';
import { AuthError } from '../lib/api/APIErrors';
import { Configuration, ConfigWebhooks } from '../lib/Config';
import { createRandomId, getFirst } from '../lib/Util';
import { Console } from '../lib/logger';
import { WebhookHelper, WebhookType } from '../lib/Webhooks';
import { Image } from '../../entities/Image';
import { User } from '../../entities/User';
import { AuthError } from '../APIErrors';
import { Configuration, ConfigWebhooks } from '../../Config';
import { createRandomId, getFirst } from '../../Util';
import { Console } from '../../logger';
import { WebhookHelper, WebhookType } from '../../Webhooks';
const pump = promisify(pipeline);
const config = Configuration.readConfig();
const rateLimiterConfig = config.core.ratelimiter
? { config: { rateLimit: { max: config.core.ratelimiter.requests, timeWindow: config.core.ratelimiter.retry_after } } }
? {
config: {
rateLimit: {
max: config.core.ratelimiter.requests,
timeWindow: config.core.ratelimiter.retry_after
}
}
}
: {};
@Controller('/api')
@@ -135,14 +142,18 @@ export class RootController {
`image ${fileName}.${ext} was uploaded by ${user.username} (${user.id})`
);
const host = `${config.core.secure ? 'https' : 'http'}://${req.hostname}${
config.uploader.rich_content_route
? config.uploader.rich_content_route
: config.uploader.route
}/`;
if (this.webhooks.events.includes(WebhookType.UPLOAD))
WebhookHelper.sendWebhook(this.webhooks.upload.content, {
image,
host: `${config.core.secure ? 'https' : 'http'}://${req.hostname}${config.uploader.route}/`
host
});
reply.send(
`${config.core.secure ? 'https' : 'http'}://${req.hostname}${config.uploader.route}/${fileName}.${ext}`
);
reply.send(host);
}
}

View File

@@ -8,13 +8,13 @@ import {
POST
} from 'fastify-decorators';
import { Repository } from 'typeorm';
import { URL } from '../entities/URL';
import { User } from '../entities/User';
import { LoginError } from '../lib/api/APIErrors';
import { Configuration, ConfigWebhooks } from '../lib/Config';
import { Console } from '../lib/logger';
import { createRandomId, readBaseCookie } from '../lib/Util';
import { WebhookType, WebhookHelper } from '../lib/Webhooks';
import { URL } from '../../entities/URL';
import { User } from '../../entities/User';
import { LoginError } from '../APIErrors';
import { Configuration, ConfigWebhooks } from '../../Config';
import { Console } from '../../logger';
import { createRandomId, readBaseCookie } from '../../Util';
import { WebhookType, WebhookHelper } from '../../Webhooks';
const config = Configuration.readConfig();

View File

@@ -9,16 +9,16 @@ import {
DELETE
} from 'fastify-decorators';
import { Repository } from 'typeorm';
import { User } from '../entities/User';
import { Zipline } from '../entities/Zipline';
import { User } from '../../entities/User';
import { Zipline } from '../../entities/Zipline';
import {
UserNotFoundError,
MissingBodyData,
LoginError,
UserExistsError
} from '../lib/api/APIErrors';
import { Configuration, ConfigWebhooks } from '../lib/Config';
import { Console } from '../lib/logger';
} from '../APIErrors';
import { Configuration, ConfigWebhooks } from '../../Config';
import { Console } from '../../logger';
import {
checkPassword,
createBaseCookie,
@@ -26,8 +26,8 @@ import {
encryptPassword,
getFirst,
readBaseCookie
} from '../lib/Util';
import { WebhookType, WebhookHelper } from '../lib/Webhooks';
} from '../../Util';
import { WebhookType, WebhookHelper } from '../../Webhooks';
const config = Configuration.readConfig();
@@ -63,7 +63,7 @@ export class UserController {
@PATCH('/')
async editUser(
req: FastifyRequest<{ Body: { username: string; password: string } }>,
req: FastifyRequest<{ Body: { username: string; password: string, email: string; } }>,
reply: FastifyReply
) {
if (!req.cookies.zipline) throw new LoginError('Not logged in.');
@@ -78,7 +78,8 @@ export class UserController {
this.logger.verbose(`attempting to save ${user.username} (${user.id})`);
user.username = req.body.username;
user.password = encryptPassword(req.body.password);
if (req.body.password) user.password = encryptPassword(req.body.password);
if (req.body.email) user.email = req.body.email;
await this.users.save(user);
this.logger.info(`saved ${user.username} (${user.id})`);

View File

@@ -11,6 +11,9 @@ export class User {
@Column('text')
public password: string;
@Column('text', { default: null }) /* used for gravatar avatar! */
public email: string;
@Column('boolean', { default: false })
public administrator: boolean;
@@ -25,6 +28,7 @@ export class User {
) {
this.username = username;
this.password = password;
this.email = null;
this.administrator = administrator;
this.token = token;
}

View File

@@ -16,7 +16,7 @@ import UI from '../../components/UI';
import UIPlaceholder from '../../components/UIPlaceholder';
import { makeStyles } from '@material-ui/core';
import { store } from '../../store';
import { Image } from '../../entities/Image';
import { Image } from '../../lib/entities/Image';
import { Configuration } from '../../lib/Config';
const useStyles = makeStyles(theme => ({

View File

@@ -24,7 +24,7 @@ import copy from 'copy-to-clipboard';
import UI from '../../components/UI';
import UIPlaceholder from '../../components/UIPlaceholder';
import { makeStyles } from '@material-ui/core';
import { URL as URLEntity } from '../../entities/URL';
import { URL as URLEntity } from '../../lib/entities/URL';
import { Configuration } from '../../lib/Config';
const useStyles = makeStyles(theme => ({

View File

@@ -1,5 +1,5 @@
/* eslint-disable indent */
import { User } from './entities/User';
import { User } from './lib/entities/User';
export const LOGIN = 'LOGIN';
export const LOGOUT = 'LOGOUT';

View File

@@ -1293,13 +1293,6 @@
"@types/react" "*"
hoist-non-react-statics "^3.3.0"
"@types/ioredis@^4.17.7":
version "4.17.7"
resolved "https://registry.yarnpkg.com/@types/ioredis/-/ioredis-4.17.7.tgz#5007a56380fd387315efabc6c777c050feabb121"
integrity sha512-M8/KDSGmNYhPFMn+CxDDpIEHP27b2muEHgnK1UgIQIMEO2KXH9mznHx3epeRlD+AjF94HFh3dy2/9zqO+pPDqQ==
dependencies:
"@types/node" "*"
"@types/json-schema@^7.0.3", "@types/json-schema@^7.0.5":
version "7.0.6"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0"
@@ -2436,11 +2429,6 @@ clsx@^1.0.2, clsx@^1.0.4, clsx@^1.1.1:
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188"
integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==
cluster-key-slot@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz#30474b2a981fb12172695833052bc0d01336d10d"
integrity sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==
code-point-at@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
@@ -2852,7 +2840,7 @@ delegates@^1.0.0:
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
denque@^1.1.0, denque@^1.4.1:
denque@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/denque/-/denque-1.4.1.tgz#6744ff7641c148c3f8a69c307e51235c1f4a37cf"
integrity sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==
@@ -4161,22 +4149,6 @@ invariant@^2.2.2:
dependencies:
loose-envify "^1.0.0"
ioredis@^4.19.2:
version "4.19.2"
resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.19.2.tgz#e3eab394c653cea5aea07c0c784d8c772dce8801"
integrity sha512-SZSIwMrbd96b7rJvJwyTWSP6XQ0m1kAIIqBnwglJKrIJ6na7TeY4F2EV2vDY0xm/fLrUY8cEg81dR7kVFt2sKA==
dependencies:
cluster-key-slot "^1.1.0"
debug "^4.1.1"
denque "^1.1.0"
lodash.defaults "^4.2.0"
lodash.flatten "^4.4.0"
p-map "^2.1.0"
redis-commands "1.6.0"
redis-errors "^1.2.0"
redis-parser "^3.0.0"
standard-as-callback "^2.0.1"
ipaddr.js@1.9.1:
version "1.9.1"
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
@@ -4637,16 +4609,6 @@ locate-path@^5.0.0:
dependencies:
p-locate "^4.1.0"
lodash.defaults@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=
lodash.flatten@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f"
integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=
lodash.sortby@^4.7.0:
version "4.7.0"
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
@@ -5390,11 +5352,6 @@ p-locate@^4.1.0:
dependencies:
p-limit "^2.2.0"
p-map@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175"
integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==
p-map@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b"
@@ -6011,23 +5968,6 @@ readdirp@~3.5.0:
dependencies:
picomatch "^2.2.1"
redis-commands@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.6.0.tgz#36d4ca42ae9ed29815cdb30ad9f97982eba1ce23"
integrity sha512-2jnZ0IkjZxvguITjFTrGiLyzQZcTvaw8DAaCXxZq/dsHXz7KfMQ3OUJy7Tz9vnRtZRVz6VRCPDvruvU8Ts44wQ==
redis-errors@^1.0.0, redis-errors@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/redis-errors/-/redis-errors-1.2.0.tgz#eb62d2adb15e4eaf4610c04afe1529384250abad"
integrity sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=
redis-parser@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-3.0.0.tgz#b66d828cdcafe6b4b8a428a7def4c6bcac31c8b4"
integrity sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=
dependencies:
redis-errors "^1.0.0"
redux-persist@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/redux-persist/-/redux-persist-6.0.0.tgz#b4d2972f9859597c130d40d4b146fecdab51b3a8"
@@ -6638,11 +6578,6 @@ stacktrace-parser@0.1.10:
dependencies:
type-fest "^0.7.1"
standard-as-callback@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.0.1.tgz#ed8bb25648e15831759b6023bdb87e6b60b38126"
integrity sha512-NQOxSeB8gOI5WjSaxjBgog2QFw55FV8TkS6Y07BiB3VJ8xNTvUYm0wl0s8ObgQ5NhdpnNfigMIKjgPESzgr4tg==
static-extend@^0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6"