1
1
mirror of https://github.com/pterodactyl/panel.git synced 2024-11-26 02:52:30 +01:00

Add basic listing of server schedules

This commit is contained in:
Dane Everitt 2020-02-08 15:23:08 -08:00
parent f9ec96c70a
commit 32e9fb0346
No known key found for this signature in database
GPG Key ID: EEA66103B3D71F53
21 changed files with 508 additions and 79 deletions

View File

@ -0,0 +1,28 @@
<?php
namespace Pterodactyl\Http\Controllers\Api\Client\Servers;
use Illuminate\Http\Request;
use Pterodactyl\Models\Server;
use Pterodactyl\Transformers\Api\Client\ScheduleTransformer;
use Pterodactyl\Http\Controllers\Api\Client\ClientApiController;
class ScheduleController extends ClientApiController
{
/**
* Returns all of the schedules belonging to a given server.
*
* @param \Illuminate\Http\Request $request
* @param \Pterodactyl\Models\Server $server
* @return array
*/
public function index(Request $request, Server $server)
{
$schedules = $server->schedule;
$schedules->loadMissing('tasks');
return $this->fractal->collection($schedules)
->transformWith($this->getTransformer(ScheduleTransformer::class))
->toArray();
}
}

View File

@ -2,6 +2,29 @@
namespace Pterodactyl\Models;
use Illuminate\Container\Container;
use Pterodactyl\Contracts\Extensions\HashidsInterface;
/**
* @property int $id
* @property int $server_id
* @property string $name
* @property string $cron_day_of_week
* @property string $cron_day_of_month
* @property string $cron_hour
* @property string $cron_minute
* @property bool $is_active
* @property bool $is_processing
* @property \Carbon\Carbon|null $last_run_at
* @property \Carbon\Carbon|null $next_run_at
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
*
* @property string $hashid
*
* @property \Pterodactyl\Models\Server $server
* @property \Pterodactyl\Models\Task[]|\Illuminate\Support\Collection $tasks
*/
class Schedule extends Validable
{
/**
@ -51,8 +74,6 @@ class Schedule extends Validable
* @var array
*/
protected $dates = [
self::CREATED_AT,
self::UPDATED_AT,
'last_run_at',
'next_run_at',
];
@ -93,7 +114,7 @@ class Schedule extends Validable
*/
public function getHashidAttribute()
{
return app()->make('hashids')->encode($this->id);
return Container::getInstance()->make(HashidsInterface::class)->encode($this->id);
}
/**

View File

@ -2,8 +2,26 @@
namespace Pterodactyl\Models;
use Illuminate\Container\Container;
use Znck\Eloquent\Traits\BelongsToThrough;
use Pterodactyl\Contracts\Extensions\HashidsInterface;
/**
* @property int $id
* @property int $schedule_id
* @property int $sequence_id
* @property string $action
* @property string $payload
* @property int $time_offset
* @property bool $is_queued
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
*
* @property string $hashid
*
* @property \Pterodactyl\Models\Schedule $schedule
* @property \Pterodactyl\Models\Server $server
*/
class Task extends Validable
{
use BelongsToThrough;
@ -83,7 +101,7 @@ class Task extends Validable
*/
public function getHashidAttribute()
{
return app()->make('hashids')->encode($this->id);
return Container::getInstance()->make(HashidsInterface::class)->encode($this->id);
}
/**

View File

@ -0,0 +1,64 @@
<?php
namespace Pterodactyl\Transformers\Api\Client;
use Pterodactyl\Models\Task;
use Pterodactyl\Models\Schedule;
use Illuminate\Database\Eloquent\Model;
class ScheduleTransformer extends BaseClientTransformer
{
/**
* @var array
*/
protected $availableIncludes = ['tasks'];
/**
* {@inheritdoc}
*/
public function getResourceName(): string
{
return Schedule::RESOURCE_NAME;
}
/**
* Returns a transformed schedule model such that a client can view the information.
*
* @param \Pterodactyl\Models\Schedule $model
* @return array
*/
public function transform(Schedule $model)
{
return [
'id' => $model->id,
'name' => $model->name,
'cron' => [
'day_of_week' => $model->cron_day_of_week,
'day_of_month' => $model->cron_day_of_month,
'hour' => $model->cron_hour,
'minute' => $model->cron_minute,
],
'is_active' => $model->is_active,
'is_processing' => $model->is_processing,
'last_run_at' => $model->last_run_at ? $model->last_run_at->toIso8601String() : null,
'next_run_at' => $model->next_run_at ? $model->next_run_at->toIso8601String() : null,
'created_at' => $model->created_at->toIso8601String(),
'updated_at' => $model->updated_at->toIso8601String(),
];
}
/**
* Allows attaching the tasks specific to the schedule in the response.
*
* @param \Pterodactyl\Models\Schedule $model
* @return \League\Fractal\Resource\Collection
*
* @throws \Pterodactyl\Exceptions\Transformer\InvalidTransformerLevelException
*/
public function includeTasks(Schedule $model)
{
return $this->collection(
$model->tasks, $this->makeTransformer(TaskTransformer::class), Task::RESOURCE_NAME
);
}
}

View File

@ -0,0 +1,36 @@
<?php
namespace Pterodactyl\Transformers\Api\Client;
use Pterodactyl\Models\Task;
class TaskTransformer extends BaseClientTransformer
{
/**
* {@inheritdoc}
*/
public function getResourceName(): string
{
return Task::RESOURCE_NAME;
}
/**
* Transforms a schedule's task into a client viewable format.
*
* @param \Pterodactyl\Models\Task $model
* @return array
*/
public function transform(Task $model)
{
return [
'id' => $model->id,
'sequence_id' => $model->sequence_id,
'action' => $model->action,
'payload' => $model->payload,
'time_offset' => $model->time_offset,
'is_queued' => $model->is_queued,
'created_at' => $model->created_at->toIso8601String(),
'updated_at' => $model->updated_at->toIso8601String(),
];
}
}

View File

@ -44,6 +44,7 @@
"@babel/core": "^7.7.5",
"@babel/plugin-proposal-class-properties": "^7.7.4",
"@babel/plugin-proposal-object-rest-spread": "^7.7.4",
"@babel/plugin-proposal-optional-chaining": "^7.8.3",
"@babel/plugin-syntax-dynamic-import": "^7.7.4",
"@babel/plugin-transform-runtime": "^7.7.5",
"@babel/preset-env": "^7.7.5",
@ -68,8 +69,8 @@
"@types/uuid": "^3.4.5",
"@types/webpack-env": "^1.13.6",
"@types/yup": "^0.26.17",
"@typescript-eslint/eslint-plugin": "^1.10.1",
"@typescript-eslint/parser": "^1.10.1",
"@typescript-eslint/eslint-plugin": "^2.19.0",
"@typescript-eslint/parser": "^2.19.0",
"babel-loader": "^8.0.6",
"babel-plugin-styled-components": "^1.10.6",
"babel-plugin-tailwind-components": "^0.5.10",
@ -98,8 +99,8 @@
"style-loader": "^0.23.1",
"tailwindcss": "^0.7.4",
"terser-webpack-plugin": "^1.3.0",
"ts-loader": "^5.3.3",
"typescript": "^3.6.3",
"ts-loader": "^6.2.1",
"typescript": "^3.7.5",
"webpack": "^4.41.2",
"webpack-assets-manifest": "^3.1.1",
"webpack-cli": "^3.3.10",

View File

@ -23,8 +23,7 @@ rules:
- always-multiline
"react-hooks/rules-of-hooks":
- error
"react-hooks/exhaustive-deps":
- warn
"react-hooks/exhaustive-deps": 0
"@typescript-eslint/explicit-function-return-type": 0
"@typescript-eslint/explicit-member-accessibility": 0
"@typescript-eslint/no-unused-vars": 0

View File

@ -0,0 +1,73 @@
import http from '@/api/http';
export interface Schedule {
id: number;
name: string;
cron: {
dayOfWeek: string;
dayOfMonth: string;
hour: string;
minute: string;
};
isActive: boolean;
isProcessing: boolean;
lastRunAt: Date | null;
nextRunAt: Date | null;
createdAt: Date;
updatedAt: Date;
tasks: Task[];
}
export interface Task {
id: number;
sequenceId: number;
action: string;
payload: string;
timeOffset: number;
isQueued: boolean;
createdAt: Date;
updatedAt: Date;
}
export const rawDataToServerTask = (data: any): Task => ({
id: data.id,
sequenceId: data.sequence_id,
action: data.action,
payload: data.payload,
timeOffset: data.time_offset,
isQueued: data.is_queued,
createdAt: new Date(data.created_at),
updatedAt: new Date(data.updated_at),
});
export const rawDataToServerSchedule = (data: any): Schedule => ({
id: data.id,
name: data.name,
cron: {
dayOfWeek: data.cron.day_of_week,
dayOfMonth: data.cron.day_of_month,
hour: data.cron.hour,
minute: data.cron.minute,
},
isActive: data.is_active,
isProcessing: data.is_processing,
lastRunAt: data.last_run_at ? new Date(data.last_run_at) : null,
nextRunAt: data.next_run_at ? new Date(data.next_run_at) : null,
createdAt: new Date(data.created_at),
updatedAt: new Date(data.updated_at),
tasks: (data.relationships?.tasks?.data || []).map((row: any) => rawDataToServerTask(row.attributes)),
});
export default (uuid: string): Promise<Schedule[]> => {
return new Promise((resolve, reject) => {
http.get(`/api/client/servers/${uuid}/schedules`, {
params: {
include: ['tasks'],
},
})
.then(({ data }) => resolve((data.data || []).map((row: any) => rawDataToServerSchedule(row.attributes))))
.catch(reject);
});
};

View File

@ -8,7 +8,7 @@ type Props = Readonly<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElemen
showFlashes?: string | boolean;
}>;
export default ({ title, borderColor, showFlashes, children, ...props }: Props) => (
const ContentBox = ({ title, borderColor, showFlashes, children, ...props }: Props) => (
<div {...props}>
{title && <h2 className={'text-neutral-300 mb-4 px-4'}>{title}</h2>}
{showFlashes &&
@ -24,3 +24,5 @@ export default ({ title, borderColor, showFlashes, children, ...props }: Props)
</div>
</div>
);
export default ContentBox;

View File

@ -1,5 +1,5 @@
import React from 'react';
import { Field, FieldProps } from 'formik';
import { Field as FormikField, FieldProps } from 'formik';
import classNames from 'classnames';
interface OwnProps {
@ -11,8 +11,8 @@ interface OwnProps {
type Props = OwnProps & Omit<React.InputHTMLAttributes<HTMLInputElement>, 'name'>;
export default ({ id, name, label, description, validate, className, ...props }: Props) => (
<Field name={name} validate={validate}>
const Field = ({ id, name, label, description, validate, className, ...props }: Props) => (
<FormikField name={name} validate={validate}>
{
({ field, form: { errors, touched } }: FieldProps) => (
<React.Fragment>
@ -37,5 +37,7 @@ export default ({ id, name, label, description, validate, className, ...props }:
</React.Fragment>
)
}
</Field>
</FormikField>
);
export default Field;

View File

@ -9,7 +9,7 @@ interface Props {
className?: string;
}
export default ({ size, centered, className }: Props) => (
const Spinner = ({ size, centered, className }: Props) => (
centered ?
<div className={classNames(`flex justify-center ${className}`, { 'm-20': size === 'large', 'm-6': size !== 'large' })}>
<div
@ -27,3 +27,5 @@ export default ({ size, centered, className }: Props) => (
})}
/>
);
export default Spinner;

View File

@ -10,7 +10,7 @@ interface Props {
backgroundOpacity?: number;
}
export default ({ size, fixed, visible, backgroundOpacity }: Props) => (
const SpinnerOverlay = ({ size, fixed, visible, backgroundOpacity }: Props) => (
<CSSTransition timeout={150} classNames={'fade'} in={visible} unmountOnExit={true}>
<div
className={classNames('z-50 pin-t pin-l flex items-center justify-center w-full h-full rounded', {
@ -23,3 +23,5 @@ export default ({ size, fixed, visible, backgroundOpacity }: Props) => (
</div>
</CSSTransition>
);
export default SpinnerOverlay;

View File

@ -1,7 +1,7 @@
import React, { Suspense } from 'react';
import Spinner from '@/components/elements/Spinner';
export default ({ children }: { children?: React.ReactNode }) => (
const SuspenseSpinner = ({ children }: { children?: React.ReactNode }) => (
<Suspense
fallback={
<div className={'mx-4 w-3/4 mr-4 flex items-center justify-center'}>
@ -12,3 +12,5 @@ export default ({ children }: { children?: React.ReactNode }) => (
{children}
</Suspense>
);
export default SuspenseSpinner;

View File

@ -9,7 +9,7 @@ interface Props {
children: React.ReactNode;
}
export default ({ icon, title, children, className }: Props) => (
const TitledGreyBox = ({ icon, title, children, className }: Props) => (
<div className={`rounded shadow-md bg-neutral-700 ${className}`}>
<div className={'bg-neutral-900 rounded-t p-3 border-b border-black'}>
<p className={'text-sm uppercase'}>
@ -21,3 +21,5 @@ export default ({ icon, title, children, className }: Props) => (
</div>
</div>
);
export default TitledGreyBox;

View File

@ -135,7 +135,7 @@ export default ({ databaseId, className, onDelete }: Props) => {
</Modal>
<div className={classNames('grey-row-box no-hover', className)}>
<div className={'icon'}>
<FontAwesomeIcon icon={faDatabase}/>
<FontAwesomeIcon icon={faDatabase} fixedWidth={true}/>
</div>
<div className={'flex-1 ml-4'}>
<p className={'text-lg'}>{database.name}</p>

View File

@ -1,3 +1,83 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import getServerSchedules, { Schedule } from '@/api/server/schedules/getServerSchedules';
import { ServerContext } from '@/state/server';
import Spinner from '@/components/elements/Spinner';
import { Link } from 'react-router-dom';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faCalendarAlt } from '@fortawesome/free-solid-svg-icons/faCalendarAlt';
import classNames from 'classnames';
import format from 'date-fns/format';
import FlashMessageRender from '@/components/FlashMessageRender';
import { Actions, useStoreActions } from 'easy-peasy';
import { ApplicationStore } from '@/state';
import { httpErrorToHuman } from '@/api/http';
export default () => null;
export default () => {
const { id, uuid } = ServerContext.useStoreState(state => state.server.data!);
const [ schedules, setSchedules ] = useState<Schedule[] | null>(null);
const { addError, clearFlashes } = useStoreActions((actions: Actions<ApplicationStore>) => actions.flashes);
useEffect(() => {
clearFlashes('schedules');
getServerSchedules(uuid)
.then(schedules => setSchedules(schedules))
.catch(error => {
addError({ message: httpErrorToHuman(error), key: 'schedules' });
console.error(error);
});
}, [ uuid, setSchedules ]);
return (
<div className={'my-10 mb-6'}>
<FlashMessageRender byKey={'schedules'} className={'mb-4'}/>
{!schedules ?
<Spinner size={'large'} centered={true}/>
:
schedules.map(schedule => (
<Link key={schedule.id} to={`/servers/${id}/schedules/${schedule.id}`} className={'grey-row-box'}>
<div className={'icon'}>
<FontAwesomeIcon icon={faCalendarAlt} fixedWidth={true}/>
</div>
<div className={'flex-1 ml-4'}>
<p>{schedule.name}</p>
<p className={'text-xs text-neutral-400'}>
Last run at: {schedule.lastRunAt ? format(schedule.lastRunAt, 'MMM Do [at] h:mma') : 'never'}
</p>
</div>
<div className={'flex items-center mx-8'}>
<div>
<p className={'font-medium text-center'}>{schedule.cron.minute}</p>
<p className={'text-2xs text-neutral-500 uppercase'}>Minute</p>
</div>
<div className={'ml-4'}>
<p className={'font-medium text-center'}>{schedule.cron.hour}</p>
<p className={'text-2xs text-neutral-500 uppercase'}>Hour</p>
</div>
<div className={'ml-4'}>
<p className={'font-medium text-center'}>{schedule.cron.dayOfMonth}</p>
<p className={'text-2xs text-neutral-500 uppercase'}>Day (Month)</p>
</div>
<div className={'ml-4'}>
<p className={'font-medium text-center'}>*</p>
<p className={'text-2xs text-neutral-500 uppercase'}>Month</p>
</div>
<div className={'ml-4'}>
<p className={'font-medium text-center'}>{schedule.cron.dayOfWeek}</p>
<p className={'text-2xs text-neutral-500 uppercase'}>Day (Week)</p>
</div>
</div>
<div>
<p className={classNames('py-1 px-3 rounded text-xs uppercase', {
'bg-green-600': schedule.isActive,
'bg-neutral-400': !schedule.isActive,
})}>
{schedule.isActive ? 'Active' : 'Inactive'}
</p>
</div>
</Link>
))
}
</div>
);
};

View File

@ -13,6 +13,7 @@ import { CSSTransition } from 'react-transition-group';
import SuspenseSpinner from '@/components/elements/SuspenseSpinner';
import FileEditContainer from '@/components/server/files/FileEditContainer';
import SettingsContainer from '@/components/server/settings/SettingsContainer';
import ScheduleContainer from '@/components/server/schedules/ScheduleContainer';
const ServerRouter = ({ match, location }: RouteComponentProps<{ id: string }>) => {
const server = ServerContext.useStoreState(state => state.server.data);
@ -35,7 +36,7 @@ const ServerRouter = ({ match, location }: RouteComponentProps<{ id: string }>)
<NavLink to={`${match.url}/files`}>File Manager</NavLink>
<NavLink to={`${match.url}/databases`}>Databases</NavLink>
{/* <NavLink to={`${match.url}/users`}>User Management</NavLink> */}
{/* <NavLink to={`${match.url}/schedules`}>Schedules</NavLink> */}
<NavLink to={`${match.url}/schedules`}>Schedules</NavLink>
<NavLink to={`${match.url}/settings`}>Settings</NavLink>
</div>
</div>
@ -63,7 +64,7 @@ const ServerRouter = ({ match, location }: RouteComponentProps<{ id: string }>)
/>
<Route path={`${match.path}/databases`} component={DatabasesContainer} exact/>
{/* <Route path={`${match.path}/users`} component={UsersContainer} exact/> */}
{/* <Route path={`${match.path}/schedules`} component={ScheduleContainer} exact/> */}
<Route path={`${match.path}/schedules`} component={ScheduleContainer} exact/>
<Route path={`${match.path}/settings`} component={SettingsContainer} exact/>
</Switch>
</React.Fragment>

View File

@ -59,6 +59,10 @@ Route::group(['prefix' => '/servers/{server}', 'middleware' => [AuthenticateServ
Route::post('/create-folder', 'Servers\FileController@createFolder')->name('api.client.servers.files.create-folder');
});
Route::group(['prefix' => '/schedules'], function () {
Route::get('/', 'Servers\ScheduleController@index');
});
Route::group(['prefix' => '/network'], function () {
Route::get('/', 'Servers\NetworkController@index')->name('api.client.servers.network');
});

View File

@ -241,15 +241,16 @@ module.exports = {
*/
textSizes: {
'xs': '.75rem', // 12px
'sm': '.875rem', // 14px
'base': '1rem', // 16px
'lg': '1.125rem', // 18px
'xl': '1.25rem', // 20px
'2xl': '1.5rem', // 24px
'3xl': '1.875rem', // 30px
'4xl': '2.25rem', // 36px
'5xl': '3rem', // 48px
'2xs': '.625rem',
'xs': '.75rem',
'sm': '.875rem',
'base': '1rem',
'lg': '1.125rem',
'xl': '1.25rem',
'2xl': '1.5rem',
'3xl': '1.875rem',
'4xl': '2.25rem',
'5xl': '3rem',
},
/*

View File

@ -86,6 +86,7 @@ module.exports = {
'@babel/transform-runtime',
'@babel/proposal-class-properties',
'@babel/proposal-object-rest-spread',
'@babel/proposal-optional-chaining',
'@babel/syntax-dynamic-import',
],
},

182
yarn.lock
View File

@ -150,6 +150,10 @@
version "7.0.0"
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250"
"@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670"
"@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4":
version "7.5.5"
resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351"
@ -260,6 +264,13 @@
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-syntax-optional-catch-binding" "^7.7.4"
"@babel/plugin-proposal-optional-chaining@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.8.3.tgz#ae10b3214cb25f7adb1f3bc87ba42ca10b7e2543"
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-syntax-optional-chaining" "^7.8.0"
"@babel/plugin-proposal-unicode-property-regex@^7.7.4":
version "7.7.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.7.4.tgz#7c239ccaf09470dbe1d453d50057460e84517ebb"
@ -303,6 +314,12 @@
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-syntax-optional-chaining@^7.8.0":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a"
dependencies:
"@babel/helper-plugin-utils" "^7.8.0"
"@babel/plugin-syntax-top-level-await@^7.7.4":
version "7.7.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.7.4.tgz#bd7d8fa7b9fee793a36e4027fd6dd1aa32f946da"
@ -766,6 +783,10 @@
"@types/react" "*"
hoist-non-react-statics "^3.3.0"
"@types/json-schema@^7.0.3":
version "7.0.4"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339"
"@types/lodash-es@^4.17.3":
version "4.17.3"
resolved "https://registry.yarnpkg.com/@types/lodash-es/-/lodash-es-4.17.3.tgz#87eb0b3673b076b8ee655f1890260a136af09a2d"
@ -872,38 +893,44 @@
version "0.26.17"
resolved "https://registry.yarnpkg.com/@types/yup/-/yup-0.26.17.tgz#5cb7cfc211d8e985b21d88289542591c92cad9dc"
"@typescript-eslint/eslint-plugin@^1.10.1":
version "1.10.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.10.1.tgz#0a9e41f375d082363e63169049cd03ef0b6dd85e"
"@typescript-eslint/eslint-plugin@^2.19.0":
version "2.19.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.19.0.tgz#bf743448a4633e4b52bee0c40148ba072ab3adbd"
dependencies:
"@typescript-eslint/experimental-utils" "1.10.1"
eslint-utils "^1.3.1"
"@typescript-eslint/experimental-utils" "2.19.0"
eslint-utils "^1.4.3"
functional-red-black-tree "^1.0.1"
regexpp "^2.0.1"
tsutils "^3.7.0"
regexpp "^3.0.0"
tsutils "^3.17.1"
"@typescript-eslint/experimental-utils@1.10.1":
version "1.10.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-1.10.1.tgz#459eb096f38cf913b226bad08e92d67961d0d8d0"
"@typescript-eslint/experimental-utils@2.19.0":
version "2.19.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.19.0.tgz#d5ca732f22c009e515ba09fcceb5f2127d841568"
dependencies:
"@typescript-eslint/typescript-estree" "1.10.1"
eslint-scope "^4.0.0"
"@types/json-schema" "^7.0.3"
"@typescript-eslint/typescript-estree" "2.19.0"
eslint-scope "^5.0.0"
"@typescript-eslint/parser@^1.10.1":
version "1.10.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-1.10.1.tgz#ee119a3e399a0dfa834ce7840eb92a244ccf570c"
"@typescript-eslint/parser@^2.19.0":
version "2.19.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.19.0.tgz#912160d9425395d09857dcd5382352bc98be11ae"
dependencies:
"@types/eslint-visitor-keys" "^1.0.0"
"@typescript-eslint/experimental-utils" "1.10.1"
"@typescript-eslint/typescript-estree" "1.10.1"
eslint-visitor-keys "^1.0.0"
"@typescript-eslint/experimental-utils" "2.19.0"
"@typescript-eslint/typescript-estree" "2.19.0"
eslint-visitor-keys "^1.1.0"
"@typescript-eslint/typescript-estree@1.10.1":
version "1.10.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-1.10.1.tgz#e4a2c45498ed53ecbdc3d8019407b63a9c16fbda"
"@typescript-eslint/typescript-estree@2.19.0":
version "2.19.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.19.0.tgz#6bd7310b9827e04756fe712909f26956aac4b196"
dependencies:
lodash.unescape "4.0.1"
semver "5.5.0"
debug "^4.1.1"
eslint-visitor-keys "^1.1.0"
glob "^7.1.6"
is-glob "^4.0.1"
lodash "^4.17.15"
semver "^6.3.0"
tsutils "^3.17.1"
"@webassemblyjs/ast@1.8.5":
version "1.8.5"
@ -1447,6 +1474,12 @@ braces@^2.3.1, braces@^2.3.2:
split-string "^3.0.2"
to-regex "^3.0.1"
braces@^3.0.1:
version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
dependencies:
fill-range "^7.0.1"
brorand@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
@ -2691,21 +2724,38 @@ eslint-plugin-standard@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.0.0.tgz#f845b45109c99cd90e77796940a344546c8f6b5c"
eslint-scope@^4.0.0, eslint-scope@^4.0.3:
eslint-scope@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848"
dependencies:
esrecurse "^4.1.0"
estraverse "^4.1.1"
eslint-scope@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9"
dependencies:
esrecurse "^4.1.0"
estraverse "^4.1.1"
eslint-utils@^1.3.0, eslint-utils@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.3.1.tgz#9a851ba89ee7c460346f97cf8939c7298827e512"
eslint-utils@^1.4.3:
version "1.4.3"
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f"
dependencies:
eslint-visitor-keys "^1.1.0"
eslint-visitor-keys@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
eslint-visitor-keys@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2"
eslint@^5.16.0:
version "5.16.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea"
@ -2964,6 +3014,12 @@ fill-range@^4.0.0:
repeat-string "^1.6.1"
to-regex-range "^2.1.0"
fill-range@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
dependencies:
to-regex-range "^5.0.1"
finalhandler@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
@ -3212,6 +3268,17 @@ glob@^7.0.3, glob@^7.0.5, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
once "^1.3.0"
path-is-absolute "^1.0.0"
glob@^7.1.6:
version "7.1.6"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^3.0.4"
once "^1.3.0"
path-is-absolute "^1.0.0"
global-modules@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780"
@ -3829,6 +3896,12 @@ is-glob@^4.0.0:
dependencies:
is-extglob "^2.1.1"
is-glob@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
dependencies:
is-extglob "^2.1.1"
is-number@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
@ -3839,6 +3912,10 @@ is-number@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff"
is-number@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
is-obj@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
@ -4240,15 +4317,11 @@ lodash.toarray@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561"
lodash.unescape@4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c"
lodash.uniq@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
"lodash@>=3.5 <5", lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.3, lodash@^4.17.5:
"lodash@>=3.5 <5", lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.3, lodash@^4.17.5:
version "4.17.15"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
@ -4379,6 +4452,13 @@ micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4:
snapdragon "^0.8.1"
to-regex "^3.0.2"
micromatch@^4.0.0:
version "4.0.2"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259"
dependencies:
braces "^3.0.1"
picomatch "^2.0.5"
miller-rabin@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d"
@ -5066,6 +5146,10 @@ perfectionist@^2.4.0:
vendors "^1.0.0"
write-file-stdout "0.0.2"
picomatch@^2.0.5:
version "2.2.1"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.1.tgz#21bac888b6ed8601f831ce7816e335bc779f0a4a"
pify@^2.0.0, pify@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
@ -6190,6 +6274,10 @@ regexpp@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f"
regexpp@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.0.0.tgz#dd63982ee3300e67b41c1956f850aa680d9d330e"
regexpu-core@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6"
@ -6429,15 +6517,11 @@ selfsigned@^1.10.7:
dependencies:
node-forge "0.9.0"
"semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0:
"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
semver@5.5.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
semver@^6.1.0, semver@^6.3.0:
semver@^6.0.0, semver@^6.1.0, semver@^6.3.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
@ -7079,6 +7163,12 @@ to-regex-range@^2.1.0:
is-number "^3.0.0"
repeat-string "^1.6.1"
to-regex-range@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
dependencies:
is-number "^7.0.0"
to-regex@^3.0.1, to-regex@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce"
@ -7100,15 +7190,15 @@ toposort@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330"
ts-loader@^5.3.3:
version "5.4.5"
resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-5.4.5.tgz#a0c1f034b017a9344cef0961bfd97cc192492b8b"
ts-loader@^6.2.1:
version "6.2.1"
resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-6.2.1.tgz#67939d5772e8a8c6bdaf6277ca023a4812da02ef"
dependencies:
chalk "^2.3.0"
enhanced-resolve "^4.0.0"
loader-utils "^1.0.2"
micromatch "^3.1.4"
semver "^5.0.1"
micromatch "^4.0.0"
semver "^6.0.0"
ts-toolbelt@^4.10.0:
version "4.12.13"
@ -7118,9 +7208,9 @@ tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
version "1.10.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
tsutils@^3.7.0:
version "3.14.0"
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.14.0.tgz#bf8d5a7bae5369331fa0f2b0a5a10bd7f7396c77"
tsutils@^3.17.1:
version "3.17.1"
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759"
dependencies:
tslib "^1.8.1"
@ -7145,9 +7235,9 @@ typedarray@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
typescript@^3.6.3:
version "3.7.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.3.tgz#b36840668a16458a7025b9eabfad11b66ab85c69"
typescript@^3.7.5:
version "3.7.5"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae"
ua-parser-js@^0.7.18:
version "0.7.20"