mirror of
https://github.com/BluemediaDev/muse.git
synced 2024-11-27 04:05:28 +01:00
Merge pull request #415 from codetheweb/feature/better-file-caching
This commit is contained in:
commit
9afca25866
|
@ -3,3 +3,6 @@ DATA_DIR=./data
|
||||||
YOUTUBE_API_KEY=
|
YOUTUBE_API_KEY=
|
||||||
SPOTIFY_CLIENT_ID=
|
SPOTIFY_CLIENT_ID=
|
||||||
SPOTIFY_CLIENT_SECRET=
|
SPOTIFY_CLIENT_SECRET=
|
||||||
|
|
||||||
|
# Optional
|
||||||
|
# CACHE_LIMIT=2GB
|
||||||
|
|
|
@ -69,3 +69,7 @@ services:
|
||||||
5. `yarn start` (or `npm run start`)
|
5. `yarn start` (or `npm run start`)
|
||||||
|
|
||||||
**Note**: if you're on Windows, you may need to manually set the ffmpeg path. See [#345](https://github.com/codetheweb/muse/issues/345) for details.
|
**Note**: if you're on Windows, you may need to manually set the ffmpeg path. See [#345](https://github.com/codetheweb/muse/issues/345) for details.
|
||||||
|
|
||||||
|
#### Advanced
|
||||||
|
|
||||||
|
By default, Muse limits the total cache size to around 2 GB. If you want to change this, set the environment variable `CACHE_LIMIT`. For example, `CACHE_LIMIT=512MB` or `CACHE_LIMIT=10GB`.
|
||||||
|
|
11
package.json
11
package.json
|
@ -25,7 +25,7 @@
|
||||||
"watch": "tsc --watch",
|
"watch": "tsc --watch",
|
||||||
"prepack": "npm run clean && npm run build",
|
"prepack": "npm run clean && npm run build",
|
||||||
"start": "node dist/index.js",
|
"start": "node dist/index.js",
|
||||||
"dev": "nodemon",
|
"dev": "concurrently nodemon 'tsc --watch'",
|
||||||
"docker-publish": "docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t codetheweb/muse:latest --push ."
|
"docker-publish": "docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t codetheweb/muse:latest --push ."
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -40,12 +40,14 @@
|
||||||
"@types/ws": "^8.2.0",
|
"@types/ws": "^8.2.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.31.1",
|
"@typescript-eslint/eslint-plugin": "^4.31.1",
|
||||||
"@typescript-eslint/parser": "^4.31.1",
|
"@typescript-eslint/parser": "^4.31.1",
|
||||||
|
"concurrently": "^6.4.0",
|
||||||
"eslint": "^7.32.0",
|
"eslint": "^7.32.0",
|
||||||
"eslint-config-xo": "^0.38.0",
|
"eslint-config-xo": "^0.38.0",
|
||||||
"eslint-config-xo-typescript": "^0.44.0",
|
"eslint-config-xo-typescript": "^0.44.0",
|
||||||
"husky": "^4.3.8",
|
"husky": "^4.3.8",
|
||||||
"nodemon": "^2.0.7",
|
"nodemon": "^2.0.7",
|
||||||
"ts-node": "^10.4.0",
|
"ts-node": "^10.4.0",
|
||||||
|
"type-fest": "^2.5.4",
|
||||||
"typescript": "^4.4.3"
|
"typescript": "^4.4.3"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
|
@ -79,7 +81,7 @@
|
||||||
"discord.js": "^13.3.0",
|
"discord.js": "^13.3.0",
|
||||||
"dotenv": "^8.5.1",
|
"dotenv": "^8.5.1",
|
||||||
"fluent-ffmpeg": "^2.1.2",
|
"fluent-ffmpeg": "^2.1.2",
|
||||||
"fs-capacitor": "^6.2.0",
|
"fs-capacitor": "^7.0.1",
|
||||||
"get-youtube-id": "^1.0.1",
|
"get-youtube-id": "^1.0.1",
|
||||||
"got": "^11.8.2",
|
"got": "^11.8.2",
|
||||||
"hasha": "^5.2.2",
|
"hasha": "^5.2.2",
|
||||||
|
@ -92,11 +94,12 @@
|
||||||
"p-limit": "^3.1.0",
|
"p-limit": "^3.1.0",
|
||||||
"p-queue": "^7.1.0",
|
"p-queue": "^7.1.0",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"sequelize": "^5.22.4",
|
"sequelize": "^6.11.0",
|
||||||
"sequelize-typescript": "^1.1.0",
|
"sequelize-typescript": "^2.1.1",
|
||||||
"spotify-uri": "^2.2.0",
|
"spotify-uri": "^2.2.0",
|
||||||
"spotify-web-api-node": "^5.0.2",
|
"spotify-web-api-node": "^5.0.2",
|
||||||
"sqlite3": "^5.0.2",
|
"sqlite3": "^5.0.2",
|
||||||
|
"xbytes": "^1.7.0",
|
||||||
"youtube.ts": "^0.2.2",
|
"youtube.ts": "^0.2.2",
|
||||||
"ytdl-core": "^4.9.1",
|
"ytdl-core": "^4.9.1",
|
||||||
"ytsr": "^3.5.3"
|
"ytsr": "^3.5.3"
|
||||||
|
|
|
@ -5,6 +5,7 @@ import {TYPES} from './types.js';
|
||||||
import Bot from './bot.js';
|
import Bot from './bot.js';
|
||||||
import {sequelize} from './utils/db.js';
|
import {sequelize} from './utils/db.js';
|
||||||
import Config from './services/config.js';
|
import Config from './services/config.js';
|
||||||
|
import FileCacheProvider from './services/file-cache.js';
|
||||||
|
|
||||||
const bot = container.get<Bot>(TYPES.Bot);
|
const bot = container.get<Bot>(TYPES.Bot);
|
||||||
|
|
||||||
|
@ -18,5 +19,7 @@ const bot = container.get<Bot>(TYPES.Bot);
|
||||||
|
|
||||||
await sequelize.sync({alter: true});
|
await sequelize.sync({alter: true});
|
||||||
|
|
||||||
|
await container.get<FileCacheProvider>(TYPES.FileCache).cleanup();
|
||||||
|
|
||||||
await bot.listen();
|
await bot.listen();
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -29,7 +29,8 @@ import Shuffle from './commands/shuffle.js';
|
||||||
import Skip from './commands/skip.js';
|
import Skip from './commands/skip.js';
|
||||||
import Unskip from './commands/unskip.js';
|
import Unskip from './commands/unskip.js';
|
||||||
import ThirdParty from './services/third-party.js';
|
import ThirdParty from './services/third-party.js';
|
||||||
import CacheProvider from './services/cache.js';
|
import FileCacheProvider from './services/file-cache.js';
|
||||||
|
import KeyValueCacheProvider from './services/key-value-cache.js';
|
||||||
|
|
||||||
const container = new Container();
|
const container = new Container();
|
||||||
|
|
||||||
|
@ -78,6 +79,7 @@ container.bind(TYPES.Config).toConstantValue(new ConfigProvider());
|
||||||
// Static libraries
|
// Static libraries
|
||||||
container.bind(TYPES.ThirdParty).to(ThirdParty);
|
container.bind(TYPES.ThirdParty).to(ThirdParty);
|
||||||
|
|
||||||
container.bind(TYPES.Cache).to(CacheProvider);
|
container.bind(TYPES.FileCache).to(FileCacheProvider);
|
||||||
|
container.bind(TYPES.KeyValueCache).to(KeyValueCacheProvider);
|
||||||
|
|
||||||
export default container;
|
export default container;
|
||||||
|
|
|
@ -2,25 +2,25 @@ import {inject, injectable} from 'inversify';
|
||||||
import {Client} from 'discord.js';
|
import {Client} from 'discord.js';
|
||||||
import {TYPES} from '../types.js';
|
import {TYPES} from '../types.js';
|
||||||
import Player from '../services/player.js';
|
import Player from '../services/player.js';
|
||||||
import Config from '../services/config.js';
|
import FileCacheProvider from '../services/file-cache.js';
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export default class {
|
export default class {
|
||||||
private readonly guildPlayers: Map<string, Player>;
|
private readonly guildPlayers: Map<string, Player>;
|
||||||
private readonly cacheDir: string;
|
|
||||||
private readonly discordClient: Client;
|
private readonly discordClient: Client;
|
||||||
|
private readonly fileCache: FileCacheProvider;
|
||||||
|
|
||||||
constructor(@inject(TYPES.Config) config: Config, @inject(TYPES.Client) client: Client) {
|
constructor(@inject(TYPES.FileCache) fileCache: FileCacheProvider, @inject(TYPES.Client) client: Client) {
|
||||||
this.guildPlayers = new Map();
|
this.guildPlayers = new Map();
|
||||||
this.cacheDir = config.CACHE_DIR;
|
|
||||||
this.discordClient = client;
|
this.discordClient = client;
|
||||||
|
this.fileCache = fileCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
get(guildId: string): Player {
|
get(guildId: string): Player {
|
||||||
let player = this.guildPlayers.get(guildId);
|
let player = this.guildPlayers.get(guildId);
|
||||||
|
|
||||||
if (!player) {
|
if (!player) {
|
||||||
player = new Player(this.cacheDir, this.discordClient);
|
player = new Player(this.discordClient, this.fileCache);
|
||||||
|
|
||||||
this.guildPlayers.set(guildId, player);
|
this.guildPlayers.set(guildId, player);
|
||||||
}
|
}
|
||||||
|
|
14
src/models/file-cache.ts
Normal file
14
src/models/file-cache.ts
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import {Table, Column, PrimaryKey, Model} from 'sequelize-typescript';
|
||||||
|
|
||||||
|
@Table
|
||||||
|
export default class FileCache extends Model {
|
||||||
|
@PrimaryKey
|
||||||
|
@Column
|
||||||
|
hash!: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
bytes!: number;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
accessedAt!: Date;
|
||||||
|
}
|
|
@ -1,9 +1,11 @@
|
||||||
import Cache from './cache.js';
|
import FileCache from './file-cache.js';
|
||||||
|
import KeyValueCache from './key-value-cache.js';
|
||||||
import Settings from './settings.js';
|
import Settings from './settings.js';
|
||||||
import Shortcut from './shortcut.js';
|
import Shortcut from './shortcut.js';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Cache,
|
FileCache,
|
||||||
|
KeyValueCache,
|
||||||
Settings,
|
Settings,
|
||||||
Shortcut,
|
Shortcut,
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,7 +2,7 @@ import {Table, Column, PrimaryKey, Model} from 'sequelize-typescript';
|
||||||
import sequelize from 'sequelize';
|
import sequelize from 'sequelize';
|
||||||
|
|
||||||
@Table
|
@Table
|
||||||
export default class Cache extends Model<Cache> {
|
export default class KeyValueCache extends Model {
|
||||||
@PrimaryKey
|
@PrimaryKey
|
||||||
@Column
|
@Column
|
||||||
key!: string;
|
key!: string;
|
|
@ -1,7 +1,7 @@
|
||||||
import {Table, Column, PrimaryKey, Model, Default} from 'sequelize-typescript';
|
import {Table, Column, PrimaryKey, Model, Default} from 'sequelize-typescript';
|
||||||
|
|
||||||
@Table
|
@Table
|
||||||
export default class Settings extends Model<Settings> {
|
export default class Settings extends Model {
|
||||||
@PrimaryKey
|
@PrimaryKey
|
||||||
@Column
|
@Column
|
||||||
guildId!: string;
|
guildId!: string;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import {Table, Column, PrimaryKey, Model, AutoIncrement, Index} from 'sequelize-typescript';
|
import {Table, Column, PrimaryKey, Model, AutoIncrement, Index} from 'sequelize-typescript';
|
||||||
|
|
||||||
@Table
|
@Table
|
||||||
export default class Shortcut extends Model<Shortcut> {
|
export default class Shortcut extends Model {
|
||||||
@PrimaryKey
|
@PrimaryKey
|
||||||
@AutoIncrement
|
@AutoIncrement
|
||||||
@Column
|
@Column
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import dotenv from 'dotenv';
|
import dotenv from 'dotenv';
|
||||||
import {injectable} from 'inversify';
|
import {injectable} from 'inversify';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import xbytes from 'xbytes';
|
||||||
|
import {ConditionalKeys} from 'type-fest';
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
export const DATA_DIR = path.resolve(process.env.DATA_DIR ? process.env.DATA_DIR : './data');
|
export const DATA_DIR = path.resolve(process.env.DATA_DIR ? process.env.DATA_DIR : './data');
|
||||||
|
@ -12,6 +14,7 @@ const CONFIG_MAP = {
|
||||||
SPOTIFY_CLIENT_SECRET: process.env.SPOTIFY_CLIENT_SECRET,
|
SPOTIFY_CLIENT_SECRET: process.env.SPOTIFY_CLIENT_SECRET,
|
||||||
DATA_DIR,
|
DATA_DIR,
|
||||||
CACHE_DIR: path.join(DATA_DIR, 'cache'),
|
CACHE_DIR: path.join(DATA_DIR, 'cache'),
|
||||||
|
CACHE_LIMIT_IN_BYTES: xbytes.parseSize(process.env.CACHE_LIMIT ?? '2GB'),
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
|
@ -22,6 +25,7 @@ export default class Config {
|
||||||
readonly SPOTIFY_CLIENT_SECRET!: string;
|
readonly SPOTIFY_CLIENT_SECRET!: string;
|
||||||
readonly DATA_DIR!: string;
|
readonly DATA_DIR!: string;
|
||||||
readonly CACHE_DIR!: string;
|
readonly CACHE_DIR!: string;
|
||||||
|
readonly CACHE_LIMIT_IN_BYTES!: number;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
for (const [key, value] of Object.entries(CONFIG_MAP)) {
|
for (const [key, value] of Object.entries(CONFIG_MAP)) {
|
||||||
|
@ -30,7 +34,13 @@ export default class Config {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
this[key as keyof typeof CONFIG_MAP] = value;
|
if (typeof value === 'number') {
|
||||||
|
this[key as ConditionalKeys<typeof CONFIG_MAP, number>] = value;
|
||||||
|
} else if (typeof value === 'string') {
|
||||||
|
this[key as ConditionalKeys<typeof CONFIG_MAP, string>] = value;
|
||||||
|
} else {
|
||||||
|
throw new Error(`Unsupported type for ${key}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
117
src/services/file-cache.ts
Normal file
117
src/services/file-cache.ts
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
import {promises as fs, createWriteStream} from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
import {inject, injectable} from 'inversify';
|
||||||
|
import sequelize from 'sequelize';
|
||||||
|
import {FileCache} from '../models/index.js';
|
||||||
|
import {TYPES} from '../types.js';
|
||||||
|
import Config from './config.js';
|
||||||
|
|
||||||
|
@injectable()
|
||||||
|
export default class FileCacheProvider {
|
||||||
|
private readonly config: Config;
|
||||||
|
|
||||||
|
constructor(@inject(TYPES.Config) config: Config) {
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns path to cached file if it exists, otherwise throws an error.
|
||||||
|
* Updates the `accessedAt` property of the cached file.
|
||||||
|
* @param hash lookup key
|
||||||
|
*/
|
||||||
|
async getPathFor(hash: string): Promise<string> {
|
||||||
|
const model = await FileCache.findByPk(hash);
|
||||||
|
|
||||||
|
if (!model) {
|
||||||
|
throw new Error('File is not cached');
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolvedPath = path.join(this.config.CACHE_DIR, hash);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await fs.access(resolvedPath);
|
||||||
|
} catch (_: unknown) {
|
||||||
|
await FileCache.destroy({where: {hash}});
|
||||||
|
|
||||||
|
throw new Error('File is not cached');
|
||||||
|
}
|
||||||
|
|
||||||
|
await model.update({accessedAt: new Date()});
|
||||||
|
|
||||||
|
return resolvedPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a write stream for the given hash key.
|
||||||
|
* The stream handles saving a new file and will
|
||||||
|
* update the database after the stream is closed.
|
||||||
|
* @param hash lookup key
|
||||||
|
*/
|
||||||
|
createWriteStream(hash: string) {
|
||||||
|
const tmpPath = path.join(this.config.CACHE_DIR, 'tmp', hash);
|
||||||
|
const finalPath = path.join(this.config.CACHE_DIR, hash);
|
||||||
|
|
||||||
|
const stream = createWriteStream(tmpPath);
|
||||||
|
|
||||||
|
stream.on('close', async () => {
|
||||||
|
// Only move if size is non-zero (may have errored out)
|
||||||
|
const stats = await fs.stat(tmpPath);
|
||||||
|
|
||||||
|
if (stats.size !== 0) {
|
||||||
|
await fs.rename(tmpPath, finalPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
await FileCache.create({hash, bytes: stats.size, accessedAt: new Date()});
|
||||||
|
|
||||||
|
await this.evictOldestIfNecessary();
|
||||||
|
});
|
||||||
|
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes orphaned cache files and evicts files if
|
||||||
|
* necessary. Should be run on program startup so files
|
||||||
|
* will be evicted if the cache limit has changed.
|
||||||
|
*/
|
||||||
|
async cleanup() {
|
||||||
|
await this.removeOrphans();
|
||||||
|
await this.evictOldestIfNecessary();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async evictOldestIfNecessary() {
|
||||||
|
const [{dataValues: {totalSizeBytes}}] = await FileCache.findAll({
|
||||||
|
attributes: [
|
||||||
|
[sequelize.fn('sum', sequelize.col('bytes')), 'totalSizeBytes'],
|
||||||
|
],
|
||||||
|
}) as unknown as [{dataValues: {totalSizeBytes: number}}];
|
||||||
|
|
||||||
|
if (totalSizeBytes > this.config.CACHE_LIMIT_IN_BYTES) {
|
||||||
|
const oldest = await FileCache.findOne({
|
||||||
|
order: [
|
||||||
|
['accessedAt', 'ASC'],
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (oldest) {
|
||||||
|
await oldest.destroy();
|
||||||
|
await fs.unlink(path.join(this.config.CACHE_DIR, oldest.hash));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continue to evict until we're under the limit
|
||||||
|
await this.evictOldestIfNecessary();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async removeOrphans() {
|
||||||
|
for await (const dirent of await fs.opendir(this.config.CACHE_DIR)) {
|
||||||
|
if (dirent.isFile()) {
|
||||||
|
const model = await FileCache.findByPk(dirent.name);
|
||||||
|
|
||||||
|
if (!model) {
|
||||||
|
await fs.unlink(path.join(this.config.CACHE_DIR, dirent.name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,7 +14,7 @@ import {TYPES} from '../types.js';
|
||||||
import {cleanUrl} from '../utils/url.js';
|
import {cleanUrl} from '../utils/url.js';
|
||||||
import ThirdParty from './third-party.js';
|
import ThirdParty from './third-party.js';
|
||||||
import Config from './config.js';
|
import Config from './config.js';
|
||||||
import CacheProvider from './cache.js';
|
import KeyValueCacheProvider from './key-value-cache.js';
|
||||||
|
|
||||||
type QueuedSongWithoutChannel = Except<QueuedSong, 'addedInChannelId'>;
|
type QueuedSongWithoutChannel = Except<QueuedSong, 'addedInChannelId'>;
|
||||||
|
|
||||||
|
@ -26,14 +26,14 @@ export default class {
|
||||||
private readonly youtube: YouTube;
|
private readonly youtube: YouTube;
|
||||||
private readonly youtubeKey: string;
|
private readonly youtubeKey: string;
|
||||||
private readonly spotify: Spotify;
|
private readonly spotify: Spotify;
|
||||||
private readonly cache: CacheProvider;
|
private readonly cache: KeyValueCacheProvider;
|
||||||
|
|
||||||
private readonly ytsrQueue: PQueue;
|
private readonly ytsrQueue: PQueue;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@inject(TYPES.ThirdParty) thirdParty: ThirdParty,
|
@inject(TYPES.ThirdParty) thirdParty: ThirdParty,
|
||||||
@inject(TYPES.Config) config: Config,
|
@inject(TYPES.Config) config: Config,
|
||||||
@inject(TYPES.Cache) cache: CacheProvider) {
|
@inject(TYPES.KeyValueCache) cache: KeyValueCacheProvider) {
|
||||||
this.youtube = thirdParty.youtube;
|
this.youtube = thirdParty.youtube;
|
||||||
this.youtubeKey = config.YOUTUBE_API_KEY;
|
this.youtubeKey = config.YOUTUBE_API_KEY;
|
||||||
this.spotify = thirdParty.spotify;
|
this.spotify = thirdParty.spotify;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import {injectable} from 'inversify';
|
import {injectable} from 'inversify';
|
||||||
import {Cache} from '../models/index.js';
|
import {KeyValueCache} from '../models/index.js';
|
||||||
import debug from '../utils/debug.js';
|
import debug from '../utils/debug.js';
|
||||||
|
|
||||||
type Seconds = number;
|
type Seconds = number;
|
||||||
|
@ -12,7 +12,7 @@ type Options = {
|
||||||
const futureTimeToDate = (time: Seconds) => new Date(new Date().getTime() + (time * 1000));
|
const futureTimeToDate = (time: Seconds) => new Date(new Date().getTime() + (time * 1000));
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export default class CacheProvider {
|
export default class KeyValueCacheProvider {
|
||||||
async wrap<T extends [...any[], Options], F>(func: (...options: any) => Promise<F>, ...options: T): Promise<F> {
|
async wrap<T extends [...any[], Options], F>(func: (...options: any) => Promise<F>, ...options: T): Promise<F> {
|
||||||
if (options.length === 0) {
|
if (options.length === 0) {
|
||||||
throw new Error('Missing cache options');
|
throw new Error('Missing cache options');
|
||||||
|
@ -29,7 +29,7 @@ export default class CacheProvider {
|
||||||
throw new Error(`Cache key ${key} is too short.`);
|
throw new Error(`Cache key ${key} is too short.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const cachedResult = await Cache.findByPk(key);
|
const cachedResult = await KeyValueCache.findByPk(key);
|
||||||
|
|
||||||
if (cachedResult) {
|
if (cachedResult) {
|
||||||
if (new Date() < cachedResult.expiresAt) {
|
if (new Date() < cachedResult.expiresAt) {
|
||||||
|
@ -45,7 +45,7 @@ export default class CacheProvider {
|
||||||
const result = await func(...options as any[]);
|
const result = await func(...options as any[]);
|
||||||
|
|
||||||
// Save result
|
// Save result
|
||||||
await Cache.upsert({
|
await KeyValueCache.upsert({
|
||||||
key,
|
key,
|
||||||
value: JSON.stringify(result),
|
value: JSON.stringify(result),
|
||||||
expiresAt: futureTimeToDate(expiresIn),
|
expiresAt: futureTimeToDate(expiresIn),
|
|
@ -1,7 +1,5 @@
|
||||||
import {VoiceChannel, Snowflake, Client, TextChannel} from 'discord.js';
|
import {VoiceChannel, Snowflake, Client, TextChannel} from 'discord.js';
|
||||||
import {promises as fs, createWriteStream} from 'fs';
|
import {Readable} from 'stream';
|
||||||
import {Readable, PassThrough} from 'stream';
|
|
||||||
import path from 'path';
|
|
||||||
import hasha from 'hasha';
|
import hasha from 'hasha';
|
||||||
import ytdl from 'ytdl-core';
|
import ytdl from 'ytdl-core';
|
||||||
import {WriteStream} from 'fs-capacitor';
|
import {WriteStream} from 'fs-capacitor';
|
||||||
|
@ -9,6 +7,7 @@ import ffmpeg from 'fluent-ffmpeg';
|
||||||
import shuffle from 'array-shuffle';
|
import shuffle from 'array-shuffle';
|
||||||
import errorMsg from '../utils/error-msg.js';
|
import errorMsg from '../utils/error-msg.js';
|
||||||
import {AudioPlayer, AudioPlayerStatus, createAudioPlayer, createAudioResource, joinVoiceChannel, StreamType, VoiceConnection, VoiceConnectionStatus} from '@discordjs/voice';
|
import {AudioPlayer, AudioPlayerStatus, createAudioPlayer, createAudioResource, joinVoiceChannel, StreamType, VoiceConnection, VoiceConnectionStatus} from '@discordjs/voice';
|
||||||
|
import FileCacheProvider from './file-cache.js';
|
||||||
|
|
||||||
export interface QueuedPlaylist {
|
export interface QueuedPlaylist {
|
||||||
title: string;
|
title: string;
|
||||||
|
@ -35,7 +34,6 @@ export default class {
|
||||||
public voiceConnection: VoiceConnection | null = null;
|
public voiceConnection: VoiceConnection | null = null;
|
||||||
private queue: QueuedSong[] = [];
|
private queue: QueuedSong[] = [];
|
||||||
private queuePosition = 0;
|
private queuePosition = 0;
|
||||||
private readonly cacheDir: string;
|
|
||||||
private audioPlayer: AudioPlayer | null = null;
|
private audioPlayer: AudioPlayer | null = null;
|
||||||
private nowPlaying: QueuedSong | null = null;
|
private nowPlaying: QueuedSong | null = null;
|
||||||
private playPositionInterval: NodeJS.Timeout | undefined;
|
private playPositionInterval: NodeJS.Timeout | undefined;
|
||||||
|
@ -44,10 +42,11 @@ export default class {
|
||||||
private positionInSeconds = 0;
|
private positionInSeconds = 0;
|
||||||
|
|
||||||
private readonly discordClient: Client;
|
private readonly discordClient: Client;
|
||||||
|
private readonly fileCache: FileCacheProvider;
|
||||||
|
|
||||||
constructor(cacheDir: string, client: Client) {
|
constructor(client: Client, fileCache: FileCacheProvider) {
|
||||||
this.cacheDir = cacheDir;
|
|
||||||
this.discordClient = client;
|
this.discordClient = client;
|
||||||
|
this.fileCache = fileCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
async connect(channel: VoiceChannel): Promise<void> {
|
async connect(channel: VoiceChannel): Promise<void> {
|
||||||
|
@ -287,40 +286,24 @@ export default class {
|
||||||
return this.queueSize() === 0;
|
return this.queueSize() === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getCachedPath(url: string): string {
|
private getHashForCache(url: string): string {
|
||||||
return path.join(this.cacheDir, hasha(url));
|
return hasha(url);
|
||||||
}
|
|
||||||
|
|
||||||
private getCachedPathTemp(url: string): string {
|
|
||||||
return path.join(this.cacheDir, 'tmp', hasha(url));
|
|
||||||
}
|
|
||||||
|
|
||||||
private async isCached(url: string): Promise<boolean> {
|
|
||||||
try {
|
|
||||||
await fs.access(this.getCachedPath(url));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (_: unknown) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getStream(url: string, options: {seek?: number} = {}): Promise<Readable> {
|
private async getStream(url: string, options: {seek?: number} = {}): Promise<Readable> {
|
||||||
const cachedPath = this.getCachedPath(url);
|
|
||||||
|
|
||||||
let ffmpegInput = '';
|
let ffmpegInput = '';
|
||||||
const ffmpegInputOptions: string[] = [];
|
const ffmpegInputOptions: string[] = [];
|
||||||
let shouldCacheVideo = false;
|
let shouldCacheVideo = false;
|
||||||
|
|
||||||
let format: ytdl.videoFormat | undefined;
|
let format: ytdl.videoFormat | undefined;
|
||||||
|
|
||||||
if (await this.isCached(url)) {
|
try {
|
||||||
ffmpegInput = cachedPath;
|
ffmpegInput = await this.fileCache.getPathFor(this.getHashForCache(url));
|
||||||
|
|
||||||
if (options.seek) {
|
if (options.seek) {
|
||||||
ffmpegInputOptions.push('-ss', options.seek.toString());
|
ffmpegInputOptions.push('-ss', options.seek.toString());
|
||||||
}
|
}
|
||||||
} else {
|
} catch {
|
||||||
// Not yet cached, must download
|
// Not yet cached, must download
|
||||||
const info = await ytdl.getInfo(url);
|
const info = await ytdl.getInfo(url);
|
||||||
|
|
||||||
|
@ -371,7 +354,6 @@ export default class {
|
||||||
'1',
|
'1',
|
||||||
'-reconnect_delay_max',
|
'-reconnect_delay_max',
|
||||||
'5',
|
'5',
|
||||||
'-re',
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (options.seek) {
|
if (options.seek) {
|
||||||
|
@ -382,6 +364,17 @@ export default class {
|
||||||
|
|
||||||
// Create stream and pipe to capacitor
|
// Create stream and pipe to capacitor
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
const capacitor = new WriteStream();
|
||||||
|
|
||||||
|
// Cache video if necessary
|
||||||
|
if (shouldCacheVideo) {
|
||||||
|
const cacheStream = this.fileCache.createWriteStream(this.getHashForCache(url));
|
||||||
|
|
||||||
|
capacitor.createReadStream().pipe(cacheStream);
|
||||||
|
} else {
|
||||||
|
ffmpegInputOptions.push('-re');
|
||||||
|
}
|
||||||
|
|
||||||
const youtubeStream = ffmpeg(ffmpegInput)
|
const youtubeStream = ffmpeg(ffmpegInput)
|
||||||
.inputOptions(ffmpegInputOptions)
|
.inputOptions(ffmpegInputOptions)
|
||||||
.noVideo()
|
.noVideo()
|
||||||
|
@ -390,29 +383,9 @@ export default class {
|
||||||
.on('error', error => {
|
.on('error', error => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
reject(error);
|
reject(error);
|
||||||
})
|
|
||||||
.pipe() as PassThrough;
|
|
||||||
|
|
||||||
const capacitor = new WriteStream();
|
|
||||||
|
|
||||||
youtubeStream.pipe(capacitor);
|
|
||||||
|
|
||||||
// Cache video if necessary
|
|
||||||
if (shouldCacheVideo) {
|
|
||||||
const cacheTempPath = this.getCachedPathTemp(url);
|
|
||||||
const cacheStream = createWriteStream(cacheTempPath);
|
|
||||||
|
|
||||||
cacheStream.on('finish', async () => {
|
|
||||||
// Only move if size is non-zero (may have errored out)
|
|
||||||
const stats = await fs.stat(cacheTempPath);
|
|
||||||
|
|
||||||
if (stats.size !== 0) {
|
|
||||||
await fs.rename(cacheTempPath, cachedPath);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
capacitor.createReadStream().pipe(cacheStream);
|
youtubeStream.pipe(capacitor);
|
||||||
}
|
|
||||||
|
|
||||||
resolve(capacitor.createReadStream());
|
resolve(capacitor.createReadStream());
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
export const TYPES = {
|
export const TYPES = {
|
||||||
Bot: Symbol('Bot'),
|
Bot: Symbol('Bot'),
|
||||||
Cache: Symbol('Cache'),
|
KeyValueCache: Symbol('KeyValueCache'),
|
||||||
|
FileCache: Symbol('FileCache'),
|
||||||
Client: Symbol('Client'),
|
Client: Symbol('Client'),
|
||||||
Config: Symbol('Config'),
|
Config: Symbol('Config'),
|
||||||
Command: Symbol('Command'),
|
Command: Symbol('Command'),
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import {Sequelize} from 'sequelize-typescript';
|
import {Sequelize} from 'sequelize-typescript';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import {DATA_DIR} from '../services/config.js';
|
import {DATA_DIR} from '../services/config.js';
|
||||||
import {Cache, Settings, Shortcut} from '../models/index.js';
|
import {FileCache, KeyValueCache, Settings, Shortcut} from '../models/index.js';
|
||||||
|
|
||||||
export const sequelize = new Sequelize({
|
export const sequelize = new Sequelize({
|
||||||
dialect: 'sqlite',
|
dialect: 'sqlite',
|
||||||
database: 'muse',
|
database: 'muse',
|
||||||
storage: path.join(DATA_DIR, 'db.sqlite'),
|
storage: path.join(DATA_DIR, 'db.sqlite'),
|
||||||
models: [Cache, Settings, Shortcut],
|
models: [FileCache, KeyValueCache, Settings, Shortcut],
|
||||||
logging: false,
|
logging: false,
|
||||||
});
|
});
|
||||||
|
|
238
yarn.lock
238
yarn.lock
|
@ -610,11 +610,6 @@ block-stream@*:
|
||||||
dependencies:
|
dependencies:
|
||||||
inherits "~2.0.0"
|
inherits "~2.0.0"
|
||||||
|
|
||||||
bluebird@^3.5.0:
|
|
||||||
version "3.7.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
|
|
||||||
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
|
|
||||||
|
|
||||||
boxen@^5.0.0:
|
boxen@^5.0.0:
|
||||||
version "5.1.2"
|
version "5.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50"
|
resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50"
|
||||||
|
@ -750,6 +745,15 @@ cli-boxes@^2.2.1:
|
||||||
resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f"
|
resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f"
|
||||||
integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==
|
integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==
|
||||||
|
|
||||||
|
cliui@^7.0.2:
|
||||||
|
version "7.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
|
||||||
|
integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==
|
||||||
|
dependencies:
|
||||||
|
string-width "^4.2.0"
|
||||||
|
strip-ansi "^6.0.0"
|
||||||
|
wrap-ansi "^7.0.0"
|
||||||
|
|
||||||
clone-response@^1.0.2:
|
clone-response@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b"
|
resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b"
|
||||||
|
@ -757,14 +761,6 @@ clone-response@^1.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
mimic-response "^1.0.0"
|
mimic-response "^1.0.0"
|
||||||
|
|
||||||
cls-bluebird@^2.1.0:
|
|
||||||
version "2.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/cls-bluebird/-/cls-bluebird-2.1.0.tgz#37ef1e080a8ffb55c2f4164f536f1919e7968aee"
|
|
||||||
integrity sha1-N+8eCAqP+1XC9BZPU28ZGeeWiu4=
|
|
||||||
dependencies:
|
|
||||||
is-bluebird "^1.0.2"
|
|
||||||
shimmer "^1.1.0"
|
|
||||||
|
|
||||||
code-point-at@^1.0.0:
|
code-point-at@^1.0.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
|
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
|
||||||
|
@ -821,6 +817,20 @@ concat-map@0.0.1:
|
||||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||||
|
|
||||||
|
concurrently@^6.4.0:
|
||||||
|
version "6.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-6.4.0.tgz#5387ee86be435a0eb51c292ade8a00acf479f170"
|
||||||
|
integrity sha512-HZ3D0RTQMH3oS4gvtYj1P+NBc6PzE2McEra6yEFcQKrUQ9HvtTGU4Dbne083F034p+LRb7kWU0tPRNvSGs1UCQ==
|
||||||
|
dependencies:
|
||||||
|
chalk "^4.1.0"
|
||||||
|
date-fns "^2.16.1"
|
||||||
|
lodash "^4.17.21"
|
||||||
|
rxjs "^6.6.3"
|
||||||
|
spawn-command "^0.0.2-1"
|
||||||
|
supports-color "^8.1.0"
|
||||||
|
tree-kill "^1.2.2"
|
||||||
|
yargs "^16.2.0"
|
||||||
|
|
||||||
configstore@^5.0.1:
|
configstore@^5.0.1:
|
||||||
version "5.0.1"
|
version "5.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96"
|
resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96"
|
||||||
|
@ -895,6 +905,11 @@ dashdash@^1.12.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
assert-plus "^1.0.0"
|
assert-plus "^1.0.0"
|
||||||
|
|
||||||
|
date-fns@^2.16.1:
|
||||||
|
version "2.25.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.25.0.tgz#8c5c8f1d958be3809a9a03f4b742eba894fc5680"
|
||||||
|
integrity sha512-ovYRFnTrbGPD4nqaEqescPEv1mNwvt+UTqI3Ay9SzNtey9NZnYu6E2qCcBBgJ6/2VF1zGGygpyTDITqpQQ5e+w==
|
||||||
|
|
||||||
debug@4, debug@^4.0.1, debug@^4.1.1, debug@^4.3.1:
|
debug@4, debug@^4.0.1, debug@^4.1.1, debug@^4.3.1:
|
||||||
version "4.3.2"
|
version "4.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
|
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
|
||||||
|
@ -1072,6 +1087,11 @@ error-ex@^1.3.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
is-arrayish "^0.2.1"
|
is-arrayish "^0.2.1"
|
||||||
|
|
||||||
|
escalade@^3.1.1:
|
||||||
|
version "3.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
||||||
|
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
|
||||||
|
|
||||||
escape-goat@^2.0.0:
|
escape-goat@^2.0.0:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675"
|
resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675"
|
||||||
|
@ -1365,10 +1385,10 @@ formidable@^1.2.2:
|
||||||
resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.6.tgz#d2a51d60162bbc9b4a055d8457a7c75315d1a168"
|
resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.6.tgz#d2a51d60162bbc9b4a055d8457a7c75315d1a168"
|
||||||
integrity sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==
|
integrity sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==
|
||||||
|
|
||||||
fs-capacitor@^6.2.0:
|
fs-capacitor@^7.0.1:
|
||||||
version "6.2.0"
|
version "7.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/fs-capacitor/-/fs-capacitor-6.2.0.tgz#fa79ac6576629163cb84561995602d8999afb7f5"
|
resolved "https://registry.yarnpkg.com/fs-capacitor/-/fs-capacitor-7.0.1.tgz#351fa0224d74ae5ee17fdd165055082426ac60a3"
|
||||||
integrity sha512-nKcE1UduoSKX27NSZlg879LdQc94OtbOsEmKMN2MBNudXREvijRKx2GEBsTMTfws+BrbkJoEuynbGSVRSpauvw==
|
integrity sha512-YjxAAorsFA/pK3PTLuYJO+FlZ7wvGTIwGPbpGzVAJ+DUp6uof0zZjG6dcYsrGX864BMeUCj9R6lmkYZ5uY5lWQ==
|
||||||
|
|
||||||
fs-minipass@^1.2.7:
|
fs-minipass@^1.2.7:
|
||||||
version "1.2.7"
|
version "1.2.7"
|
||||||
|
@ -1443,6 +1463,11 @@ gauge@~2.7.3:
|
||||||
strip-ansi "^3.0.1"
|
strip-ansi "^3.0.1"
|
||||||
wide-align "^1.1.0"
|
wide-align "^1.1.0"
|
||||||
|
|
||||||
|
get-caller-file@^2.0.5:
|
||||||
|
version "2.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
||||||
|
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
||||||
|
|
||||||
get-intrinsic@^1.0.2:
|
get-intrinsic@^1.0.2:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6"
|
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6"
|
||||||
|
@ -1485,19 +1510,7 @@ glob-parent@^5.1.2, glob-parent@~5.1.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
is-glob "^4.0.1"
|
is-glob "^4.0.1"
|
||||||
|
|
||||||
glob@7.1.2:
|
glob@7.2.0, glob@^7.0.3, glob@^7.1.3:
|
||||||
version "7.1.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
|
|
||||||
integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==
|
|
||||||
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"
|
|
||||||
|
|
||||||
glob@^7.0.3, glob@^7.1.3:
|
|
||||||
version "7.2.0"
|
version "7.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
|
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
|
||||||
integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==
|
integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==
|
||||||
|
@ -1720,10 +1733,10 @@ imurmurhash@^0.1.4:
|
||||||
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
||||||
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
|
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
|
||||||
|
|
||||||
inflection@1.12.0:
|
inflection@1.13.1:
|
||||||
version "1.12.0"
|
version "1.13.1"
|
||||||
resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.12.0.tgz#a200935656d6f5f6bc4dc7502e1aecb703228416"
|
resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.13.1.tgz#c5cadd80888a90cf84c2e96e340d7edc85d5f0cb"
|
||||||
integrity sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=
|
integrity sha512-dldYtl2WlN0QDkIDtg8+xFwOS2Tbmp12t1cHa5/YClU6ZQjTFm7B66UcVbh9NQB+HvT5BAd2t5+yKsBkw5pcqA==
|
||||||
|
|
||||||
inflight@^1.0.4:
|
inflight@^1.0.4:
|
||||||
version "1.0.6"
|
version "1.0.6"
|
||||||
|
@ -1765,11 +1778,6 @@ is-binary-path@~2.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
binary-extensions "^2.0.0"
|
binary-extensions "^2.0.0"
|
||||||
|
|
||||||
is-bluebird@^1.0.2:
|
|
||||||
version "1.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/is-bluebird/-/is-bluebird-1.0.2.tgz#096439060f4aa411abee19143a84d6a55346d6e2"
|
|
||||||
integrity sha1-CWQ5Bg9KpBGr7hkUOoTWpVNG1uI=
|
|
||||||
|
|
||||||
is-ci@^2.0.0:
|
is-ci@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c"
|
resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c"
|
||||||
|
@ -2005,7 +2013,7 @@ lodash.truncate@^4.4.2:
|
||||||
resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
|
resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
|
||||||
integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=
|
integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=
|
||||||
|
|
||||||
lodash@^4.17.15, lodash@^4.17.21:
|
lodash@^4.17.20, lodash@^4.17.21:
|
||||||
version "4.17.21"
|
version "4.17.21"
|
||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||||
|
@ -2151,14 +2159,14 @@ mkdirp@^1.0.3:
|
||||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
||||||
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
|
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
|
||||||
|
|
||||||
moment-timezone@^0.5.21:
|
moment-timezone@^0.5.31:
|
||||||
version "0.5.34"
|
version "0.5.34"
|
||||||
resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.34.tgz#a75938f7476b88f155d3504a9343f7519d9a405c"
|
resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.34.tgz#a75938f7476b88f155d3504a9343f7519d9a405c"
|
||||||
integrity sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==
|
integrity sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==
|
||||||
dependencies:
|
dependencies:
|
||||||
moment ">= 2.9.0"
|
moment ">= 2.9.0"
|
||||||
|
|
||||||
"moment@>= 2.9.0", moment@^2.24.0:
|
"moment@>= 2.9.0", moment@^2.26.0:
|
||||||
version "2.29.1"
|
version "2.29.1"
|
||||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
|
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
|
||||||
integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
|
integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
|
||||||
|
@ -2533,6 +2541,11 @@ performance-now@^2.1.0:
|
||||||
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
|
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
|
||||||
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
|
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
|
||||||
|
|
||||||
|
pg-connection-string@^2.5.0:
|
||||||
|
version "2.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.5.0.tgz#538cadd0f7e603fc09a12590f3b8a452c2c0cf34"
|
||||||
|
integrity sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==
|
||||||
|
|
||||||
picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3:
|
picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3:
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
|
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
|
||||||
|
@ -2718,6 +2731,11 @@ request@^2.87.0:
|
||||||
tunnel-agent "^0.6.0"
|
tunnel-agent "^0.6.0"
|
||||||
uuid "^3.3.2"
|
uuid "^3.3.2"
|
||||||
|
|
||||||
|
require-directory@^2.1.1:
|
||||||
|
version "2.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
|
||||||
|
integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
|
||||||
|
|
||||||
require-from-string@^2.0.2:
|
require-from-string@^2.0.2:
|
||||||
version "2.0.2"
|
version "2.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
|
resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
|
||||||
|
@ -2780,6 +2798,13 @@ run-parallel@^1.1.9:
|
||||||
dependencies:
|
dependencies:
|
||||||
queue-microtask "^1.2.2"
|
queue-microtask "^1.2.2"
|
||||||
|
|
||||||
|
rxjs@^6.6.3:
|
||||||
|
version "6.6.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
|
||||||
|
integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==
|
||||||
|
dependencies:
|
||||||
|
tslib "^1.9.0"
|
||||||
|
|
||||||
safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@^5.2.1, safe-buffer@~5.2.0:
|
safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@^5.2.1, safe-buffer@~5.2.0:
|
||||||
version "5.2.1"
|
version "5.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||||
|
@ -2839,38 +2864,37 @@ semver@~5.3.0:
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
|
||||||
integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8=
|
integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8=
|
||||||
|
|
||||||
sequelize-pool@^2.3.0:
|
sequelize-pool@^6.0.0:
|
||||||
version "2.3.0"
|
version "6.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/sequelize-pool/-/sequelize-pool-2.3.0.tgz#64f1fe8744228172c474f530604b6133be64993d"
|
resolved "https://registry.yarnpkg.com/sequelize-pool/-/sequelize-pool-6.1.0.tgz#caaa0c1e324d3c2c3a399fed2c7998970925d668"
|
||||||
integrity sha512-Ibz08vnXvkZ8LJTiUOxRcj1Ckdn7qafNZ2t59jYHMX1VIebTAOYefWdRYFt6z6+hy52WGthAHAoLc9hvk3onqA==
|
integrity sha512-4YwEw3ZgK/tY/so+GfnSgXkdwIJJ1I32uZJztIEgZeAO6HMgj64OzySbWLgxj+tXhZCJnzRfkY9gINw8Ft8ZMg==
|
||||||
|
|
||||||
sequelize-typescript@^1.1.0:
|
sequelize-typescript@^2.1.1:
|
||||||
version "1.1.0"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/sequelize-typescript/-/sequelize-typescript-1.1.0.tgz#d5c2945e7fbfe55a934917b27d84589858d79123"
|
resolved "https://registry.yarnpkg.com/sequelize-typescript/-/sequelize-typescript-2.1.1.tgz#92445632062db868b760cd20215406403da737a2"
|
||||||
integrity sha512-FAPEQPeAhIaFQNLAcf9Q2IWcqWhNcvn5OZZ7BzGB0CJMtImIsGg4E/EAb7huMmPaPwDArxJUWGqk1KurphTNRA==
|
integrity sha512-4am/5O6dlAvtR/akH2KizcECm4rRAjWr+oc5mo9vFVMez8hrbOhQlDNzk0H6VMOQASCN7yBF+qOnSEN60V6/vA==
|
||||||
dependencies:
|
dependencies:
|
||||||
glob "7.1.2"
|
glob "7.2.0"
|
||||||
|
|
||||||
sequelize@^5.22.4:
|
sequelize@^6.11.0:
|
||||||
version "5.22.4"
|
version "6.11.0"
|
||||||
resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-5.22.4.tgz#4dbd8a1a735e98150880d43a95d45e9f46d151fa"
|
resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-6.11.0.tgz#11620b02ab2ca02af59ec652dd22bef7ccd348af"
|
||||||
integrity sha512-xFQQ38HPg7EyDRDA+NdzMSRWbo9m6Z/RxpjnkBl3ggyQG+jRrup48x0jaw4Ox42h56wFnXOBC2NZOkTJfZeWCw==
|
integrity sha512-+j3N5lr+FR1eicMRGR3bRsGOl9HMY0UGb2PyB2i1yZ64XBgsz3xejMH0UD45LcUitj40soDGIa9CyvZG0dfzKg==
|
||||||
dependencies:
|
dependencies:
|
||||||
bluebird "^3.5.0"
|
|
||||||
cls-bluebird "^2.1.0"
|
|
||||||
debug "^4.1.1"
|
debug "^4.1.1"
|
||||||
dottie "^2.0.0"
|
dottie "^2.0.0"
|
||||||
inflection "1.12.0"
|
inflection "1.13.1"
|
||||||
lodash "^4.17.15"
|
lodash "^4.17.20"
|
||||||
moment "^2.24.0"
|
moment "^2.26.0"
|
||||||
moment-timezone "^0.5.21"
|
moment-timezone "^0.5.31"
|
||||||
|
pg-connection-string "^2.5.0"
|
||||||
retry-as-promised "^3.2.0"
|
retry-as-promised "^3.2.0"
|
||||||
semver "^6.3.0"
|
semver "^7.3.2"
|
||||||
sequelize-pool "^2.3.0"
|
sequelize-pool "^6.0.0"
|
||||||
toposort-class "^1.0.1"
|
toposort-class "^1.0.1"
|
||||||
uuid "^3.3.3"
|
uuid "^8.1.0"
|
||||||
validator "^10.11.0"
|
validator "^13.7.0"
|
||||||
wkx "^0.4.8"
|
wkx "^0.5.0"
|
||||||
|
|
||||||
set-blocking@^2.0.0, set-blocking@~2.0.0:
|
set-blocking@^2.0.0, set-blocking@~2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
|
@ -2889,11 +2913,6 @@ shebang-regex@^3.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
|
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
|
||||||
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
|
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
|
||||||
|
|
||||||
shimmer@^1.1.0:
|
|
||||||
version "1.2.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337"
|
|
||||||
integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==
|
|
||||||
|
|
||||||
side-channel@^1.0.4:
|
side-channel@^1.0.4:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
|
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
|
||||||
|
@ -2922,6 +2941,11 @@ slice-ansi@^4.0.0:
|
||||||
astral-regex "^2.0.0"
|
astral-regex "^2.0.0"
|
||||||
is-fullwidth-code-point "^3.0.0"
|
is-fullwidth-code-point "^3.0.0"
|
||||||
|
|
||||||
|
spawn-command@^0.0.2-1:
|
||||||
|
version "0.0.2-1"
|
||||||
|
resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0"
|
||||||
|
integrity sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=
|
||||||
|
|
||||||
spotify-uri@^2.2.0:
|
spotify-uri@^2.2.0:
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/spotify-uri/-/spotify-uri-2.2.0.tgz#8db641615cf6e122284874287fe39e89595922df"
|
resolved "https://registry.yarnpkg.com/spotify-uri/-/spotify-uri-2.2.0.tgz#8db641615cf6e122284874287fe39e89595922df"
|
||||||
|
@ -2981,7 +3005,7 @@ string-width@^1.0.1:
|
||||||
is-fullwidth-code-point "^2.0.0"
|
is-fullwidth-code-point "^2.0.0"
|
||||||
strip-ansi "^4.0.0"
|
strip-ansi "^4.0.0"
|
||||||
|
|
||||||
"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.2, string-width@^4.2.3:
|
"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
|
||||||
version "4.2.3"
|
version "4.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||||
|
@ -3066,6 +3090,13 @@ supports-color@^7.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
has-flag "^4.0.0"
|
has-flag "^4.0.0"
|
||||||
|
|
||||||
|
supports-color@^8.1.0:
|
||||||
|
version "8.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
|
||||||
|
integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
|
||||||
|
dependencies:
|
||||||
|
has-flag "^4.0.0"
|
||||||
|
|
||||||
table@^6.0.9:
|
table@^6.0.9:
|
||||||
version "6.7.3"
|
version "6.7.3"
|
||||||
resolved "https://registry.yarnpkg.com/table/-/table-6.7.3.tgz#255388439715a738391bd2ee4cbca89a4d05a9b7"
|
resolved "https://registry.yarnpkg.com/table/-/table-6.7.3.tgz#255388439715a738391bd2ee4cbca89a4d05a9b7"
|
||||||
|
@ -3158,6 +3189,11 @@ tr46@~0.0.3:
|
||||||
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
|
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
|
||||||
integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=
|
integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=
|
||||||
|
|
||||||
|
tree-kill@^1.2.2:
|
||||||
|
version "1.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
|
||||||
|
integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==
|
||||||
|
|
||||||
ts-mixer@^6.0.0:
|
ts-mixer@^6.0.0:
|
||||||
version "6.0.0"
|
version "6.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/ts-mixer/-/ts-mixer-6.0.0.tgz#4e631d3a36e3fa9521b973b132e8353bc7267f9f"
|
resolved "https://registry.yarnpkg.com/ts-mixer/-/ts-mixer-6.0.0.tgz#4e631d3a36e3fa9521b973b132e8353bc7267f9f"
|
||||||
|
@ -3181,7 +3217,7 @@ ts-node@^10.4.0:
|
||||||
make-error "^1.1.1"
|
make-error "^1.1.1"
|
||||||
yn "3.1.1"
|
yn "3.1.1"
|
||||||
|
|
||||||
tslib@^1.8.1:
|
tslib@^1.8.1, tslib@^1.9.0:
|
||||||
version "1.14.1"
|
version "1.14.1"
|
||||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
||||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||||
|
@ -3232,6 +3268,11 @@ type-fest@^1.2.1:
|
||||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1"
|
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1"
|
||||||
integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==
|
integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==
|
||||||
|
|
||||||
|
type-fest@^2.5.4:
|
||||||
|
version "2.5.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.5.4.tgz#1613bf29a172ff1c66c29325466af9096fe505b5"
|
||||||
|
integrity sha512-zyPomVvb6u7+gJ/GPYUH6/nLDNiTtVOqXVUHtxFv5PmZQh6skgfeRtFYzWC01T5KeNWNIx5/0P111rKFLlkFvA==
|
||||||
|
|
||||||
typedarray-to-buffer@^3.1.5:
|
typedarray-to-buffer@^3.1.5:
|
||||||
version "3.1.5"
|
version "3.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080"
|
resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080"
|
||||||
|
@ -3295,11 +3336,16 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1:
|
||||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||||
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
||||||
|
|
||||||
uuid@^3.3.2, uuid@^3.3.3:
|
uuid@^3.3.2:
|
||||||
version "3.4.0"
|
version "3.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
|
||||||
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
|
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
|
||||||
|
|
||||||
|
uuid@^8.1.0:
|
||||||
|
version "8.3.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
|
||||||
|
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
||||||
|
|
||||||
v8-compile-cache@^2.0.3:
|
v8-compile-cache@^2.0.3:
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
|
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
|
||||||
|
@ -3310,10 +3356,10 @@ vali-date@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6"
|
resolved "https://registry.yarnpkg.com/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6"
|
||||||
integrity sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=
|
integrity sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=
|
||||||
|
|
||||||
validator@^10.11.0:
|
validator@^13.7.0:
|
||||||
version "10.11.0"
|
version "13.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/validator/-/validator-10.11.0.tgz#003108ea6e9a9874d31ccc9e5006856ccd76b228"
|
resolved "https://registry.yarnpkg.com/validator/-/validator-13.7.0.tgz#4f9658ba13ba8f3d82ee881d3516489ea85c0857"
|
||||||
integrity sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==
|
integrity sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==
|
||||||
|
|
||||||
verror@1.10.0:
|
verror@1.10.0:
|
||||||
version "1.10.0"
|
version "1.10.0"
|
||||||
|
@ -3370,10 +3416,10 @@ widest-line@^3.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
string-width "^4.0.0"
|
string-width "^4.0.0"
|
||||||
|
|
||||||
wkx@^0.4.8:
|
wkx@^0.5.0:
|
||||||
version "0.4.8"
|
version "0.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/wkx/-/wkx-0.4.8.tgz#a092cf088d112683fdc7182fd31493b2c5820003"
|
resolved "https://registry.yarnpkg.com/wkx/-/wkx-0.5.0.tgz#c6c37019acf40e517cc6b94657a25a3d4aa33e8c"
|
||||||
integrity sha512-ikPXMM9IR/gy/LwiOSqWlSL3X/J5uk9EO2hHNRXS41eTLXaUFEVw9fn/593jW/tE5tedNg8YjT5HkCa4FqQZyQ==
|
integrity sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
|
@ -3411,11 +3457,21 @@ ws@^8.2.3:
|
||||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba"
|
resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba"
|
||||||
integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==
|
integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==
|
||||||
|
|
||||||
|
xbytes@^1.7.0:
|
||||||
|
version "1.7.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/xbytes/-/xbytes-1.7.0.tgz#a44ca476af66c54e79f744756a035326c697bb8d"
|
||||||
|
integrity sha512-iZglBXuHoC1F7jRz7746QhicNE167tEVq2H/iYQ1jIFdYIjqL8OfM86K52csfRZm+d83/VJO8bu37jN/G1ekKQ==
|
||||||
|
|
||||||
xdg-basedir@^4.0.0:
|
xdg-basedir@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13"
|
resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13"
|
||||||
integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==
|
integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==
|
||||||
|
|
||||||
|
y18n@^5.0.5:
|
||||||
|
version "5.0.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
|
||||||
|
integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
|
||||||
|
|
||||||
yallist@^3.0.0, yallist@^3.1.1:
|
yallist@^3.0.0, yallist@^3.1.1:
|
||||||
version "3.1.1"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
|
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
|
||||||
|
@ -3431,6 +3487,24 @@ yaml@^1.10.0:
|
||||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
|
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
|
||||||
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
|
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
|
||||||
|
|
||||||
|
yargs-parser@^20.2.2:
|
||||||
|
version "20.2.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
|
||||||
|
integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
|
||||||
|
|
||||||
|
yargs@^16.2.0:
|
||||||
|
version "16.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
|
||||||
|
integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==
|
||||||
|
dependencies:
|
||||||
|
cliui "^7.0.2"
|
||||||
|
escalade "^3.1.1"
|
||||||
|
get-caller-file "^2.0.5"
|
||||||
|
require-directory "^2.1.1"
|
||||||
|
string-width "^4.2.0"
|
||||||
|
y18n "^5.0.5"
|
||||||
|
yargs-parser "^20.2.2"
|
||||||
|
|
||||||
yn@3.1.1:
|
yn@3.1.1:
|
||||||
version "3.1.1"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
|
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
|
||||||
|
|
Loading…
Reference in a new issue