mirror of https://github.com/sylv/micro.git
feat: conversions
This commit is contained in:
parent
1aeaace977
commit
92cef85511
|
@ -26,6 +26,7 @@ An invite-only file sharing service with support for ShareX. You can see a previ
|
|||
- [x] URL Shortening
|
||||
- [x] Mobile support
|
||||
- [x] EXIF metadata removal
|
||||
- [x] Conversions (GIF>WebM, WebP>PNG, etc.)
|
||||
- [x] Purging of old and/or large files (`config.purge`).
|
||||
|
||||
## screenshots
|
||||
|
@ -76,8 +77,6 @@ You should take a full database backup before updating. Pending database migrati
|
|||
- [ ] Password recovery via emails
|
||||
- [ ] SQLite support
|
||||
- [ ] Private email aliases like firefox relay (might be difficult/expensive)
|
||||
- [ ] Export data options (all files, though that could get huge)
|
||||
- [ ] Convert gifs to mp4s on upload to save space
|
||||
|
||||
## discord
|
||||
|
||||
|
|
|
@ -54,9 +54,11 @@ hosts:
|
|||
|
||||
|
||||
|
||||
# # to allow and require users to sign up with an email, specify an SMTP server to send emails from.
|
||||
# # if you do not specify an email, it will not be asked for during signup and users will sign in with their username.
|
||||
# # enabling this on an existing instance will prompt users without an email to add one (https://micro.sylo.digital/i/J1Ilba)
|
||||
|
||||
|
||||
# # To allow and require users to sign up with an email, specify an SMTP server to send emails from.
|
||||
# # If you do not specify an email, it will not be asked for during signup and users will sign in with their username.
|
||||
# # Enabling this on an existing instance will prompt users without an email to add one (https://micro.sylo.digital/i/J1Ilba)
|
||||
# email:
|
||||
# from: 'noreply@example.net'
|
||||
# smtp:
|
||||
|
@ -66,3 +68,23 @@ hosts:
|
|||
# auth:
|
||||
# user: 'username'
|
||||
# pass: 'password'
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Conversions allow you to convert files to other formats on upload.
|
||||
# This is intended for converting inefficient formats like gif to webm (40mb>4mb in testing).
|
||||
# The original copy will be discarded.
|
||||
|
||||
# Video conversions rely on ffmpeg which is a slow and flakey process. If possible,
|
||||
# it's recommended to disable conversions and just don't upload gifs.
|
||||
|
||||
# The recommended options are below, on low power devices like a raspberry pi you should disable conversions entirely.
|
||||
# This is currently not retroactive, but in the future old files may also be converted.
|
||||
conversions:
|
||||
# You cannot convert video/* to image/* and vice versa. How would that even work?
|
||||
# image/gif to video/webm is an exception.
|
||||
- from: image/gif # This could also be a list of types, just a category like "image", or both.
|
||||
to: video/webm
|
||||
minSize: 1MB # Required size before conversion, files uploaded under this limit are ignored
|
|
@ -43,6 +43,7 @@
|
|||
"escape-string-regexp": "^4",
|
||||
"fastify": "^3.29.0",
|
||||
"file-type": "^16",
|
||||
"fluent-ffmpeg": "^2.1.2",
|
||||
"get-stream": "^6.0.1",
|
||||
"graphql": "^16.5.0",
|
||||
"handlebars": "^4.7.7",
|
||||
|
@ -68,6 +69,7 @@
|
|||
"@swc/core": "^1.2.208",
|
||||
"@sylo-digital/scripts": "^1.0.2",
|
||||
"@types/dedent": "^0.7.0",
|
||||
"@types/fluent-ffmpeg": "^2.1.20",
|
||||
"@types/jest": "^28.1.4",
|
||||
"@types/luxon": "^2.3.2",
|
||||
"@types/mime-types": "^2.1.1",
|
||||
|
|
|
@ -3,6 +3,7 @@ import {
|
|||
IsBoolean,
|
||||
IsDefined,
|
||||
IsEmail,
|
||||
IsMimeType,
|
||||
IsNumber,
|
||||
IsOptional,
|
||||
IsString,
|
||||
|
@ -11,12 +12,13 @@ import {
|
|||
NotEquals,
|
||||
ValidateNested,
|
||||
} from 'class-validator';
|
||||
import fileType from 'file-type';
|
||||
import path from 'path';
|
||||
import xbytes from 'xbytes';
|
||||
import { MicroConfigPurge } from './MicroConfigPurge';
|
||||
import { expandMime } from '../helpers/expand-mime';
|
||||
import { MicroConversion } from './MicroConversion';
|
||||
import { MicroEmail } from './MicroEmail';
|
||||
import { MicroHost } from './MicroHost';
|
||||
import { MicroPurge } from './MicroPurge';
|
||||
|
||||
export class MicroConfig {
|
||||
@IsUrl({ require_tld: false, require_protocol: true, protocols: ['postgresql', 'postgres'] })
|
||||
|
@ -38,27 +40,11 @@ export class MicroConfig {
|
|||
@Max(500000)
|
||||
maxPasteLength = 500000;
|
||||
|
||||
@IsString({ each: true })
|
||||
@IsMimeType({ each: true })
|
||||
@IsOptional()
|
||||
@Transform(({ value }) => {
|
||||
if (!value) return value;
|
||||
const clean: string[] = [];
|
||||
for (const type of value) {
|
||||
const stripped = type.replace(/\/\*$/u, '');
|
||||
if (stripped.includes('/')) {
|
||||
if (!fileType.mimeTypes.has(type)) {
|
||||
throw new Error(`Invalid mime type: ${type}`);
|
||||
}
|
||||
|
||||
clean.push(type);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const knownType of fileType.mimeTypes.values()) {
|
||||
if (knownType.startsWith(stripped)) clean.push(knownType);
|
||||
}
|
||||
}
|
||||
|
||||
const clean = expandMime(value);
|
||||
return new Set(clean);
|
||||
})
|
||||
allowTypes?: Set<string>;
|
||||
|
@ -72,14 +58,19 @@ export class MicroConfig {
|
|||
|
||||
@ValidateNested()
|
||||
@IsOptional()
|
||||
@Type(() => MicroConfigPurge)
|
||||
purge?: MicroConfigPurge;
|
||||
@Type(() => MicroPurge)
|
||||
purge?: MicroPurge;
|
||||
|
||||
@ValidateNested()
|
||||
@IsOptional()
|
||||
@Type(() => MicroEmail)
|
||||
email: MicroEmail;
|
||||
|
||||
@ValidateNested({ each: true })
|
||||
@IsOptional()
|
||||
@Type(() => MicroConversion)
|
||||
conversions?: MicroConversion[];
|
||||
|
||||
@ValidateNested({ each: true })
|
||||
@IsDefined()
|
||||
@Type(() => MicroHost)
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
import { Transform } from 'class-transformer';
|
||||
import { IsMimeType, IsNumber, IsOptional, IsString } from 'class-validator';
|
||||
import xbytes from 'xbytes';
|
||||
import { expandMime } from '../helpers/expand-mime';
|
||||
|
||||
export class MicroConversion {
|
||||
@IsString({ each: true })
|
||||
@Transform(({ value }) => {
|
||||
const clean = expandMime(value);
|
||||
return new Set(clean);
|
||||
})
|
||||
from: Set<string>;
|
||||
|
||||
@IsMimeType()
|
||||
to: string;
|
||||
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
@Transform(({ value }) => xbytes.parseSize(value))
|
||||
minSize?: number;
|
||||
}
|
|
@ -3,7 +3,7 @@ import { IsNumber } from 'class-validator';
|
|||
import ms from 'ms';
|
||||
import xbytes from 'xbytes';
|
||||
|
||||
export class MicroConfigPurge {
|
||||
export class MicroPurge {
|
||||
@IsNumber()
|
||||
@Transform(({ value }) => xbytes.parseSize(value))
|
||||
overLimit: number;
|
|
@ -0,0 +1,66 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`should expand mime types 1`] = `
|
||||
Array [
|
||||
"video/mp4",
|
||||
"video/webm",
|
||||
"video/ogg",
|
||||
"video/quicktime",
|
||||
"video/x-ms-wmv",
|
||||
"video/x-msvideo",
|
||||
"video/x-flv",
|
||||
"video/x-matroska",
|
||||
"video/3gpp",
|
||||
"video/3gpp2",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`should expand mime types 2`] = `
|
||||
Array [
|
||||
"image/bmp",
|
||||
"image/gif",
|
||||
"image/jpeg",
|
||||
"image/png",
|
||||
"image/svg+xml",
|
||||
"image/tiff",
|
||||
"image/webp",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`should expand mime types 3`] = `
|
||||
Array [
|
||||
"image/bmp",
|
||||
"image/gif",
|
||||
"image/jpeg",
|
||||
"image/png",
|
||||
"image/svg+xml",
|
||||
"image/tiff",
|
||||
"image/webp",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`should expand mime types 4`] = `
|
||||
Array [
|
||||
"image/bmp",
|
||||
"image/gif",
|
||||
"image/jpeg",
|
||||
"image/png",
|
||||
"image/svg+xml",
|
||||
"image/tiff",
|
||||
"image/webp",
|
||||
"video/mp4",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`should expand mime types 5`] = `
|
||||
Array [
|
||||
"image/bmp",
|
||||
"image/gif",
|
||||
"image/jpeg",
|
||||
"image/png",
|
||||
"image/svg+xml",
|
||||
"image/tiff",
|
||||
"image/webp",
|
||||
"video/mp4",
|
||||
]
|
||||
`;
|
|
@ -0,0 +1,9 @@
|
|||
import { expandMime } from './expand-mime';
|
||||
|
||||
it('should expand mime types', () => {
|
||||
expect(expandMime('video')).toMatchSnapshot();
|
||||
expect(expandMime('image')).toMatchSnapshot();
|
||||
expect(expandMime(['image'])).toMatchSnapshot();
|
||||
expect(expandMime(['image', 'video/mp4'])).toMatchSnapshot();
|
||||
expect(expandMime(['image/*', 'video/mp4'])).toMatchSnapshot();
|
||||
});
|
|
@ -0,0 +1,58 @@
|
|||
const WILDCARD_REGEX = /\/\*$/gu;
|
||||
const MIME_MAP = new Map<string, string[]>([
|
||||
[
|
||||
'video',
|
||||
[
|
||||
'video/mp4',
|
||||
'video/webm',
|
||||
'video/ogg',
|
||||
'video/quicktime',
|
||||
'video/x-ms-wmv',
|
||||
'video/x-msvideo',
|
||||
'video/x-flv',
|
||||
'video/x-matroska',
|
||||
'video/3gpp',
|
||||
'video/3gpp2',
|
||||
],
|
||||
],
|
||||
['image', ['image/bmp', 'image/gif', 'image/jpeg', 'image/png', 'image/svg+xml', 'image/tiff', 'image/webp']],
|
||||
[
|
||||
'audio',
|
||||
[
|
||||
'audio/aac',
|
||||
'audio/aacp',
|
||||
'audio/amr',
|
||||
'audio/amr-wb',
|
||||
'audio/basic',
|
||||
'audio/flac',
|
||||
'audio/midi',
|
||||
'audio/mp3',
|
||||
'audio/mpeg',
|
||||
'audio/mpeg3',
|
||||
'audio/ogg',
|
||||
'audio/opus',
|
||||
'audio/wav',
|
||||
'audio/webm',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
export const expandMime = (input: string | string[]) => {
|
||||
if (!Array.isArray(input)) input = [input];
|
||||
const output: string[] = [];
|
||||
for (const mimeType of input) {
|
||||
const alias = MIME_MAP.get(mimeType.replace(WILDCARD_REGEX, ''));
|
||||
if (alias) {
|
||||
output.push(...alias);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!mimeType.includes('/')) {
|
||||
throw new Error(`Unknown mime category "${mimeType}"`);
|
||||
}
|
||||
|
||||
output.push(mimeType);
|
||||
}
|
||||
|
||||
return output;
|
||||
};
|
|
@ -7,7 +7,10 @@ import { BadRequestException, Injectable, Logger, NotFoundException, PayloadTooL
|
|||
import { Cron, CronExpression } from '@nestjs/schedule';
|
||||
import contentRange from 'content-range';
|
||||
import type { FastifyReply, FastifyRequest } from 'fastify';
|
||||
import ffmpeg from 'fluent-ffmpeg';
|
||||
import { DateTime } from 'luxon';
|
||||
import mime from 'mime-types';
|
||||
import sharp from 'sharp';
|
||||
import { PassThrough } from 'stream';
|
||||
import xbytes from 'xbytes';
|
||||
import type { MicroHost } from '../../classes/MicroHost';
|
||||
|
@ -46,27 +49,86 @@ export class FileService implements OnApplicationBootstrap {
|
|||
): Promise<File> {
|
||||
if (host) this.hostService.checkUserCanUploadTo(host, owner);
|
||||
if (!request.headers['content-length']) throw new BadRequestException('Missing "Content-Length" header.');
|
||||
if (Number(request.headers['content-length']) >= config.uploadLimit) {
|
||||
const contentLength = Number(request.headers['content-length']);
|
||||
if (Number.isNaN(contentLength) || contentLength >= config.uploadLimit) {
|
||||
const size = xbytes(Number(request.headers['content-length']));
|
||||
this.logger.warn(
|
||||
`User ${owner.id} tried uploading a ${size} file, which is over the configured upload size limit.`
|
||||
);
|
||||
|
||||
throw new PayloadTooLargeException();
|
||||
}
|
||||
|
||||
const stream = multipart.file;
|
||||
const typeStream = stream.pipe(new PassThrough());
|
||||
const uploadStream = stream.pipe(new PassThrough());
|
||||
const type = (await getStreamType(multipart.filename, typeStream)) ?? multipart.mimetype;
|
||||
if (config.allowTypes && !config.allowTypes.has(type)) {
|
||||
throw new BadRequestException(`"${type}" is not supported by this server.`);
|
||||
let uploadStream = stream.pipe(new PassThrough());
|
||||
const fileType = (await getStreamType(multipart.filename, typeStream)) ?? multipart.mimetype;
|
||||
if (config.allowTypes && !config.allowTypes.has(fileType)) {
|
||||
throw new BadRequestException(`"${fileType}" is not supported by this server.`);
|
||||
}
|
||||
|
||||
const conversion = config.conversions?.find((conversion) => {
|
||||
if (!conversion.from.has(fileType)) return false;
|
||||
if (conversion.minSize && contentLength < conversion.minSize) return false;
|
||||
if (conversion.to === fileType) return false; // dont convert to the same type
|
||||
return true;
|
||||
});
|
||||
|
||||
if (conversion) {
|
||||
this.logger.debug(`Converting ${fileType} to ${conversion.to}`);
|
||||
const fromGroup = fileType.split('/')[0];
|
||||
const toGroup = conversion.to.split('/')[0];
|
||||
if (fromGroup !== toGroup && fileType !== 'image/gif') {
|
||||
throw new Error(`Cannot convert from ${fromGroup} to ${toGroup}`);
|
||||
}
|
||||
|
||||
switch (toGroup) {
|
||||
case 'video': {
|
||||
let fromFormat = fileType.split('/')[1];
|
||||
if (fromFormat === 'gif') {
|
||||
// ffmpeg doesnt support piping gifs unless "gif_pipe" is the input format.
|
||||
// you have no idea how long it took to discover this.
|
||||
fromFormat = 'gif_pipe';
|
||||
}
|
||||
|
||||
const toFormat = conversion.to.split('/')[1];
|
||||
const transcodeStream = new PassThrough();
|
||||
|
||||
ffmpeg()
|
||||
.input(uploadStream)
|
||||
.fromFormat(fromFormat)
|
||||
.toFormat(toFormat)
|
||||
.writeToStream(transcodeStream, { end: true });
|
||||
|
||||
uploadStream = transcodeStream;
|
||||
break;
|
||||
}
|
||||
case 'image': {
|
||||
const toFormat = conversion.to.split('/')[1];
|
||||
if (!(toFormat in sharp.format)) {
|
||||
throw new Error(`Unknown or unsupported image format ${toFormat}`);
|
||||
}
|
||||
|
||||
// pages: -1 enables support to convert gif to webp without it being a static image
|
||||
const transformer = sharp({ pages: -1 }).toFormat(toFormat as any, {
|
||||
effort: 3,
|
||||
quality: 70,
|
||||
progressive: true,
|
||||
});
|
||||
|
||||
uploadStream = uploadStream.pipe(transformer).pipe(new PassThrough());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new Error(`Unknown or unsupported conversion ${fromGroup} to ${toGroup}`);
|
||||
}
|
||||
}
|
||||
|
||||
const fileId = generateContentId();
|
||||
const { hash, size } = await this.storageService.create(uploadStream);
|
||||
const file = this.fileRepo.create({
|
||||
id: fileId,
|
||||
type: type,
|
||||
type: fileType,
|
||||
name: multipart.filename,
|
||||
owner: owner.id,
|
||||
hostname: host?.normalised.replace('{{username}}', owner.username),
|
||||
|
@ -74,6 +136,17 @@ export class FileService implements OnApplicationBootstrap {
|
|||
size: size,
|
||||
});
|
||||
|
||||
if (conversion) {
|
||||
// swap the file type to the new mime type
|
||||
const originalExtension = mime.extension(file.type);
|
||||
file.type = conversion.to;
|
||||
const conversionExtension = mime.extension(conversion.to);
|
||||
if (file.name && originalExtension && conversionExtension) {
|
||||
// "fix" extensions in the ile name, eg "Test.png" > "Test.webp"
|
||||
file.name = file.name.replace(`.${originalExtension}`, `.${conversionExtension}`);
|
||||
}
|
||||
}
|
||||
|
||||
await this.fileRepo.persistAndFlush(file);
|
||||
return file;
|
||||
}
|
||||
|
|
|
@ -8,5 +8,6 @@ export interface Embeddable {
|
|||
paths: {
|
||||
direct: string;
|
||||
view?: string;
|
||||
thumbnail?: string | null;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import { BASE_EMBED_CLASSES, MAX_HEIGHT } from '../embed';
|
|||
import type { Embeddable } from '../embeddable';
|
||||
|
||||
export const EmbedImage = ({ data }: { data: Embeddable }) => {
|
||||
const containerClasses = classNames('flex items-center justify-center relative', BASE_EMBED_CLASSES);
|
||||
const containerClasses = classNames('flex items-center justify-center relative overflow-hidden', BASE_EMBED_CLASSES);
|
||||
const imageClasses = classNames(`object-contain`, MAX_HEIGHT);
|
||||
|
||||
return (
|
||||
|
|
|
@ -9,6 +9,7 @@ export const EmbedVideo = ({ file }: { file: Embeddable }) => {
|
|||
controls
|
||||
loop
|
||||
playsInline
|
||||
autoPlay
|
||||
className={classes}
|
||||
height={file.height || undefined}
|
||||
width={file.width || undefined}
|
||||
|
|
|
@ -82,11 +82,11 @@ export default function Upload() {
|
|||
}
|
||||
|
||||
location.href = body.urls.view;
|
||||
setFile(null);
|
||||
} catch (error: unknown) {
|
||||
const message = getErrorMessage(error) ?? 'An unknown error occured.';
|
||||
createToast({ error: true, text: message });
|
||||
} finally {
|
||||
setFile(null);
|
||||
setUploading(false);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -33,6 +33,7 @@ importers:
|
|||
'@sylo-digital/scripts': ^1.0.2
|
||||
'@types/bcryptjs': ^2.4.2
|
||||
'@types/dedent': ^0.7.0
|
||||
'@types/fluent-ffmpeg': ^2.1.20
|
||||
'@types/jest': ^28.1.4
|
||||
'@types/luxon': ^2.3.2
|
||||
'@types/mime-types': ^2.1.1
|
||||
|
@ -50,6 +51,7 @@ importers:
|
|||
escape-string-regexp: ^4
|
||||
fastify: ^3.29.0
|
||||
file-type: ^16
|
||||
fluent-ffmpeg: ^2.1.2
|
||||
get-stream: ^6.0.1
|
||||
graphql: ^16.5.0
|
||||
handlebars: ^4.7.7
|
||||
|
@ -103,6 +105,7 @@ importers:
|
|||
escape-string-regexp: 4.0.0
|
||||
fastify: 3.29.0
|
||||
file-type: 16.5.3
|
||||
fluent-ffmpeg: 2.1.2
|
||||
get-stream: 6.0.1
|
||||
graphql: 16.5.0
|
||||
handlebars: 4.7.7
|
||||
|
@ -127,6 +130,7 @@ importers:
|
|||
'@swc/core': 1.2.208
|
||||
'@sylo-digital/scripts': 1.0.2_jest@28.1.2
|
||||
'@types/dedent': 0.7.0
|
||||
'@types/fluent-ffmpeg': 2.1.20
|
||||
'@types/jest': 28.1.4
|
||||
'@types/luxon': 2.3.2
|
||||
'@types/mime-types': 2.1.1
|
||||
|
@ -1596,7 +1600,6 @@ packages:
|
|||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
'@jridgewell/trace-mapping': 0.3.9
|
||||
dev: true
|
||||
|
||||
/@endemolshinegroup/cosmiconfig-typescript-loader/3.0.2_zmjss6mecb4soo3dpdlecld3xa:
|
||||
resolution: {integrity: sha512-QRVtqJuS1mcT56oHpVegkKBlgtWjXw/gHNWO3eL9oyB5Sc7HBoc2OLG/nYpVfT/Jejvo3NUrD0Udk7XgoyDKkA==}
|
||||
|
@ -2352,6 +2355,7 @@ packages:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- ts-node
|
||||
dev: true
|
||||
|
||||
/@jest/core/28.1.2_ts-node@10.8.2:
|
||||
resolution: {integrity: sha512-Xo4E+Sb/nZODMGOPt2G3cMmCBqL4/W2Ijwr7/mrXlq4jdJwcFQ/9KrrJZT2adQRk2otVBXXOz1GRQ4Z5iOgvRQ==}
|
||||
|
@ -2394,7 +2398,6 @@ packages:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- ts-node
|
||||
dev: true
|
||||
|
||||
/@jest/create-cache-key-function/27.5.1:
|
||||
resolution: {integrity: sha512-dmH1yW+makpTSURTy8VzdUwFnfQh1G8R+DxO2Ho2FFmBbKFEVm+3jWdvFhE2VqB/LATCTokkP0dotjyQyw5/AQ==}
|
||||
|
@ -2567,7 +2570,7 @@ packages:
|
|||
dependencies:
|
||||
'@types/istanbul-lib-coverage': 2.0.3
|
||||
'@types/istanbul-reports': 3.0.1
|
||||
'@types/node': 16.11.33
|
||||
'@types/node': 16.11.43
|
||||
'@types/yargs': 15.0.14
|
||||
chalk: 4.1.2
|
||||
dev: false
|
||||
|
@ -2660,7 +2663,6 @@ packages:
|
|||
dependencies:
|
||||
'@jridgewell/resolve-uri': 3.0.8
|
||||
'@jridgewell/sourcemap-codec': 1.4.14
|
||||
dev: true
|
||||
|
||||
/@mikro-orm/cli/5.2.2_4k2cb7nrrwahnwnvazylxfgb44:
|
||||
resolution: {integrity: sha512-IRMcfVFF6edBX2lQsKswMAjw6ILOvwnLT0cMJziknVMuPop/ckaWxlA5r4Uu1BorNtoHf52qB9i3r5YwEe9qAQ==}
|
||||
|
@ -3546,7 +3548,6 @@ packages:
|
|||
cpu: [arm]
|
||||
os: [android]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-android-arm64/1.2.204:
|
||||
|
@ -3563,7 +3564,6 @@ packages:
|
|||
cpu: [arm64]
|
||||
os: [android]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-darwin-arm64/1.2.204:
|
||||
|
@ -3580,7 +3580,6 @@ packages:
|
|||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-darwin-x64/1.2.204:
|
||||
|
@ -3597,7 +3596,6 @@ packages:
|
|||
cpu: [x64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-freebsd-x64/1.2.204:
|
||||
|
@ -3614,7 +3612,6 @@ packages:
|
|||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-linux-arm-gnueabihf/1.2.204:
|
||||
|
@ -3631,7 +3628,6 @@ packages:
|
|||
cpu: [arm]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-linux-arm64-gnu/1.2.204:
|
||||
|
@ -3648,7 +3644,6 @@ packages:
|
|||
cpu: [arm64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-linux-arm64-musl/1.2.204:
|
||||
|
@ -3665,7 +3660,6 @@ packages:
|
|||
cpu: [arm64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-linux-x64-gnu/1.2.204:
|
||||
|
@ -3682,7 +3676,6 @@ packages:
|
|||
cpu: [x64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-linux-x64-musl/1.2.204:
|
||||
|
@ -3699,7 +3692,6 @@ packages:
|
|||
cpu: [x64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-win32-arm64-msvc/1.2.204:
|
||||
|
@ -3716,7 +3708,6 @@ packages:
|
|||
cpu: [arm64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-win32-ia32-msvc/1.2.204:
|
||||
|
@ -3733,7 +3724,6 @@ packages:
|
|||
cpu: [ia32]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-win32-x64-msvc/1.2.204:
|
||||
|
@ -3750,7 +3740,6 @@ packages:
|
|||
cpu: [x64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core/1.2.204:
|
||||
|
@ -3790,7 +3779,6 @@ packages:
|
|||
'@swc/core-win32-arm64-msvc': 1.2.208
|
||||
'@swc/core-win32-ia32-msvc': 1.2.208
|
||||
'@swc/core-win32-x64-msvc': 1.2.208
|
||||
dev: true
|
||||
|
||||
/@swc/helpers/0.4.2:
|
||||
resolution: {integrity: sha512-556Az0VX7WR6UdoTn4htt/l3zPQ7bsQWK+HqdG4swV7beUCxo/BqmvbOpUkTIm/9ih86LIf1qsUnywNL3obGHw==}
|
||||
|
@ -3833,7 +3821,7 @@ packages:
|
|||
eslint: 8.19.0
|
||||
eslint-config-galex: 3.6.5_eslint@8.19.0+jest@28.1.2
|
||||
eslint-plugin-es: 4.1.0_eslint@8.19.0
|
||||
jest: 28.1.2_@types+node@16.11.43
|
||||
jest: 28.1.2_qv5kk3vgcyi3feqo7l5zvvzluy
|
||||
transitivePeerDependencies:
|
||||
- eslint-import-resolver-typescript
|
||||
- eslint-import-resolver-webpack
|
||||
|
@ -3897,24 +3885,20 @@ packages:
|
|||
|
||||
/@tsconfig/node10/1.0.9:
|
||||
resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==}
|
||||
dev: true
|
||||
|
||||
/@tsconfig/node12/1.0.11:
|
||||
resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==}
|
||||
dev: true
|
||||
|
||||
/@tsconfig/node14/1.0.3:
|
||||
resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==}
|
||||
dev: true
|
||||
|
||||
/@tsconfig/node16/1.0.3:
|
||||
resolution: {integrity: sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==}
|
||||
dev: true
|
||||
|
||||
/@types/accepts/1.3.5:
|
||||
resolution: {integrity: sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==}
|
||||
dependencies:
|
||||
'@types/node': 16.11.33
|
||||
'@types/node': 16.11.43
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
|
@ -3957,12 +3941,12 @@ packages:
|
|||
resolution: {integrity: sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==}
|
||||
dependencies:
|
||||
'@types/connect': 3.4.35
|
||||
'@types/node': 16.11.33
|
||||
'@types/node': 16.11.43
|
||||
|
||||
/@types/connect/3.4.35:
|
||||
resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==}
|
||||
dependencies:
|
||||
'@types/node': 16.11.33
|
||||
'@types/node': 16.11.43
|
||||
|
||||
/@types/content-disposition/0.5.5:
|
||||
resolution: {integrity: sha512-v6LCdKfK6BwcqMo+wYW05rLS12S0ZO0Fl4w1h4aaZMD7bqT3gVUns6FvLJKGZHQmYn3SX55JWGpziwJRwVgutA==}
|
||||
|
@ -3975,7 +3959,7 @@ packages:
|
|||
'@types/connect': 3.4.35
|
||||
'@types/express': 4.17.13
|
||||
'@types/keygrip': 1.0.2
|
||||
'@types/node': 16.11.33
|
||||
'@types/node': 16.11.43
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
|
@ -3992,7 +3976,7 @@ packages:
|
|||
/@types/express-serve-static-core/4.17.29:
|
||||
resolution: {integrity: sha512-uMd++6dMKS32EOuw1Uli3e3BPgdLIXmezcfHv7N4c1s3gkhikBplORPpMq3fuWkxncZN1reb16d5n8yhQ80x7Q==}
|
||||
dependencies:
|
||||
'@types/node': 16.11.33
|
||||
'@types/node': 16.11.43
|
||||
'@types/qs': 6.9.7
|
||||
'@types/range-parser': 1.2.4
|
||||
|
||||
|
@ -4013,14 +3997,14 @@ packages:
|
|||
/@types/fs-capacitor/2.0.0:
|
||||
resolution: {integrity: sha512-FKVPOCFbhCvZxpVAMhdBdTfVfXUpsh15wFHgqOKxh9N9vzWZVuWCSijZ5T4U34XYNnuj2oduh6xcs1i+LPI+BQ==}
|
||||
dependencies:
|
||||
'@types/node': 16.11.33
|
||||
'@types/node': 16.11.43
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/@types/graceful-fs/4.1.5:
|
||||
resolution: {integrity: sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==}
|
||||
dependencies:
|
||||
'@types/node': 16.11.33
|
||||
'@types/node': 16.11.43
|
||||
|
||||
/@types/hast/2.3.4:
|
||||
resolution: {integrity: sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==}
|
||||
|
@ -4114,7 +4098,7 @@ packages:
|
|||
'@types/http-errors': 1.8.2
|
||||
'@types/keygrip': 1.0.2
|
||||
'@types/koa-compose': 3.2.5
|
||||
'@types/node': 16.11.33
|
||||
'@types/node': 16.11.43
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
|
@ -4154,7 +4138,7 @@ packages:
|
|||
/@types/node-fetch/2.5.10:
|
||||
resolution: {integrity: sha512-IpkX0AasN44hgEad0gEF/V6EgR5n69VEqPEgnmoM8GsIGro3PowbWs4tR6IhxUTyPLpOn+fiGG6nrQhcmoCuIQ==}
|
||||
dependencies:
|
||||
'@types/node': 16.11.33
|
||||
'@types/node': 16.11.43
|
||||
form-data: 3.0.1
|
||||
dev: false
|
||||
optional: true
|
||||
|
@ -4252,7 +4236,7 @@ packages:
|
|||
resolution: {integrity: sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==}
|
||||
dependencies:
|
||||
'@types/mime': 1.3.2
|
||||
'@types/node': 16.11.33
|
||||
'@types/node': 16.11.43
|
||||
|
||||
/@types/sharp/0.30.4:
|
||||
resolution: {integrity: sha512-6oJEzKt7wZeS7e+6x9QFEOWGs0T/6of00+0onZGN1zSmcSjcTDZKgIGZ6YWJnHowpaKUCFBPH52mYljWqU32Eg==}
|
||||
|
@ -4270,7 +4254,7 @@ packages:
|
|||
/@types/ws/7.4.7:
|
||||
resolution: {integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==}
|
||||
dependencies:
|
||||
'@types/node': 16.11.33
|
||||
'@types/node': 16.11.43
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
|
@ -4555,7 +4539,6 @@ packages:
|
|||
/acorn-walk/8.2.0:
|
||||
resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
dev: true
|
||||
|
||||
/acorn/7.4.1:
|
||||
resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==}
|
||||
|
@ -5019,7 +5002,6 @@ packages:
|
|||
|
||||
/arg/4.1.3:
|
||||
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
|
||||
dev: true
|
||||
|
||||
/arg/5.0.2:
|
||||
resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
|
||||
|
@ -6077,7 +6059,6 @@ packages:
|
|||
|
||||
/create-require/1.1.1:
|
||||
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
|
||||
dev: true
|
||||
|
||||
/cron/1.8.2:
|
||||
resolution: {integrity: sha512-Gk2c4y6xKEO8FSAUTklqtfSr7oTq0CiPQeLBG5Fl0qoXpZyMcj1SG59YL+hqq04bu6/IuEA7lMkYDAplQNKkyg==}
|
||||
|
@ -6379,7 +6360,6 @@ packages:
|
|||
/diff/4.0.2:
|
||||
resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
|
||||
engines: {node: '>=0.3.1'}
|
||||
dev: true
|
||||
|
||||
/diff/5.1.0:
|
||||
resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==}
|
||||
|
@ -7020,7 +7000,7 @@ packages:
|
|||
'@typescript-eslint/eslint-plugin': 5.12.0_byxz3mnn3ms3gbtbci7fo4cm6q
|
||||
'@typescript-eslint/utils': 5.29.0_m32fwjepeyylyephxtubzxm4ui
|
||||
eslint: 8.19.0
|
||||
jest: 28.1.2_@types+node@16.11.43
|
||||
jest: 28.1.2_qv5kk3vgcyi3feqo7l5zvvzluy
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- typescript
|
||||
|
@ -8990,6 +8970,7 @@ packages:
|
|||
- '@types/node'
|
||||
- supports-color
|
||||
- ts-node
|
||||
dev: true
|
||||
|
||||
/jest-cli/28.1.2_qv5kk3vgcyi3feqo7l5zvvzluy:
|
||||
resolution: {integrity: sha512-l6eoi5Do/IJUXAFL9qRmDiFpBeEJAnjJb1dcd9i/VWfVWbp3mJhuH50dNtX67Ali4Ecvt4eBkWb4hXhPHkAZTw==}
|
||||
|
@ -9017,7 +8998,6 @@ packages:
|
|||
- '@types/node'
|
||||
- supports-color
|
||||
- ts-node
|
||||
dev: true
|
||||
|
||||
/jest-config/28.1.2_4maxphccb5fztufhofwcslq6fm:
|
||||
resolution: {integrity: sha512-g6EfeRqddVbjPVBVY4JWpUY4IvQoFRIZcv4V36QkqzE0IGhEC/VkugFeBMAeUE7PRgC8KJF0yvJNDeQRbamEVA==}
|
||||
|
@ -9057,7 +9037,6 @@ packages:
|
|||
ts-node: 10.8.2_pbcylixk5f7tclmtradmulh4qa
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/jest-config/28.1.2_@types+node@16.11.43:
|
||||
resolution: {integrity: sha512-g6EfeRqddVbjPVBVY4JWpUY4IvQoFRIZcv4V36QkqzE0IGhEC/VkugFeBMAeUE7PRgC8KJF0yvJNDeQRbamEVA==}
|
||||
|
@ -9096,6 +9075,7 @@ packages:
|
|||
strip-json-comments: 3.1.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/jest-config/28.1.2_qv5kk3vgcyi3feqo7l5zvvzluy:
|
||||
resolution: {integrity: sha512-g6EfeRqddVbjPVBVY4JWpUY4IvQoFRIZcv4V36QkqzE0IGhEC/VkugFeBMAeUE7PRgC8KJF0yvJNDeQRbamEVA==}
|
||||
|
@ -9135,7 +9115,6 @@ packages:
|
|||
ts-node: 10.8.2_pbcylixk5f7tclmtradmulh4qa
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/jest-diff/28.1.1:
|
||||
resolution: {integrity: sha512-/MUUxeR2fHbqHoMMiffe/Afm+U8U4olFRJ0hiVG2lZatPJcnGxx292ustVu7bULhjV65IYMxRdploAKLbcrsyg==}
|
||||
|
@ -9183,7 +9162,7 @@ packages:
|
|||
dependencies:
|
||||
'@jest/types': 26.6.2
|
||||
'@types/graceful-fs': 4.1.5
|
||||
'@types/node': 16.11.33
|
||||
'@types/node': 16.11.43
|
||||
anymatch: 3.1.2
|
||||
fb-watchman: 2.0.1
|
||||
graceful-fs: 4.2.10
|
||||
|
@ -9359,7 +9338,7 @@ packages:
|
|||
resolution: {integrity: sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g==}
|
||||
engines: {node: '>= 10.14.2'}
|
||||
dependencies:
|
||||
'@types/node': 16.11.33
|
||||
'@types/node': 16.11.43
|
||||
graceful-fs: 4.2.10
|
||||
dev: false
|
||||
|
||||
|
@ -9398,7 +9377,7 @@ packages:
|
|||
engines: {node: '>= 10.14.2'}
|
||||
dependencies:
|
||||
'@jest/types': 26.6.2
|
||||
'@types/node': 16.11.33
|
||||
'@types/node': 16.11.43
|
||||
chalk: 4.1.2
|
||||
graceful-fs: 4.2.10
|
||||
is-ci: 2.0.0
|
||||
|
@ -9444,7 +9423,7 @@ packages:
|
|||
resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==}
|
||||
engines: {node: '>= 10.13.0'}
|
||||
dependencies:
|
||||
'@types/node': 16.11.33
|
||||
'@types/node': 16.11.43
|
||||
merge-stream: 2.0.0
|
||||
supports-color: 7.2.0
|
||||
dev: false
|
||||
|
@ -9475,6 +9454,7 @@ packages:
|
|||
- '@types/node'
|
||||
- supports-color
|
||||
- ts-node
|
||||
dev: true
|
||||
|
||||
/jest/28.1.2_qv5kk3vgcyi3feqo7l5zvvzluy:
|
||||
resolution: {integrity: sha512-Tuf05DwLeCh2cfWCQbcz9UxldoDyiR1E9Igaei5khjonKncYdc6LDfynKCEWozK0oLE3GD+xKAo2u8x/0s6GOg==}
|
||||
|
@ -9494,7 +9474,6 @@ packages:
|
|||
- '@types/node'
|
||||
- supports-color
|
||||
- ts-node
|
||||
dev: true
|
||||
|
||||
/joycon/3.1.1:
|
||||
resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
|
||||
|
@ -10024,7 +10003,6 @@ packages:
|
|||
|
||||
/make-error/1.3.6:
|
||||
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
|
||||
dev: true
|
||||
|
||||
/make-fetch-happen/8.0.14:
|
||||
resolution: {integrity: sha512-EsS89h6l4vbfJEtBZnENTOFk8mCRpY5ru36Xe5bcX1KYIli2mkSHqoFsp5O1wMDvTJJzxe/4THpCTtygjeeGWQ==}
|
||||
|
@ -13126,7 +13104,6 @@ packages:
|
|||
typescript: 4.7.4
|
||||
v8-compile-cache-lib: 3.0.1
|
||||
yn: 3.1.1
|
||||
dev: true
|
||||
|
||||
/ts-node/9.1.1_typescript@4.7.4:
|
||||
resolution: {integrity: sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==}
|
||||
|
@ -13443,7 +13420,6 @@ packages:
|
|||
resolution: {integrity: sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==}
|
||||
engines: {node: '>=4.2.0'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/ua-parser-js/0.7.31:
|
||||
resolution: {integrity: sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==}
|
||||
|
@ -13676,7 +13652,6 @@ packages:
|
|||
|
||||
/v8-compile-cache-lib/3.0.1:
|
||||
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
|
||||
dev: true
|
||||
|
||||
/v8-compile-cache/2.3.0:
|
||||
resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==}
|
||||
|
@ -14024,7 +13999,6 @@ packages:
|
|||
/yn/3.1.1:
|
||||
resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==}
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/yocto-queue/0.1.0:
|
||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||
|
|
Loading…
Reference in New Issue