Browse Source
- Worker to process link-ingest jobs - Link preview template w/oembed support - CSS for typical link presentation in light & dark themesdevelop
31 changed files with 979 additions and 102 deletions
@ -0,0 +1,264 @@ |
|||||
|
// image.js
|
||||
|
// Copyright (C) 2024 DTP Technologies, LLC
|
||||
|
// All Rights Reserved
|
||||
|
|
||||
|
'use strict'; |
||||
|
|
||||
|
import path from 'node:path'; |
||||
|
import fs from 'node:fs'; |
||||
|
|
||||
|
import mongoose from 'mongoose'; |
||||
|
const StreamRayImage = mongoose.model('Image'); |
||||
|
|
||||
|
import sharp from 'sharp'; |
||||
|
|
||||
|
import { SiteService, SiteAsync } from '../../lib/site-lib.js'; |
||||
|
|
||||
|
export default class ImageService extends SiteService { |
||||
|
|
||||
|
static get name ( ) { return 'ImageService'; } |
||||
|
static get slug ( ) { return 'image'; } |
||||
|
|
||||
|
constructor (dtp) { |
||||
|
super(dtp, ImageService); |
||||
|
} |
||||
|
|
||||
|
async start ( ) { |
||||
|
await super.start(); |
||||
|
|
||||
|
const { user: userService } = this.dtp.services; |
||||
|
this.populateImage = [ |
||||
|
{ |
||||
|
path: 'owner', |
||||
|
select: userService.USER_SELECT, |
||||
|
}, |
||||
|
]; |
||||
|
|
||||
|
await fs.promises.mkdir(process.env.IMAGE_WORK_PATH, { recursive: true }); |
||||
|
} |
||||
|
|
||||
|
async create (owner, imageDefinition, file) { |
||||
|
const NOW = new Date(); |
||||
|
const { chat: chatService, minio: minioService } = this.dtp.services; |
||||
|
|
||||
|
this.log.debug('processing uploaded image', { imageDefinition, file }); |
||||
|
|
||||
|
const sharpImage = await sharp(file.path); |
||||
|
const metadata = await sharpImage.metadata(); |
||||
|
|
||||
|
// create an Image model instance, but leave it here in application memory.
|
||||
|
// we don't persist it to the db until MinIO accepts the binary data.
|
||||
|
const image = new StreamRayImage(); |
||||
|
image.created = NOW; |
||||
|
image.owner = owner._id; |
||||
|
if (imageDefinition.caption) { |
||||
|
image.caption = chatService.filterText(imageDefinition.caption); |
||||
|
} |
||||
|
image.flags.isSensitive = imageDefinition['flags.isSensitive'] === 'on'; |
||||
|
image.flags.isPendingAttachment = imageDefinition['flags.isPendingAttachment'] === 'on'; |
||||
|
|
||||
|
image.type = file.mimetype; |
||||
|
image.size = file.size; |
||||
|
|
||||
|
image.file.bucket = process.env.MINIO_IMAGE_BUCKET; |
||||
|
image.metadata = this.makeImageMetadata(metadata); |
||||
|
|
||||
|
const imageId = image._id.toString(); |
||||
|
const ownerId = owner._id.toString(); |
||||
|
const fileKey = `/${ownerId.slice(0, 3)}/${ownerId}/${imageId.slice(0, 3)}/${imageId}`; |
||||
|
image.file.key = fileKey; |
||||
|
|
||||
|
// upload the image file to MinIO
|
||||
|
const response = await minioService.uploadFile({ |
||||
|
bucket: image.file.bucket, |
||||
|
key: image.file.key, |
||||
|
filePath: file.path, |
||||
|
metadata: { |
||||
|
'Content-Type': file.mimetype, |
||||
|
'Content-Length': file.size, |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
// store the eTag from MinIO in the Image model
|
||||
|
image.file.etag = response.etag; |
||||
|
|
||||
|
// save the Image model to the db
|
||||
|
await image.save(); |
||||
|
|
||||
|
this.log.info('processed uploaded image', { ownerId, imageId, fileKey }); |
||||
|
return image.toObject(); |
||||
|
} |
||||
|
|
||||
|
async getImageById (imageId) { |
||||
|
const image = await StreamRayImage |
||||
|
.findById(imageId) |
||||
|
.populate(this.populateImage); |
||||
|
return image; |
||||
|
} |
||||
|
|
||||
|
async getRecentImagesForOwner (owner) { |
||||
|
const images = await StreamRayImage |
||||
|
.find({ owner: owner._id }) |
||||
|
.sort({ created: -1 }) |
||||
|
.limit(10) |
||||
|
.populate(this.populateImage) |
||||
|
.lean(); |
||||
|
return images; |
||||
|
} |
||||
|
|
||||
|
async deleteImage (image) { |
||||
|
const { minio: minioService } = this.dtp.services; |
||||
|
try { |
||||
|
if (image.file && image.file.bucket && image.file.key) { |
||||
|
// this.log.debug('removing image from storage', { file: image.file });
|
||||
|
await minioService.removeObject(image.file.bucket, image.file.key); |
||||
|
} |
||||
|
} catch (error) { |
||||
|
this.log.error('failed to remove image from storage', { error }); |
||||
|
// fall through
|
||||
|
} |
||||
|
await StreamRayImage.deleteOne({ _id: image._id }); |
||||
|
} |
||||
|
|
||||
|
async processImageFile (owner, file, outputs, options) { |
||||
|
this.log.debug('processing image file', { owner, file, outputs }); |
||||
|
const sharpImage = sharp(file.path); |
||||
|
return this.processImage(owner, sharpImage, outputs, options); |
||||
|
} |
||||
|
|
||||
|
async processImage (owner, sharpImage, outputs, options) { |
||||
|
const NOW = new Date(); |
||||
|
const service = this; |
||||
|
const { minio: minioService } = this.dtp.services; |
||||
|
|
||||
|
options = Object.assign({ |
||||
|
removeWorkFiles: true, |
||||
|
}, options); |
||||
|
|
||||
|
const imageWorkPath = process.env.IMAGE_WORK_PATH || '/tmp'; |
||||
|
const metadata = await sharpImage.metadata(); |
||||
|
|
||||
|
async function processOutputImage (output) { |
||||
|
const outputMetadata = service.makeImageMetadata(metadata); |
||||
|
outputMetadata.width = output.width; |
||||
|
outputMetadata.height = output.height; |
||||
|
|
||||
|
service.log.debug('processing image', { output, outputMetadata }); |
||||
|
|
||||
|
const image = new StreamRayImage(); |
||||
|
image.created = NOW; |
||||
|
image.owner = owner._id; |
||||
|
image.type = `image/${output.format}`; |
||||
|
image.metadata = outputMetadata; |
||||
|
|
||||
|
try { |
||||
|
let chain = sharpImage.clone().resize({ width: output.width, height: output.height }); |
||||
|
chain = chain[output.format](output.formatParameters); |
||||
|
|
||||
|
output.filePath = path.join(imageWorkPath, `${image._id}.${output.width}x${output.height}.${output.format}`); |
||||
|
output.mimetype = `image/${output.format}`; |
||||
|
await chain.toFile(output.filePath); |
||||
|
output.stat = await fs.promises.stat(output.filePath); |
||||
|
} catch (error) { |
||||
|
service.log.error('failed to process output image', { output, error }); |
||||
|
throw error; |
||||
|
} |
||||
|
|
||||
|
try { |
||||
|
const imageId = image._id.toString(); |
||||
|
const ownerId = owner._id.toString(); |
||||
|
const fileKey = `/${ownerId.slice(0, 3)}/${ownerId}/images/${imageId.slice(0, 3)}/${imageId}.${output.format}`; |
||||
|
|
||||
|
image.file.bucket = process.env.MINIO_IMAGE_BUCKET; |
||||
|
image.file.key = fileKey; |
||||
|
image.size = output.stat.size; |
||||
|
|
||||
|
// upload the image file to MinIO
|
||||
|
const response = await minioService.uploadFile({ |
||||
|
bucket: image.file.bucket, |
||||
|
key: image.file.key, |
||||
|
filePath: output.filePath, |
||||
|
metadata: { |
||||
|
'Content-Type': output.mimetype, |
||||
|
'Content-Length': output.stat.size, |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
// store the eTag from MinIO in the Image model
|
||||
|
image.file.etag = response.etag; |
||||
|
|
||||
|
// save the Image model to the db
|
||||
|
await image.save(); |
||||
|
|
||||
|
service.log.info('processed uploaded image', { ownerId, imageId, fileKey }); |
||||
|
|
||||
|
if (options.removeWorkFiles) { |
||||
|
service.log.debug('removing work file', { path: output.filePath }); |
||||
|
await fs.promises.unlink(output.filePath); |
||||
|
delete output.filePath; |
||||
|
} |
||||
|
|
||||
|
output.image = { |
||||
|
_id: image._id, |
||||
|
bucket: image.file.bucket, |
||||
|
key: image.file.key, |
||||
|
}; |
||||
|
} catch (error) { |
||||
|
service.log.error('failed to persist output image', { output, error }); |
||||
|
if (options.removeWorkFiles) { |
||||
|
service.log.debug('removing work file', { path: output.filePath }); |
||||
|
await SiteAsync.each(outputs, async (output) => { |
||||
|
await fs.promises.unlink(output.filePath); |
||||
|
delete output.filePath; |
||||
|
}, 4); |
||||
|
} |
||||
|
throw error; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
await SiteAsync.each(outputs, processOutputImage, 4); |
||||
|
} |
||||
|
|
||||
|
makeImageMetadata (metadata) { |
||||
|
return { |
||||
|
format: metadata.format, |
||||
|
size: metadata.size, |
||||
|
width: metadata.width, |
||||
|
height: metadata.height, |
||||
|
space: metadata.space, |
||||
|
channels: metadata.channels, |
||||
|
depth: metadata.depth, |
||||
|
density: metadata.density, |
||||
|
hasAlpha: metadata.hasAlpha, |
||||
|
orientation: metadata.orientation, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
async reportStats ( ) { |
||||
|
const chart = await StreamRayImage.aggregate([ |
||||
|
{ |
||||
|
$match: { }, |
||||
|
}, |
||||
|
{ |
||||
|
$group: { |
||||
|
_id: { $dateToString: { format: '%Y-%m', date: '$created' } }, |
||||
|
count: { $sum: 1 }, |
||||
|
bytes: { $sum: '$size' }, |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
$sort: { _id: 1 }, |
||||
|
}, |
||||
|
]); |
||||
|
|
||||
|
const stats = { }; |
||||
|
stats.count = chart.reduce((prev, value) => { |
||||
|
return prev + value.count; |
||||
|
}, 0); |
||||
|
stats.bytes = chart.reduce((prev, value) => { |
||||
|
return prev + value.bytes; |
||||
|
}, 0); |
||||
|
|
||||
|
return { chart, stats }; |
||||
|
} |
||||
|
} |
@ -0,0 +1,280 @@ |
|||||
|
// host-services.js
|
||||
|
// Copyright (C) 2024 DTP Technologies, LLC
|
||||
|
// All Rights Reserved
|
||||
|
|
||||
|
'use strict'; |
||||
|
|
||||
|
import 'dotenv/config'; |
||||
|
|
||||
|
import path, { dirname } from 'path'; |
||||
|
import fs from 'node:fs'; |
||||
|
import readline from 'node:readline'; |
||||
|
|
||||
|
import { SiteRuntime } from '../../lib/site-lib.js'; |
||||
|
|
||||
|
import { CronJob } from 'cron'; |
||||
|
const CRON_TIMEZONE = 'America/New_York'; |
||||
|
|
||||
|
import { Readable, pipeline } from 'node:stream'; |
||||
|
import { promisify } from 'node:util'; |
||||
|
const streamPipeline = promisify(pipeline); |
||||
|
|
||||
|
class ChatLinksService extends SiteRuntime { |
||||
|
|
||||
|
static get name ( ) { return 'ChatLinksWorker'; } |
||||
|
static get slug ( ) { return 'chatLinks'; } |
||||
|
|
||||
|
static get BLOCKLIST_URL ( ) { return 'https://raw.githubusercontent.com/StevenBlack/hosts/master/alternates/porn/hosts'; } |
||||
|
|
||||
|
constructor (rootPath) { |
||||
|
super(ChatLinksService, rootPath); |
||||
|
} |
||||
|
|
||||
|
async start ( ) { |
||||
|
await super.start(); |
||||
|
|
||||
|
const mongoose = await import('mongoose'); |
||||
|
this.Link = mongoose.model('Link'); |
||||
|
|
||||
|
this.viewModel = { }; |
||||
|
await this.populateViewModel(this.viewModel); |
||||
|
|
||||
|
this.blacklist = { |
||||
|
porn: path.join(this.config.root, 'data', 'blacklist', 'porn'), |
||||
|
}; |
||||
|
|
||||
|
/* |
||||
|
* Bull Queue job processors |
||||
|
*/ |
||||
|
|
||||
|
this.log.info('registering link-ingest job processor', { config: this.config.jobQueues.links }); |
||||
|
this.linksProcessingQueue = this.services.jobQueue.getJobQueue('links', this.config.jobQueues.links); |
||||
|
this.linksProcessingQueue.process('link-ingest', 1, this.ingestLink.bind(this)); |
||||
|
|
||||
|
/* |
||||
|
* Cron jobs |
||||
|
*/ |
||||
|
|
||||
|
const cronBlacklistUpdate = '0 0 3 * * *'; // Ever day at 3:00 a.m.
|
||||
|
this.log.info('created URL blacklist update cron', { cronBlacklistUpdate }); |
||||
|
this.updateBlacklistJob = new CronJob( |
||||
|
cronBlacklistUpdate, |
||||
|
this.updateUrlBlacklist.bind(this), |
||||
|
null, |
||||
|
true, |
||||
|
CRON_TIMEZONE, |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
async shutdown ( ) { |
||||
|
this.log.alert('ChatLinksWorker shutting down'); |
||||
|
await super.shutdown(); |
||||
|
} |
||||
|
|
||||
|
async ingestLink (job) { |
||||
|
const { link: linkService, user: userService } = this.services; |
||||
|
this.log.info('received link ingest job', { data: job.data }); |
||||
|
|
||||
|
try { |
||||
|
if (!job.data.submitterId) { |
||||
|
this.log.error('link ingest submitted without submitterId'); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
job.data.submitter = await userService.getUserAccount(job.data.submitterId); |
||||
|
if (!job.data.submitter) { |
||||
|
this.log.error('link submitted with invalid User', { submitterId: job.data.submitterId }); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Is the submitter blocked from sharing links? |
||||
|
*/ |
||||
|
if (!job.data.submitter.permissions.canShareLinks) { |
||||
|
this.log.alert('Submitter is not permitted to share links', { |
||||
|
submitter: { |
||||
|
_id: job.data.submitter._id, |
||||
|
username: job.data.submitter.username, |
||||
|
}, |
||||
|
}); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
this.log.info('fetching link from database'); |
||||
|
job.data.link = await linkService.getById(job.data.linkId); |
||||
|
if (!job.data.link) { |
||||
|
this.log.error('link not found in database', { linkId: job.data.linkId }); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Is the domain or URL already known to be blocked? |
||||
|
*/ |
||||
|
if (job.data.link.flags && job.data.link.flags.isBlocked) { |
||||
|
this.log.alert('aborting ingest of blocked link', { |
||||
|
submitter: { |
||||
|
_id: job.data.submitter._id, |
||||
|
username: job.data.submitter.username, |
||||
|
}, |
||||
|
domain: job.data.link.domain, |
||||
|
url: job.data.link.url, |
||||
|
}); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Is the domain currently blocked? |
||||
|
*/ |
||||
|
const isDomainBlocked = await linkService.isDomainBlocked(job.data.link.domain); |
||||
|
if (isDomainBlocked) { |
||||
|
/* |
||||
|
* Make sure the flag is set on the Link |
||||
|
*/ |
||||
|
await this.Link.updateOne( |
||||
|
{ _id: job.data.link._id }, |
||||
|
{ |
||||
|
$set: { |
||||
|
'flags.isBlocked': true, |
||||
|
}, |
||||
|
}, |
||||
|
); |
||||
|
/* |
||||
|
* Log the rejection |
||||
|
*/ |
||||
|
this.log.alert('prohibiting link from blocked domain', { |
||||
|
submitter: { |
||||
|
_id: job.data.submitter._id, |
||||
|
username: job.data.submitter.username, |
||||
|
}, |
||||
|
domain: job.data.link.domain, |
||||
|
url: job.data.link.url, |
||||
|
}); |
||||
|
|
||||
|
return; // bye!
|
||||
|
} |
||||
|
|
||||
|
this.log.info('fetching link preview', { |
||||
|
domain: job.data.link.domain, |
||||
|
url: job.data.link.url, |
||||
|
}); |
||||
|
|
||||
|
job.data.preview = await linkService.generatePagePreview(job.data.link.url); |
||||
|
if (!job.data.preview) { |
||||
|
throw new Error('failed to load link preview'); |
||||
|
} |
||||
|
|
||||
|
this.log.info('updating link record in Mongo', { |
||||
|
link: job.data.link._id, |
||||
|
preview: job.data.preview, |
||||
|
}); |
||||
|
job.data.link = await this.Link.findOneAndUpdate( |
||||
|
{ _id: job.data.link._id }, |
||||
|
{ |
||||
|
$set: { |
||||
|
lastPreviewFetched: job.data.preview.fetched, |
||||
|
title: job.data.preview.title, |
||||
|
siteName: job.data.preview.siteName, |
||||
|
description: job.data.preview.description, |
||||
|
tags: job.data.preview.tags, |
||||
|
mediaType: job.data.preview.mediaType, |
||||
|
contentType: job.data.preview.contentType, |
||||
|
images: job.data.preview.images, |
||||
|
videos: job.data.preview.videos, |
||||
|
audios: job.data.preview.audios, |
||||
|
favicons: job.data.preview.favicons, |
||||
|
oembed: job.data.preview.oembed, |
||||
|
'flags.havePreview': true, |
||||
|
}, |
||||
|
}, |
||||
|
{ new: true }, |
||||
|
); |
||||
|
job.data.link = await this.Link.populate(job.data.link, linkService.populateLink); |
||||
|
|
||||
|
this.log.info('link ingest complete', { |
||||
|
submitter: { |
||||
|
_id: job.data.submitter._id, |
||||
|
username: job.data.submitter.username, |
||||
|
}, |
||||
|
link: job.data.link, |
||||
|
}); |
||||
|
|
||||
|
if (job.data?.options?.channelId) { |
||||
|
const viewModel = Object.assign({ link: job.data.link }, this.viewModel); |
||||
|
const displayList = linkService.createDisplayList('replace-preview'); |
||||
|
displayList.replaceElement( |
||||
|
`.link-container[data-link-id="${job.data.link._id}"]`, |
||||
|
await linkService.renderPreview(viewModel), |
||||
|
); |
||||
|
this.emitter.to(job.data.options.channelId).emit('chat-control', { displayList }); |
||||
|
} |
||||
|
} catch (error) { |
||||
|
await this.log.error('failed to ingest link', { |
||||
|
domain: job.data.link.domain, |
||||
|
url: job.data.link.url, |
||||
|
error |
||||
|
}); |
||||
|
throw error; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async updateUrlBlacklist ( ) { |
||||
|
try { |
||||
|
/* |
||||
|
* Fetch latest to local file |
||||
|
*/ |
||||
|
this.log.info('fetching updated domain blacklist'); |
||||
|
const response = await fetch(ChatLinksService.BLOCKLIST_URL); |
||||
|
if (!response.ok) { |
||||
|
throw new Error(`unexpected response ${response.statusText}`); |
||||
|
} |
||||
|
|
||||
|
await streamPipeline(Readable.fromWeb(response.body), fs.createWriteStream(this.blacklist.porn)); |
||||
|
|
||||
|
/* |
||||
|
* Read local file line-by-line with filtering and comment removal to insert |
||||
|
* to Redis set of blocked domains |
||||
|
*/ |
||||
|
const fileStream = fs.createReadStream(this.blacklist.porn); |
||||
|
const rl = readline.createInterface({ |
||||
|
input: fileStream, |
||||
|
crlfDelay: Infinity, |
||||
|
}); |
||||
|
for await (let line of rl) { |
||||
|
line = line.trim(); |
||||
|
if (line[0] === '#') { |
||||
|
continue; |
||||
|
} |
||||
|
const tokens = line.split(' '); |
||||
|
if (tokens[0] !== '0.0.0.0' || tokens[1] === '0.0.0.0') { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
const r = await this.redis.sadd(ChatLinksService.DOMAIN_BLACKLIST_KEY, tokens[1]); |
||||
|
if (r > 0) { |
||||
|
this.log.info('added domain to Redis blocklist', { domain: tokens[1] }); |
||||
|
} |
||||
|
} |
||||
|
} catch (error) { |
||||
|
this.log.error('failed to update domain blacklist', { error }); |
||||
|
// fall through
|
||||
|
} finally { |
||||
|
this.log.info('domain block list updated'); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
(async ( ) => { |
||||
|
|
||||
|
try { |
||||
|
const { fileURLToPath } = await import('node:url'); |
||||
|
const __dirname = dirname(fileURLToPath(import.meta.url)); // jshint ignore:line
|
||||
|
|
||||
|
const worker = new ChatLinksService(path.resolve(__dirname, '..', '..')); |
||||
|
await worker.start(); |
||||
|
|
||||
|
} catch (error) { |
||||
|
console.error('failed to start Host Cache worker', { error }); |
||||
|
process.exit(-1); |
||||
|
} |
||||
|
|
||||
|
})(); |
@ -0,0 +1,36 @@ |
|||||
|
|
||||
|
|
||||
|
.link-container { |
||||
|
box-sizing: border-box; |
||||
|
|
||||
|
padding: 5px; |
||||
|
background-color: @link-container-bgcolor; |
||||
|
|
||||
|
// border-top: solid 1px red; |
||||
|
// border-right: solid 1px red; |
||||
|
// border-bottom: solid 1px red; |
||||
|
border-left: solid 4px @link-container-border-color; |
||||
|
|
||||
|
border-radius: 5px; |
||||
|
|
||||
|
.link-preview { |
||||
|
|
||||
|
img.link-thumbnail { |
||||
|
width: 180px; |
||||
|
height: auto; |
||||
|
} |
||||
|
|
||||
|
.link-description { |
||||
|
line-height: 1.15em; |
||||
|
max-height: 4.65em; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
iframe { |
||||
|
aspect-ratio: 16 / 9; |
||||
|
height: auto; |
||||
|
width: 100%; |
||||
|
max-height: 540px; |
||||
|
} |
||||
|
} |
||||
|
} |
After Width: | Height: | Size: 362 B |
@ -956,11 +956,131 @@ |
|||||
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" |
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" |
||||
integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== |
integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== |
||||
|
|
||||
|
"@emnapi/runtime@^1.1.0": |
||||
|
version "1.1.1" |
||||
|
resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.1.1.tgz#697d02276ca6f49bafe6fd01c9df0034818afa98" |
||||
|
integrity sha512-3bfqkzuR1KLx57nZfjr2NLnFOobvyS0aTszaEGCGqmYMVDRaGvgIZbjGSV/MHSSmLgQ/b9JFHQ5xm5WRZYd+XQ== |
||||
|
dependencies: |
||||
|
tslib "^2.4.0" |
||||
|
|
||||
"@fortawesome/fontawesome-free@^6.5.1": |
"@fortawesome/fontawesome-free@^6.5.1": |
||||
version "6.5.1" |
version "6.5.1" |
||||
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.5.1.tgz#55cc8410abf1003b726324661ce5b0d1c10de258" |
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.5.1.tgz#55cc8410abf1003b726324661ce5b0d1c10de258" |
||||
integrity sha512-CNy5vSwN3fsUStPRLX7fUYojyuzoEMSXPl7zSLJ8TgtRfjv24LOnOWKT2zYwaHZCJGkdyRnTmstR0P+Ah503Gw== |
integrity sha512-CNy5vSwN3fsUStPRLX7fUYojyuzoEMSXPl7zSLJ8TgtRfjv24LOnOWKT2zYwaHZCJGkdyRnTmstR0P+Ah503Gw== |
||||
|
|
||||
|
"@img/[email protected]": |
||||
|
version "0.33.3" |
||||
|
resolved "https://registry.yarnpkg.com/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.3.tgz#2bbf676be830c5a9ae7d9294f201c9151535badd" |
||||
|
integrity sha512-FaNiGX1MrOuJ3hxuNzWgsT/mg5OHG/Izh59WW2mk1UwYHUwtfbhk5QNKYZgxf0pLOhx9ctGiGa2OykD71vOnSw== |
||||
|
optionalDependencies: |
||||
|
"@img/sharp-libvips-darwin-arm64" "1.0.2" |
||||
|
|
||||
|
"@img/[email protected]": |
||||
|
version "0.33.3" |
||||
|
resolved "https://registry.yarnpkg.com/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.3.tgz#c59567b141eb676e884066f76091a2673120c3f5" |
||||
|
integrity sha512-2QeSl7QDK9ru//YBT4sQkoq7L0EAJZA3rtV+v9p8xTKl4U1bUqTIaCnoC7Ctx2kCjQgwFXDasOtPTCT8eCTXvw== |
||||
|
optionalDependencies: |
||||
|
"@img/sharp-libvips-darwin-x64" "1.0.2" |
||||
|
|
||||
|
"@img/[email protected]": |
||||
|
version "1.0.2" |
||||
|
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.2.tgz#b69f49fecbe9572378675769b189410721b0fa53" |
||||
|
integrity sha512-tcK/41Rq8IKlSaKRCCAuuY3lDJjQnYIW1UXU1kxcEKrfL8WR7N6+rzNoOxoQRJWTAECuKwgAHnPvqXGN8XfkHA== |
||||
|
|
||||
|
"@img/[email protected]": |
||||
|
version "1.0.2" |
||||
|
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.2.tgz#5665da7360d8e5ed7bee314491c8fe736b6a3c39" |
||||
|
integrity sha512-Ofw+7oaWa0HiiMiKWqqaZbaYV3/UGL2wAPeLuJTx+9cXpCRdvQhCLG0IH8YGwM0yGWGLpsF4Su9vM1o6aer+Fw== |
||||
|
|
||||
|
"@img/[email protected]": |
||||
|
version "1.0.2" |
||||
|
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.2.tgz#8a05e5e9e9b760ff46561e32f19bd5e035fa881c" |
||||
|
integrity sha512-x7kCt3N00ofFmmkkdshwj3vGPCnmiDh7Gwnd4nUwZln2YjqPxV1NlTyZOvoDWdKQVDL911487HOueBvrpflagw== |
||||
|
|
||||
|
"@img/[email protected]": |
||||
|
version "1.0.2" |
||||
|
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.2.tgz#0fd33b9bf3221948ce0ca7a5a725942626577a03" |
||||
|
integrity sha512-iLWCvrKgeFoglQxdEwzu1eQV04o8YeYGFXtfWU26Zr2wWT3q3MTzC+QTCO3ZQfWd3doKHT4Pm2kRmLbupT+sZw== |
||||
|
|
||||
|
"@img/[email protected]": |
||||
|
version "1.0.2" |
||||
|
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.2.tgz#4b89150ec91b256ee2cbb5bb125321bf029a4770" |
||||
|
integrity sha512-cmhQ1J4qVhfmS6szYW7RT+gLJq9dH2i4maq+qyXayUSn9/3iY2ZeWpbAgSpSVbV2E1JUL2Gg7pwnYQ1h8rQIog== |
||||
|
|
||||
|
"@img/[email protected]": |
||||
|
version "1.0.2" |
||||
|
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.2.tgz#947ccc22ca5bc8c8cfe921b39a5fdaebc5e39f3f" |
||||
|
integrity sha512-E441q4Qdb+7yuyiADVi5J+44x8ctlrqn8XgkDTwr4qPJzWkaHwD489iZ4nGDgcuya4iMN3ULV6NwbhRZJ9Z7SQ== |
||||
|
|
||||
|
"@img/[email protected]": |
||||
|
version "1.0.2" |
||||
|
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.2.tgz#821d58ce774f0f8bed065b69913a62f65d512f2f" |
||||
|
integrity sha512-3CAkndNpYUrlDqkCM5qhksfE+qSIREVpyoeHIU6jd48SJZViAmznoQQLAv4hVXF7xyUB9zf+G++e2v1ABjCbEQ== |
||||
|
|
||||
|
"@img/[email protected]": |
||||
|
version "1.0.2" |
||||
|
resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.2.tgz#4309474bd8b728a61af0b3b4fad0c476b5f3ccbe" |
||||
|
integrity sha512-VI94Q6khIHqHWNOh6LLdm9s2Ry4zdjWJwH56WoiJU7NTeDwyApdZZ8c+SADC8OH98KWNQXnE01UdJ9CSfZvwZw== |
||||
|
|
||||
|
"@img/[email protected]": |
||||
|
version "0.33.3" |
||||
|
resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.3.tgz#a1f788ddf49ed63509dd37d4b01e571fe7f189d5" |
||||
|
integrity sha512-Zf+sF1jHZJKA6Gor9hoYG2ljr4wo9cY4twaxgFDvlG0Xz9V7sinsPp8pFd1XtlhTzYo0IhDbl3rK7P6MzHpnYA== |
||||
|
optionalDependencies: |
||||
|
"@img/sharp-libvips-linux-arm64" "1.0.2" |
||||
|
|
||||
|
"@img/[email protected]": |
||||
|
version "0.33.3" |
||||
|
resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.3.tgz#661b0671ed7f740fd06821ce15050ba23f1d0523" |
||||
|
integrity sha512-Q7Ee3fFSC9P7vUSqVEF0zccJsZ8GiiCJYGWDdhEjdlOeS9/jdkyJ6sUSPj+bL8VuOYFSbofrW0t/86ceVhx32w== |
||||
|
optionalDependencies: |
||||
|
"@img/sharp-libvips-linux-arm" "1.0.2" |
||||
|
|
||||
|
"@img/[email protected]": |
||||
|
version "0.33.3" |
||||
|
resolved "https://registry.yarnpkg.com/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.3.tgz#8719341d3931a297df1a956c02ee003736fa8fac" |
||||
|
integrity sha512-vFk441DKRFepjhTEH20oBlFrHcLjPfI8B0pMIxGm3+yilKyYeHEVvrZhYFdqIseSclIqbQ3SnZMwEMWonY5XFA== |
||||
|
optionalDependencies: |
||||
|
"@img/sharp-libvips-linux-s390x" "1.0.2" |
||||
|
|
||||
|
"@img/[email protected]": |
||||
|
version "0.33.3" |
||||
|
resolved "https://registry.yarnpkg.com/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.3.tgz#dbd860b4aa16e7e25727c7e05b411132b58d017d" |
||||
|
integrity sha512-Q4I++herIJxJi+qmbySd072oDPRkCg/SClLEIDh5IL9h1zjhqjv82H0Seupd+q2m0yOfD+/fJnjSoDFtKiHu2g== |
||||
|
optionalDependencies: |
||||
|
"@img/sharp-libvips-linux-x64" "1.0.2" |
||||
|
|
||||
|
"@img/[email protected]": |
||||
|
version "0.33.3" |
||||
|
resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.3.tgz#25b3fbfe9b6fa32d773422d878d8d84f3f6afceb" |
||||
|
integrity sha512-qnDccehRDXadhM9PM5hLvcPRYqyFCBN31kq+ErBSZtZlsAc1U4Z85xf/RXv1qolkdu+ibw64fUDaRdktxTNP9A== |
||||
|
optionalDependencies: |
||||
|
"@img/sharp-libvips-linuxmusl-arm64" "1.0.2" |
||||
|
|
||||
|
"@img/[email protected]": |
||||
|
version "0.33.3" |
||||
|
resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.3.tgz#1e533e44abf2e2d427428ed49294ddba4eb11456" |
||||
|
integrity sha512-Jhchim8kHWIU/GZ+9poHMWRcefeaxFIs9EBqf9KtcC14Ojk6qua7ghKiPs0sbeLbLj/2IGBtDcxHyjCdYWkk2w== |
||||
|
optionalDependencies: |
||||
|
"@img/sharp-libvips-linuxmusl-x64" "1.0.2" |
||||
|
|
||||
|
"@img/[email protected]": |
||||
|
version "0.33.3" |
||||
|
resolved "https://registry.yarnpkg.com/@img/sharp-wasm32/-/sharp-wasm32-0.33.3.tgz#340006047a77df0744db84477768bbca6327b4b4" |
||||
|
integrity sha512-68zivsdJ0koE96stdUfM+gmyaK/NcoSZK5dV5CAjES0FUXS9lchYt8LAB5rTbM7nlWtxaU/2GON0HVN6/ZYJAQ== |
||||
|
dependencies: |
||||
|
"@emnapi/runtime" "^1.1.0" |
||||
|
|
||||
|
"@img/[email protected]": |
||||
|
version "0.33.3" |
||||
|
resolved "https://registry.yarnpkg.com/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.3.tgz#0fdc49ab094ed0151ec8347afac7917aa5fc5145" |
||||
|
integrity sha512-CyimAduT2whQD8ER4Ux7exKrtfoaUiVr7HG0zZvO0XTFn2idUWljjxv58GxNTkFb8/J9Ub9AqITGkJD6ZginxQ== |
||||
|
|
||||
|
"@img/[email protected]": |
||||
|
version "0.33.3" |
||||
|
resolved "https://registry.yarnpkg.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.3.tgz#a94e1028f180666f97fd51e35c4ad092d7704ef0" |
||||
|
integrity sha512-viT4fUIDKnli3IfOephGnolMzhz5VaTvDRkYqtZxOMIoMQ4MrAziO7pT1nVnOt2FAm7qW5aa+CCc13aEY6Le0g== |
||||
|
|
||||
"@ioredis/commands@^1.1.1": |
"@ioredis/commands@^1.1.1": |
||||
version "1.2.0" |
version "1.2.0" |
||||
resolved "https://registry.yarnpkg.com/@ioredis/commands/-/commands-1.2.0.tgz#6d61b3097470af1fdbbe622795b8921d42018e11" |
resolved "https://registry.yarnpkg.com/@ioredis/commands/-/commands-1.2.0.tgz#6d61b3097470af1fdbbe622795b8921d42018e11" |
||||
@ -2024,16 +2144,32 @@ [email protected]: |
|||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" |
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" |
||||
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== |
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== |
||||
|
|
||||
color-name@~1.1.4: |
color-name@^1.0.0, color-name@~1.1.4: |
||||
version "1.1.4" |
version "1.1.4" |
||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" |
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" |
||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== |
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== |
||||
|
|
||||
|
color-string@^1.9.0: |
||||
|
version "1.9.1" |
||||
|
resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" |
||||
|
integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== |
||||
|
dependencies: |
||||
|
color-name "^1.0.0" |
||||
|
simple-swizzle "^0.2.2" |
||||
|
|
||||
color-support@^1.1.3: |
color-support@^1.1.3: |
||||
version "1.1.3" |
version "1.1.3" |
||||
resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" |
resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" |
||||
integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== |
integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== |
||||
|
|
||||
|
color@^4.2.3: |
||||
|
version "4.2.3" |
||||
|
resolved "https://registry.yarnpkg.com/color/-/color-4.2.3.tgz#d781ecb5e57224ee43ea9627560107c0e0c6463a" |
||||
|
integrity sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A== |
||||
|
dependencies: |
||||
|
color-convert "^2.0.1" |
||||
|
color-string "^1.9.0" |
||||
|
|
||||
colorette@^2.0.10, colorette@^2.0.14: |
colorette@^2.0.10, colorette@^2.0.14: |
||||
version "2.0.20" |
version "2.0.20" |
||||
resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" |
resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" |
||||
@ -2387,6 +2523,11 @@ destroy@~1.0.4: |
|||||
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" |
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" |
||||
integrity sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg== |
integrity sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg== |
||||
|
|
||||
|
detect-libc@^2.0.3: |
||||
|
version "2.0.3" |
||||
|
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700" |
||||
|
integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw== |
||||
|
|
||||
dev-ip@^1.0.1: |
dev-ip@^1.0.1: |
||||
version "1.0.1" |
version "1.0.1" |
||||
resolved "https://registry.yarnpkg.com/dev-ip/-/dev-ip-1.0.1.tgz#a76a3ed1855be7a012bb8ac16cb80f3c00dc28f0" |
resolved "https://registry.yarnpkg.com/dev-ip/-/dev-ip-1.0.1.tgz#a76a3ed1855be7a012bb8ac16cb80f3c00dc28f0" |
||||
@ -3355,6 +3496,11 @@ is-array-buffer@^3.0.4: |
|||||
call-bind "^1.0.2" |
call-bind "^1.0.2" |
||||
get-intrinsic "^1.2.1" |
get-intrinsic "^1.2.1" |
||||
|
|
||||
|
is-arrayish@^0.3.1: |
||||
|
version "0.3.2" |
||||
|
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" |
||||
|
integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== |
||||
|
|
||||
is-bigint@^1.0.1: |
is-bigint@^1.0.1: |
||||
version "1.0.4" |
version "1.0.4" |
||||
resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" |
resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" |
||||
@ -5019,7 +5165,7 @@ semver@^6.3.1: |
|||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" |
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" |
||||
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== |
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== |
||||
|
|
||||
semver@^7.5.2, semver@^7.5.3, semver@^7.5.4: |
semver@^7.5.2, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0: |
||||
version "7.6.0" |
version "7.6.0" |
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" |
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" |
||||
integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== |
integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== |
||||
@ -5160,6 +5306,35 @@ shallow-clone@^3.0.0: |
|||||
dependencies: |
dependencies: |
||||
kind-of "^6.0.2" |
kind-of "^6.0.2" |
||||
|
|
||||
|
sharp@^0.33.3: |
||||
|
version "0.33.3" |
||||
|
resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.33.3.tgz#3342fe0aa5ed45a363e6578fa575c7af366216c2" |
||||
|
integrity sha512-vHUeXJU1UvlO/BNwTpT0x/r53WkLUVxrmb5JTgW92fdFCFk0ispLMAeu/jPO2vjkXM1fYUi3K7/qcLF47pwM1A== |
||||
|
dependencies: |
||||
|
color "^4.2.3" |
||||
|
detect-libc "^2.0.3" |
||||
|
semver "^7.6.0" |
||||
|
optionalDependencies: |
||||
|
"@img/sharp-darwin-arm64" "0.33.3" |
||||
|
"@img/sharp-darwin-x64" "0.33.3" |
||||
|
"@img/sharp-libvips-darwin-arm64" "1.0.2" |
||||
|
"@img/sharp-libvips-darwin-x64" "1.0.2" |
||||
|
"@img/sharp-libvips-linux-arm" "1.0.2" |
||||
|
"@img/sharp-libvips-linux-arm64" "1.0.2" |
||||
|
"@img/sharp-libvips-linux-s390x" "1.0.2" |
||||
|
"@img/sharp-libvips-linux-x64" "1.0.2" |
||||
|
"@img/sharp-libvips-linuxmusl-arm64" "1.0.2" |
||||
|
"@img/sharp-libvips-linuxmusl-x64" "1.0.2" |
||||
|
"@img/sharp-linux-arm" "0.33.3" |
||||
|
"@img/sharp-linux-arm64" "0.33.3" |
||||
|
"@img/sharp-linux-s390x" "0.33.3" |
||||
|
"@img/sharp-linux-x64" "0.33.3" |
||||
|
"@img/sharp-linuxmusl-arm64" "0.33.3" |
||||
|
"@img/sharp-linuxmusl-x64" "0.33.3" |
||||
|
"@img/sharp-wasm32" "0.33.3" |
||||
|
"@img/sharp-win32-ia32" "0.33.3" |
||||
|
"@img/sharp-win32-x64" "0.33.3" |
||||
|
|
||||
shebang-command@^2.0.0: |
shebang-command@^2.0.0: |
||||
version "2.0.0" |
version "2.0.0" |
||||
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" |
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" |
||||
@ -5194,6 +5369,13 @@ [email protected]: |
|||||
resolved "https://registry.yarnpkg.com/sift/-/sift-16.0.1.tgz#e9c2ccc72191585008cf3e36fc447b2d2633a053" |
resolved "https://registry.yarnpkg.com/sift/-/sift-16.0.1.tgz#e9c2ccc72191585008cf3e36fc447b2d2633a053" |
||||
integrity sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ== |
integrity sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ== |
||||
|
|
||||
|
simple-swizzle@^0.2.2: |
||||
|
version "0.2.2" |
||||
|
resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" |
||||
|
integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg== |
||||
|
dependencies: |
||||
|
is-arrayish "^0.3.1" |
||||
|
|
||||
simple-update-notifier@^2.0.0: |
simple-update-notifier@^2.0.0: |
||||
version "2.0.0" |
version "2.0.0" |
||||
resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb" |
resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb" |
||||
@ -5647,7 +5829,7 @@ tr46@^5.0.0: |
|||||
dependencies: |
dependencies: |
||||
punycode "^2.3.1" |
punycode "^2.3.1" |
||||
|
|
||||
tslib@^2.0.0, tslib@^2.3.0: |
tslib@^2.0.0, tslib@^2.3.0, tslib@^2.4.0: |
||||
version "2.6.2" |
version "2.6.2" |
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" |
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" |
||||
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== |
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== |
||||
|
Loading…
Reference in new issue