kopia lustrzana https://github.com/mifi/lossless-cut
upgrade execa and node types
rodzic
2fb78214fc
commit
ca8eccf899
|
@ -45,6 +45,7 @@
|
|||
"@radix-ui/react-checkbox": "^1.0.4",
|
||||
"@radix-ui/react-switch": "^1.0.1",
|
||||
"@tsconfig/node18": "^18.2.2",
|
||||
"@tsconfig/node20": "^20.1.4",
|
||||
"@tsconfig/strictest": "^2.0.2",
|
||||
"@tsconfig/vite-react": "^3.0.0",
|
||||
"@types/color": "^3.0.6",
|
||||
|
@ -58,7 +59,7 @@
|
|||
"@types/mime-types": "^2.1.4",
|
||||
"@types/morgan": "^1.9.9",
|
||||
"@types/mousetrap": "^1.6.15",
|
||||
"@types/node": "18",
|
||||
"@types/node": "20",
|
||||
"@types/react": "^18.2.66",
|
||||
"@types/react-dom": "^18.2.22",
|
||||
"@types/sortablejs": "^1.15.0",
|
||||
|
@ -122,7 +123,7 @@
|
|||
"tiny-invariant": "^1.3.3",
|
||||
"tsx": "^4.7.1",
|
||||
"type-fest": "^4.23.0",
|
||||
"typescript": "^5.5.4",
|
||||
"typescript": "^5.7.2",
|
||||
"use-debounce": "^5.1.0",
|
||||
"use-trace-update": "^1.3.0",
|
||||
"vite": "^5.3.6",
|
||||
|
@ -134,7 +135,7 @@
|
|||
"cue-parser": "^0.3.0",
|
||||
"electron-store": "5.1.1",
|
||||
"electron-unhandled": "^5.0.0",
|
||||
"execa": "^8.0.1",
|
||||
"execa": "^9.5.1",
|
||||
"express": "^4.20.0",
|
||||
"express-async-handler": "^1.2.0",
|
||||
"file-type": "patch:file-type@npm%3A19.4.1#~/.yarn/patches/file-type-npm-19.4.1-d18086444c.patch",
|
||||
|
|
|
@ -5,7 +5,7 @@ import { DateTime } from 'luxon';
|
|||
const xmlUrl = new URL('../no.mifi.losslesscut.appdata.xml', import.meta.url);
|
||||
const xmlData = await readFile(xmlUrl);
|
||||
|
||||
const packageJson = JSON.parse(await readFile(new URL('../package.json', import.meta.url)) as unknown as string);
|
||||
const packageJson = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf8'));
|
||||
|
||||
const parser = new XMLParser({ alwaysCreateTextNode: true, ignoreAttributes: false, ignoreDeclaration: false });
|
||||
const xml = parser.parse(xmlData);
|
||||
|
|
|
@ -18,7 +18,7 @@ const bundleId = args[4];
|
|||
// seems to be the same
|
||||
const ascPublicId = apiIssuer;
|
||||
|
||||
const packageJson = JSON.parse(await readFile(new URL('../package.json', import.meta.url)) as unknown as string);
|
||||
const packageJson = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf8'));
|
||||
|
||||
console.log('Using version', packageJson.version);
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import assert from 'node:assert';
|
||||
import { ExecaError } from 'execa';
|
||||
|
||||
import logger from './logger.js';
|
||||
import { createMediaSourceProcess, readOneJpegFrame as readOneJpegFrameRaw } from './ffmpeg.js';
|
||||
|
@ -64,16 +65,12 @@ export function createMediaSourceStream({ path, videoStreamIndex, audioStreamInd
|
|||
try {
|
||||
await process;
|
||||
} catch (err) {
|
||||
if (err instanceof Error && err.name === 'AbortError') {
|
||||
if (err instanceof ExecaError && err.isTerminated) {
|
||||
return;
|
||||
}
|
||||
|
||||
// @ts-expect-error todo
|
||||
if (!(err.killed)) {
|
||||
// @ts-expect-error todo
|
||||
logger.warn(err.message);
|
||||
logger.warn(stderr.toString('utf8'));
|
||||
}
|
||||
logger.warn((err as Error).message);
|
||||
logger.warn(stderr.toString('utf8'));
|
||||
}
|
||||
})();
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { join } from 'node:path';
|
||||
import readline from 'node:readline';
|
||||
import stringToStream from 'string-to-stream';
|
||||
import { BufferEncodingOption, execa, ExecaChildProcess, Options as ExecaOptions } from 'execa';
|
||||
import { execa, Options as ExecaOptions, ResultPromise } from 'execa';
|
||||
import assert from 'node:assert';
|
||||
import { Readable } from 'node:stream';
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
|
@ -14,7 +14,7 @@ import logger from './logger.js';
|
|||
import { parseFfmpegProgressLine } from './progress.js';
|
||||
|
||||
|
||||
const runningFfmpegs = new Set<ExecaChildProcess<Buffer>>();
|
||||
const runningFfmpegs = new Set<ResultPromise<Omit<ExecaOptions, 'encoding'> & { encoding: 'buffer' }>>();
|
||||
// setInterval(() => console.log(runningFfmpegs.size), 1000);
|
||||
|
||||
let customFfPath: string | undefined;
|
||||
|
@ -59,7 +59,7 @@ export const getFfmpegPath = () => getFfPath('ffmpeg');
|
|||
export function abortFfmpegs() {
|
||||
logger.info('Aborting', runningFfmpegs.size, 'ffmpeg process(es)');
|
||||
runningFfmpegs.forEach((process) => {
|
||||
process.kill('SIGTERM', { forceKillAfterTimeout: 10000 });
|
||||
process.kill();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -88,20 +88,27 @@ function handleProgress(
|
|||
});
|
||||
}
|
||||
|
||||
function getExecaOptions({ env, ...customExecaOptions }: Omit<ExecaOptions<BufferEncodingOption>, 'buffer'> = {}) {
|
||||
const execaOptions: Omit<ExecaOptions<BufferEncodingOption>, 'buffer'> = { ...customExecaOptions, encoding: 'buffer' };
|
||||
// https://github.com/mifi/lossless-cut/issues/1143#issuecomment-1500883489
|
||||
if (isLinux && !isDev && !customFfPath) {
|
||||
return {
|
||||
...execaOptions,
|
||||
env: { ...env, LD_LIBRARY_PATH: process.resourcesPath },
|
||||
};
|
||||
}
|
||||
function getExecaOptions({ env, cancelSignal, ...rest }: ExecaOptions = {}) {
|
||||
// This is a ugly hack to please execa which expects cancelSignal to be a prototype of AbortSignal
|
||||
// however this gets lost during @electron/remote passing
|
||||
// https://github.com/sindresorhus/execa/blob/c8cff27a47b6e6f1cfbfec2bf7fa9dcd08cefed1/lib/terminate/cancel.js#L5
|
||||
if (cancelSignal != null) Object.setPrototypeOf(cancelSignal, new AbortController().signal);
|
||||
|
||||
const execaOptions: Pick<ExecaOptions, 'env'> & { encoding: 'buffer' } = {
|
||||
...(cancelSignal != null && { cancelSignal }),
|
||||
...rest,
|
||||
encoding: 'buffer' as const,
|
||||
env: {
|
||||
...env,
|
||||
// https://github.com/mifi/lossless-cut/issues/1143#issuecomment-1500883489
|
||||
...(isLinux && !isDev && !customFfPath && { LD_LIBRARY_PATH: process.resourcesPath }),
|
||||
},
|
||||
};
|
||||
return execaOptions;
|
||||
}
|
||||
|
||||
// todo collect warnings from ffmpeg output and show them after export? example: https://github.com/mifi/lossless-cut/issues/1469
|
||||
function runFfmpegProcess(args: readonly string[], customExecaOptions?: Omit<ExecaOptions<BufferEncodingOption>, 'encoding'>, additionalOptions?: { logCli?: boolean }) {
|
||||
function runFfmpegProcess(args: readonly string[], customExecaOptions?: ExecaOptions, additionalOptions?: { logCli?: boolean }) {
|
||||
const ffmpegPath = getFfmpegPath();
|
||||
const { logCli = true } = additionalOptions ?? {};
|
||||
if (logCli) logger.info(getFfCommandLine('ffmpeg', args));
|
||||
|
@ -187,8 +194,8 @@ export async function renderWaveformPng({ filePath, start, duration, color, stre
|
|||
|
||||
logger.info(`${getFfCommandLine('ffmpeg1', args1)} | \n${getFfCommandLine('ffmpeg2', args2)}`);
|
||||
|
||||
let ps1: ExecaChildProcess<Buffer> | undefined;
|
||||
let ps2: ExecaChildProcess<Buffer> | undefined;
|
||||
let ps1: ResultPromise<{ encoding: 'buffer' }> | undefined;
|
||||
let ps2: ResultPromise<{ encoding: 'buffer' }> | undefined;
|
||||
try {
|
||||
ps1 = runFfmpegProcess(args1, { buffer: false }, { logCli: false });
|
||||
ps2 = runFfmpegProcess(args2, undefined, { logCli: false });
|
||||
|
@ -210,7 +217,7 @@ export async function renderWaveformPng({ filePath, start, duration, color, stre
|
|||
}
|
||||
|
||||
return {
|
||||
buffer: stdout,
|
||||
buffer: Buffer.from(stdout),
|
||||
};
|
||||
} catch (err) {
|
||||
if (ps1) ps1.kill();
|
||||
|
@ -465,7 +472,7 @@ async function readFormatData(filePath: string) {
|
|||
const { stdout } = await runFfprobe([
|
||||
'-of', 'json', '-show_format', '-i', filePath, '-hide_banner',
|
||||
]);
|
||||
return JSON.parse(stdout as unknown as string).format;
|
||||
return JSON.parse(new TextDecoder().decode(stdout)).format;
|
||||
}
|
||||
|
||||
export async function getDuration(filePath: string) {
|
||||
|
@ -557,7 +564,7 @@ export function createMediaSourceProcess({ path, videoStreamIndex, audioStreamIn
|
|||
|
||||
if (enableLog) logger.info(getFfCommandLine('ffmpeg', args));
|
||||
|
||||
return execa(getFfmpegPath(), args, { encoding: null, buffer: false, stderr: enableLog ? 'inherit' : 'pipe' });
|
||||
return execa(getFfmpegPath(), args, { encoding: 'buffer', buffer: false, stderr: enableLog ? 'inherit' : 'pipe' });
|
||||
}
|
||||
|
||||
export async function downloadMediaUrl(url: string, outPath: string) {
|
||||
|
|
|
@ -230,7 +230,7 @@ async function startPlayback({ path, video, videoStreamIndex, audioStreamIndex,
|
|||
processChunk();
|
||||
}
|
||||
|
||||
function drawJpegFrame(canvas: HTMLCanvasElement | null, jpegImage: Buffer) {
|
||||
function drawJpegFrame(canvas: HTMLCanvasElement | null, jpegImage: Uint8Array) {
|
||||
if (!canvas) return;
|
||||
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
@ -244,7 +244,8 @@ function drawJpegFrame(canvas: HTMLCanvasElement | null, jpegImage: Buffer) {
|
|||
img.onload = () => ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
|
||||
// eslint-disable-next-line unicorn/prefer-add-event-listener
|
||||
img.onerror = (error) => console.error('Canvas JPEG image error', error);
|
||||
img.src = `data:image/jpeg;base64,${jpegImage.toString('base64')}`;
|
||||
// todo use Blob?
|
||||
img.src = `data:image/jpeg;base64,${Buffer.from(jpegImage).toString('base64')}`;
|
||||
}
|
||||
|
||||
async function createPauseImage({ path, seekTo, videoStreamIndex, canvas, signal }: {
|
||||
|
|
|
@ -84,7 +84,7 @@ export async function saveLlcProject({ savePath, filePath, cutSegments }) {
|
|||
}
|
||||
|
||||
export async function loadLlcProject(path: string) {
|
||||
const parsed = JSON5.parse(await readFile(path) as unknown as string) as unknown;
|
||||
const parsed = JSON5.parse(await readFile(path, 'utf8')) as unknown;
|
||||
if (parsed == null || typeof parsed !== 'object') throw new Error('Invalid LLC file');
|
||||
let mediaFileName: string | undefined;
|
||||
if ('mediaFileName' in parsed && typeof parsed.mediaFileName === 'string') {
|
||||
|
|
|
@ -27,23 +27,23 @@ export class RefuseOverwriteError extends Error {
|
|||
}
|
||||
}
|
||||
|
||||
export function fixRemoteBuffer(buffer: Buffer) {
|
||||
export function safeCreateBlob(array: Uint8Array, options?: BlobPropertyBag) {
|
||||
// if we don't do this when creating a Blob, we get:
|
||||
// "Failed to construct 'Blob': The provided ArrayBufferView value must not be resizable."
|
||||
// maybe when moving away from @electron/remote, it's not needed anymore?
|
||||
const buffer2 = Buffer.allocUnsafe(buffer.length);
|
||||
buffer.copy(buffer2);
|
||||
return buffer2;
|
||||
// https://stackoverflow.com/a/25255750/6519037
|
||||
const cloned = new Uint8Array(array);
|
||||
return new Blob([cloned], options);
|
||||
}
|
||||
|
||||
export function logStdoutStderr({ stdout, stderr }: { stdout: Buffer, stderr: Buffer }) {
|
||||
export function logStdoutStderr({ stdout, stderr }: { stdout: Uint8Array, stderr: Uint8Array }) {
|
||||
if (stdout.length > 0) {
|
||||
console.log('%cSTDOUT:', 'color: green; font-weight: bold');
|
||||
console.log(stdout.toString('utf8'));
|
||||
console.log(new TextDecoder().decode(stdout));
|
||||
}
|
||||
if (stderr.length > 0) {
|
||||
console.log('%cSTDERR:', 'color: blue; font-weight: bold');
|
||||
console.log(stderr.toString('utf8'));
|
||||
console.log(new TextDecoder().decode(stderr));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ export async function readFrames({ filePath, from, to, streamIndex }: {
|
|||
}) {
|
||||
const intervalsArgs = from != null && to != null ? ['-read_intervals', `${from}%${to}`] : [];
|
||||
const { stdout } = await runFfprobe(['-v', 'error', ...intervalsArgs, '-show_packets', '-select_streams', String(streamIndex), '-show_entries', 'packet=pts_time,flags', '-of', 'json', filePath], { logCli: false });
|
||||
const packetsFiltered: Frame[] = (JSON.parse(stdout as unknown as string).packets as { flags: string, pts_time: string }[])
|
||||
const packetsFiltered: Frame[] = (JSON.parse(new TextDecoder().decode(stdout)).packets as { flags: string, pts_time: string }[])
|
||||
.map((p) => ({
|
||||
keyframe: p.flags[0] === 'K',
|
||||
time: parseFloat(p.pts_time),
|
||||
|
@ -356,7 +356,7 @@ export async function readFileMeta(filePath: string) {
|
|||
let parsedJson: FFprobeProbeResult;
|
||||
try {
|
||||
// https://github.com/mifi/lossless-cut/issues/1342
|
||||
parsedJson = JSON.parse(stdout.toString('utf8'));
|
||||
parsedJson = JSON.parse(new TextDecoder().decode(stdout));
|
||||
} catch {
|
||||
console.log('ffprobe stdout', stdout);
|
||||
throw new Error('ffprobe returned malformed data');
|
||||
|
@ -383,9 +383,9 @@ async function renderThumbnail(filePath: string, timestamp: number, signal: Abor
|
|||
'-',
|
||||
];
|
||||
|
||||
const { stdout } = await runFfmpeg(args, { signal }, { logCli: false });
|
||||
const { stdout } = await runFfmpeg(args, { cancelSignal: signal }, { logCli: false });
|
||||
|
||||
const blob = new Blob([fixRemoteBuffer(stdout)], { type: 'image/jpeg' });
|
||||
const blob = safeCreateBlob(stdout, { type: 'image/jpeg' });
|
||||
return URL.createObjectURL(blob);
|
||||
}
|
||||
|
||||
|
@ -399,7 +399,7 @@ export async function extractSubtitleTrack(filePath: string, streamId: number) {
|
|||
];
|
||||
|
||||
const { stdout } = await runFfmpeg(args);
|
||||
return stdout.toString('utf8');
|
||||
return new TextDecoder().decode(stdout);
|
||||
}
|
||||
|
||||
export async function extractSubtitleTrackToSegments(filePath: string, streamId: number) {
|
||||
|
@ -423,7 +423,7 @@ export async function extractSubtitleTrackVtt(filePath: string, streamId: number
|
|||
|
||||
const { stdout } = await runFfmpeg(args);
|
||||
|
||||
const blob = new Blob([fixRemoteBuffer(stdout)], { type: 'text/vtt' });
|
||||
const blob = safeCreateBlob(stdout, { type: 'text/vtt' });
|
||||
return URL.createObjectURL(blob);
|
||||
}
|
||||
|
||||
|
|
|
@ -762,7 +762,7 @@ function useFfmpegOperations({ filePath, treatInputFileModifiedTimeAsStart, trea
|
|||
appendFfmpegCommandLog(ffmpegArgs);
|
||||
const { stdout } = await runFfmpegWithProgress({ ffmpegArgs, duration, onProgress });
|
||||
|
||||
console.log(stdout.toString('utf8'));
|
||||
console.log(new TextDecoder().decode(stdout));
|
||||
|
||||
invariant(outPath != null);
|
||||
await transferTimestamps({ inPath: filePathArg, outPath, treatOutputFileModifiedTimeAsStart });
|
||||
|
@ -901,7 +901,7 @@ function useFfmpegOperations({ filePath, treatInputFileModifiedTimeAsStart, trea
|
|||
|
||||
appendFfmpegCommandLog(ffmpegArgs);
|
||||
const { stdout } = await runFfmpeg(ffmpegArgs);
|
||||
console.log(stdout.toString('utf8'));
|
||||
console.log(new TextDecoder().decode(stdout));
|
||||
|
||||
return outPaths;
|
||||
}, [appendFfmpegCommandLog, enableOverwriteOutput, filePath]);
|
||||
|
@ -939,7 +939,7 @@ function useFfmpegOperations({ filePath, treatInputFileModifiedTimeAsStart, trea
|
|||
try {
|
||||
appendFfmpegCommandLog(ffmpegArgs);
|
||||
const { stdout } = await runFfmpeg(ffmpegArgs);
|
||||
console.log(stdout.toString('utf8'));
|
||||
console.log(new TextDecoder().decode(stdout));
|
||||
} catch (err) {
|
||||
// Unfortunately ffmpeg will exit with code 1 even though it's a success
|
||||
// Note: This is kind of hacky:
|
||||
|
|
|
@ -6,6 +6,7 @@ import sortBy from 'lodash/sortBy';
|
|||
import { renderThumbnails as ffmpegRenderThumbnails } from '../ffmpeg';
|
||||
import { Thumbnail } from '../types';
|
||||
import { isDurationValid } from '../segments';
|
||||
import { isExecaError } from '../util';
|
||||
|
||||
|
||||
export default ({ filePath, zoomedDuration, zoomWindowStartTime, showThumbnails }: {
|
||||
|
@ -39,7 +40,7 @@ export default ({ filePath, zoomedDuration, zoomWindowStartTime, showThumbnails
|
|||
|
||||
await ffmpegRenderThumbnails({ signal: abortController.signal, filePath: debounced.filePath, from: debounced.zoomWindowStartTime, duration: debounced.zoomedDuration, onThumbnail: addThumbnail });
|
||||
} catch (err) {
|
||||
if ((err as Error).name !== 'AbortError') {
|
||||
if ((err as Error).name !== 'AbortError' && !(isExecaError(err) && err.isCanceled)) {
|
||||
console.error('Failed to render thumbnails', err);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import sortBy from 'lodash/sortBy';
|
|||
import { useThrottle } from '@uidotdev/usehooks';
|
||||
import { waveformColorDark, waveformColorLight } from '../colors';
|
||||
|
||||
import { fixRemoteBuffer, renderWaveformPng } from '../ffmpeg';
|
||||
import { renderWaveformPng, safeCreateBlob } from '../ffmpeg';
|
||||
import { RenderableWaveform } from '../types';
|
||||
import { FFprobeStream } from '../../../../ffprobe';
|
||||
|
||||
|
@ -75,7 +75,7 @@ export default ({ darkMode, filePath, relevantTime, duration, waveformEnabled, a
|
|||
|
||||
return {
|
||||
...w,
|
||||
url: URL.createObjectURL(new Blob([fixRemoteBuffer(buffer)], { type: 'image/png' })),
|
||||
url: URL.createObjectURL(safeCreateBlob(buffer, { type: 'image/png' })),
|
||||
};
|
||||
}));
|
||||
} catch (err) {
|
||||
|
|
|
@ -2,7 +2,7 @@ import i18n from 'i18next';
|
|||
import { Trans } from 'react-i18next';
|
||||
|
||||
import CopyClipboardButton from './components/CopyClipboardButton';
|
||||
import { isStoreBuild, isMasBuild, isWindowsStoreBuild } from './util';
|
||||
import { isStoreBuild, isMasBuild, isWindowsStoreBuild, isExecaError } from './util';
|
||||
import { ReactSwal } from './swal';
|
||||
|
||||
const electron = window.require('electron');
|
||||
|
@ -33,15 +33,15 @@ export function openSendReportDialog(err: unknown | undefined, state?: unknown)
|
|||
const version = app.getVersion();
|
||||
|
||||
const text = `${err instanceof Error ? err.stack : 'No error occurred.'}\n\n${JSON.stringify({
|
||||
err: err instanceof Error && {
|
||||
code: err['code'],
|
||||
killed: err['killed'],
|
||||
failed: err['failed'],
|
||||
timedOut: err['timedOut'],
|
||||
isCanceled: err['isCanceled'],
|
||||
exitCode: err['exitCode'],
|
||||
signal: err['signal'],
|
||||
signalDescription: err['signalDescription'],
|
||||
err: isExecaError(err) && {
|
||||
code: err.code,
|
||||
isTerminated: err.isTerminated,
|
||||
failed: err.failed,
|
||||
timedOut: err.timedOut,
|
||||
isCanceled: err.isCanceled,
|
||||
exitCode: err.exitCode,
|
||||
signal: err.signal,
|
||||
signalDescription: err.signalDescription,
|
||||
},
|
||||
|
||||
state,
|
||||
|
|
|
@ -291,17 +291,23 @@ export const deleteDispositionValue = 'llc_disposition_remove';
|
|||
|
||||
export const mirrorTransform = 'matrix(-1, 0, 0, 1, 0, 0)';
|
||||
|
||||
export type InvariantExecaError = ExecaError<string> | ExecaError<Buffer> | ExecaError<undefined>;
|
||||
// todo this is not a correct assumption
|
||||
export type InvariantExecaError = ExecaError<{ encoding: 'utf8' }> | ExecaError<{ encoding: 'buffer' }>;
|
||||
|
||||
// note: I don't think we can use instanceof ExecaError because the error has been sent over the main-renderer bridge
|
||||
// We can't use `instanceof ExecaError` because the error has been sent over the main-renderer bridge (@electron/remote)
|
||||
// so instead we just check if it has some of execa's specific error properties
|
||||
export function isExecaError(err: unknown): err is InvariantExecaError {
|
||||
return err instanceof Error && 'stdout' in err && 'stderr' in err;
|
||||
// https://github.com/sindresorhus/execa/blob/main/docs/api.md#resultfailed
|
||||
return err instanceof Error && ('failed' in err && 'shortMessage' in err && 'isForcefullyTerminated' in err);
|
||||
}
|
||||
|
||||
// execa killed (aborted by user)
|
||||
export const isAbortedError = (err: unknown) => isExecaError(err) && err.killed;
|
||||
export const isAbortedError = (err: unknown) => (
|
||||
// execa killed (aborted by user). isTerminated because runningFfmpegs process.kill
|
||||
(isExecaError(err) && (err.isCanceled || err.isTerminated))
|
||||
|| (err instanceof Error && err.name === 'AbortError')
|
||||
);
|
||||
|
||||
export const getStdioString = (stdio: string | Buffer | undefined) => (stdio instanceof Buffer ? stdio.toString('utf8') : stdio);
|
||||
export const getStdioString = (stdio: string | Uint8Array) => (stdio instanceof Uint8Array ? Buffer.from(stdio).toString('utf8') : stdio);
|
||||
|
||||
// A bit hacky but it works, unless someone has a file called "No space left on device" ( ͡° ͜ʖ ͡°)
|
||||
export const isOutOfSpaceError = (err: InvariantExecaError) => (
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"extends": ["@tsconfig/strictest", "@tsconfig/node18/tsconfig.json"],
|
||||
"extends": ["@tsconfig/strictest", "@tsconfig/node20/tsconfig.json"],
|
||||
"compilerOptions": {
|
||||
"noEmit": true,
|
||||
},
|
||||
|
|
156
yarn.lock
156
yarn.lock
|
@ -1804,6 +1804,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sindresorhus/merge-streams@npm:^4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "@sindresorhus/merge-streams@npm:4.0.0"
|
||||
checksum: 10/16551c787f5328c8ef05fd9831ade64369ccc992df78deb635ec6c44af217d2f1b43f8728c348cdc4e00585ff2fad6e00d8155199cbf6b154acc45fe65cbf0aa
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@szmarczak/http-timer@npm:^4.0.5":
|
||||
version: 4.0.6
|
||||
resolution: "@szmarczak/http-timer@npm:4.0.6"
|
||||
|
@ -1843,6 +1850,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@tsconfig/node20@npm:^20.1.4":
|
||||
version: 20.1.4
|
||||
resolution: "@tsconfig/node20@npm:20.1.4"
|
||||
checksum: 10/345dba8074647f6c11b8d78afa76d9c16e3436cb56a8e78fe2060014d33a09f3f4fd6ed81dc90e955d3509f926cd7fd61c6ddfd3d5a1d80758d7844f7cc3a99e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@tsconfig/strictest@npm:^2.0.2":
|
||||
version: 2.0.2
|
||||
resolution: "@tsconfig/strictest@npm:2.0.2"
|
||||
|
@ -2172,12 +2186,12 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/node@npm:18":
|
||||
version: 18.19.21
|
||||
resolution: "@types/node@npm:18.19.21"
|
||||
"@types/node@npm:20":
|
||||
version: 20.17.9
|
||||
resolution: "@types/node@npm:20.17.9"
|
||||
dependencies:
|
||||
undici-types: "npm:~5.26.4"
|
||||
checksum: 10/3a5c5841f294bc35b5b416a32764b5c0c2f22f4cef48cb7d2e3b4e068a52d5857e50da8e6e0685e743127c70344301c833849a3904ce3bd3f67448da5e85487a
|
||||
undici-types: "npm:~6.19.2"
|
||||
checksum: 10/11604a47adf383892394a59a339136b2746a71addf4a3b13f661d23b6e81e8a4f3b35e69dbcffc94698368e5ab5ec056a43a86c87eff00b1b8ea8cfcbfe641df
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
@ -5430,6 +5444,26 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"execa@npm:^9.5.1":
|
||||
version: 9.5.1
|
||||
resolution: "execa@npm:9.5.1"
|
||||
dependencies:
|
||||
"@sindresorhus/merge-streams": "npm:^4.0.0"
|
||||
cross-spawn: "npm:^7.0.3"
|
||||
figures: "npm:^6.1.0"
|
||||
get-stream: "npm:^9.0.0"
|
||||
human-signals: "npm:^8.0.0"
|
||||
is-plain-obj: "npm:^4.1.0"
|
||||
is-stream: "npm:^4.0.1"
|
||||
npm-run-path: "npm:^6.0.0"
|
||||
pretty-ms: "npm:^9.0.0"
|
||||
signal-exit: "npm:^4.1.0"
|
||||
strip-final-newline: "npm:^4.0.0"
|
||||
yoctocolors: "npm:^2.0.0"
|
||||
checksum: 10/aa030cdd43ffbf6a8825c16eec1515729553ce3655a8fa5165f0ddab2320957a9783effbeff37662e238e6f5d979d9732e3baa4bcaaeba4360856e627a214177
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"expand-template@npm:^2.0.3":
|
||||
version: 2.0.3
|
||||
resolution: "expand-template@npm:2.0.3"
|
||||
|
@ -5622,6 +5656,15 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"figures@npm:^6.1.0":
|
||||
version: 6.1.0
|
||||
resolution: "figures@npm:6.1.0"
|
||||
dependencies:
|
||||
is-unicode-supported: "npm:^2.0.0"
|
||||
checksum: 10/9822d13630bee8e6a9f2da866713adf13854b07e0bfde042defa8bba32d47a1c0b2afa627ce73837c674cf9a5e3edce7e879ea72cb9ea7960b2390432d8e1167
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"file-entry-cache@npm:^6.0.1":
|
||||
version: 6.0.1
|
||||
resolution: "file-entry-cache@npm:6.0.1"
|
||||
|
@ -6040,7 +6083,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"get-stream@npm:^9.0.1":
|
||||
"get-stream@npm:^9.0.0, get-stream@npm:^9.0.1":
|
||||
version: 9.0.1
|
||||
resolution: "get-stream@npm:9.0.1"
|
||||
dependencies:
|
||||
|
@ -6516,6 +6559,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"human-signals@npm:^8.0.0":
|
||||
version: 8.0.0
|
||||
resolution: "human-signals@npm:8.0.0"
|
||||
checksum: 10/89acdc7081ac2a065e41cca7351c4b0fe2382e213b7372f90df6a554e340f31b49388a307adc1d6f4c60b2b4fe81eeff0bc1f44be6f5d844311cd92ccc7831c6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"humanize-ms@npm:^1.2.1":
|
||||
version: 1.2.1
|
||||
resolution: "humanize-ms@npm:1.2.1"
|
||||
|
@ -7016,7 +7066,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"is-plain-obj@npm:^4.0.0":
|
||||
"is-plain-obj@npm:^4.0.0, is-plain-obj@npm:^4.1.0":
|
||||
version: 4.1.0
|
||||
resolution: "is-plain-obj@npm:4.1.0"
|
||||
checksum: 10/6dc45da70d04a81f35c9310971e78a6a3c7a63547ef782e3a07ee3674695081b6ca4e977fbb8efc48dae3375e0b34558d2bcd722aec9bddfa2d7db5b041be8ce
|
||||
|
@ -7111,6 +7161,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"is-unicode-supported@npm:^2.0.0":
|
||||
version: 2.1.0
|
||||
resolution: "is-unicode-supported@npm:2.1.0"
|
||||
checksum: 10/f254e3da6b0ab1a57a94f7273a7798dd35d1d45b227759f600d0fa9d5649f9c07fa8d3c8a6360b0e376adf916d151ec24fc9a50c5295c58bae7ca54a76a063f9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"is-valid-glob@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "is-valid-glob@npm:1.0.0"
|
||||
|
@ -7605,6 +7662,7 @@ __metadata:
|
|||
"@radix-ui/react-checkbox": "npm:^1.0.4"
|
||||
"@radix-ui/react-switch": "npm:^1.0.1"
|
||||
"@tsconfig/node18": "npm:^18.2.2"
|
||||
"@tsconfig/node20": "npm:^20.1.4"
|
||||
"@tsconfig/strictest": "npm:^2.0.2"
|
||||
"@tsconfig/vite-react": "npm:^3.0.0"
|
||||
"@types/color": "npm:^3.0.6"
|
||||
|
@ -7618,7 +7676,7 @@ __metadata:
|
|||
"@types/mime-types": "npm:^2.1.4"
|
||||
"@types/morgan": "npm:^1.9.9"
|
||||
"@types/mousetrap": "npm:^1.6.15"
|
||||
"@types/node": "npm:18"
|
||||
"@types/node": "npm:20"
|
||||
"@types/react": "npm:^18.2.66"
|
||||
"@types/react-dom": "npm:^18.2.22"
|
||||
"@types/sortablejs": "npm:^1.15.0"
|
||||
|
@ -7647,7 +7705,7 @@ __metadata:
|
|||
eslint-plugin-react-hooks: "npm:^4.3.0"
|
||||
eslint-plugin-unicorn: "npm:^51.0.1"
|
||||
evergreen-ui: "npm:^6.13.1"
|
||||
execa: "npm:^8.0.1"
|
||||
execa: "npm:^9.5.1"
|
||||
express: "npm:^4.20.0"
|
||||
express-async-handler: "npm:^1.2.0"
|
||||
fast-xml-parser: "npm:^4.4.1"
|
||||
|
@ -7698,7 +7756,7 @@ __metadata:
|
|||
tiny-invariant: "npm:^1.3.3"
|
||||
tsx: "npm:^4.7.1"
|
||||
type-fest: "npm:^4.23.0"
|
||||
typescript: "npm:^5.5.4"
|
||||
typescript: "npm:^5.7.2"
|
||||
use-debounce: "npm:^5.1.0"
|
||||
use-trace-update: "npm:^1.3.0"
|
||||
vite: "npm:^5.3.6"
|
||||
|
@ -8354,6 +8412,16 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"npm-run-path@npm:^6.0.0":
|
||||
version: 6.0.0
|
||||
resolution: "npm-run-path@npm:6.0.0"
|
||||
dependencies:
|
||||
path-key: "npm:^4.0.0"
|
||||
unicorn-magic: "npm:^0.3.0"
|
||||
checksum: 10/1a1b50aba6e6af7fd34a860ba2e252e245c4a59b316571a990356417c0cdf0414cabf735f7f52d9c330899cb56f0ab804a8e21fb12a66d53d7843e39ada4a3b6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"npmlog@npm:^6.0.0":
|
||||
version: 6.0.2
|
||||
resolution: "npmlog@npm:6.0.2"
|
||||
|
@ -8676,6 +8744,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"parse-ms@npm:^4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "parse-ms@npm:4.0.0"
|
||||
checksum: 10/673c801d9f957ff79962d71ed5a24850163f4181a90dd30c4e3666b3a804f53b77f1f0556792e8b2adbb5d58757907d1aa51d7d7dc75997c2a56d72937cbc8b7
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"parse5-htmlparser2-tree-adapter@npm:^7.0.0":
|
||||
version: 7.0.0
|
||||
resolution: "parse5-htmlparser2-tree-adapter@npm:7.0.0"
|
||||
|
@ -8912,6 +8987,15 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"pretty-ms@npm:^9.0.0":
|
||||
version: 9.2.0
|
||||
resolution: "pretty-ms@npm:9.2.0"
|
||||
dependencies:
|
||||
parse-ms: "npm:^4.0.0"
|
||||
checksum: 10/a65a1d81560867f4f7128862fdbf0e1c2d3c5607bf75cae7758bf8111e2c4b744be46e084704125a38ba918bb43defa7a53aaff0f48c5c2d95367d3148c980d9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"prismjs@npm:^1.25.0":
|
||||
version: 1.26.0
|
||||
resolution: "prismjs@npm:1.26.0"
|
||||
|
@ -10483,6 +10567,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"strip-final-newline@npm:^4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "strip-final-newline@npm:4.0.0"
|
||||
checksum: 10/b5fe48f695d74863153a3b3155220e6e9bf51f4447832998c8edec38e6559b3af87a9fe5ac0df95570a78a26f5fa91701358842eab3c15480e27980b154a145f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"strip-indent@npm:^3.0.0":
|
||||
version: 3.0.0
|
||||
resolution: "strip-indent@npm:3.0.0"
|
||||
|
@ -11068,7 +11159,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript@npm:^5.0.4, typescript@npm:^5.5.4":
|
||||
"typescript@npm:^5.0.4":
|
||||
version: 5.5.4
|
||||
resolution: "typescript@npm:5.5.4"
|
||||
bin:
|
||||
|
@ -11078,6 +11169,16 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript@npm:^5.7.2":
|
||||
version: 5.7.2
|
||||
resolution: "typescript@npm:5.7.2"
|
||||
bin:
|
||||
tsc: bin/tsc
|
||||
tsserver: bin/tsserver
|
||||
checksum: 10/4caa3904df69db9d4a8bedc31bafc1e19ffb7b24fbde2997a1633ae1398d0de5bdbf8daf602ccf3b23faddf1aeeb9b795223a2ed9c9a4fdcaf07bfde114a401a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript@patch:typescript@npm%3A^4.0.2#optional!builtin<compat/typescript>":
|
||||
version: 4.9.5
|
||||
resolution: "typescript@patch:typescript@npm%3A4.9.5#optional!builtin<compat/typescript>::version=4.9.5&hash=289587"
|
||||
|
@ -11088,7 +11189,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript@patch:typescript@npm%3A^5.0.4#optional!builtin<compat/typescript>, typescript@patch:typescript@npm%3A^5.5.4#optional!builtin<compat/typescript>":
|
||||
"typescript@patch:typescript@npm%3A^5.0.4#optional!builtin<compat/typescript>":
|
||||
version: 5.5.4
|
||||
resolution: "typescript@patch:typescript@npm%3A5.5.4#optional!builtin<compat/typescript>::version=5.5.4&hash=379a07"
|
||||
bin:
|
||||
|
@ -11098,6 +11199,16 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript@patch:typescript@npm%3A^5.7.2#optional!builtin<compat/typescript>":
|
||||
version: 5.7.2
|
||||
resolution: "typescript@patch:typescript@npm%3A5.7.2#optional!builtin<compat/typescript>::version=5.7.2&hash=74658d"
|
||||
bin:
|
||||
tsc: bin/tsc
|
||||
tsserver: bin/tsserver
|
||||
checksum: 10/ff27fc124bceb8969be722baa38af945b2505767cf794de3e2715e58f61b43780284060287d651fcbbdfb6f917f4653b20f4751991f17e0706db389b9bb3f75d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ua-parser-js@npm:^0.7.30":
|
||||
version: 0.7.33
|
||||
resolution: "ua-parser-js@npm:0.7.33"
|
||||
|
@ -11154,6 +11265,20 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"undici-types@npm:~6.19.2":
|
||||
version: 6.19.8
|
||||
resolution: "undici-types@npm:6.19.8"
|
||||
checksum: 10/cf0b48ed4fc99baf56584afa91aaffa5010c268b8842f62e02f752df209e3dea138b372a60a963b3b2576ed932f32329ce7ddb9cb5f27a6c83040d8cd74b7a70
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"unicorn-magic@npm:^0.3.0":
|
||||
version: 0.3.0
|
||||
resolution: "unicorn-magic@npm:0.3.0"
|
||||
checksum: 10/bdd7d7c522f9456f32a0b77af23f8854f9a7db846088c3868ec213f9550683ab6a2bdf3803577eacbafddb4e06900974385841ccb75338d17346ccef45f9cb01
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"unique-filename@npm:^2.0.0":
|
||||
version: 2.0.1
|
||||
resolution: "unique-filename@npm:2.0.1"
|
||||
|
@ -11761,6 +11886,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"yoctocolors@npm:^2.0.0":
|
||||
version: 2.1.1
|
||||
resolution: "yoctocolors@npm:2.1.1"
|
||||
checksum: 10/563fbec88bce9716d1044bc98c96c329e1d7a7c503e6f1af68f1ff914adc3ba55ce953c871395e2efecad329f85f1632f51a99c362032940321ff80c42a6f74d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"zod@npm:^3.22.5":
|
||||
version: 3.22.5
|
||||
resolution: "zod@npm:3.22.5"
|
||||
|
|
Ładowanie…
Reference in New Issue