mirror of
https://github.com/immich-app/immich
synced 2026-08-15 13:03:57 +00:00
chore(server): remove unused code (#30772)
chore(server): remove unnused code
This commit is contained in:
parent
6a61901e79
commit
14241ac7bc
23 changed files with 5 additions and 328 deletions
|
|
@ -1,9 +1,7 @@
|
|||
export const uuidDto = {
|
||||
invalid: 'invalid-uuid',
|
||||
// valid uuid v4
|
||||
notFound: '00000000-0000-4000-a000-000000000000',
|
||||
dummy: '00000000-0000-4000-a000-000000000001',
|
||||
dummy2: '00000000-0000-4000-a000-000000000002',
|
||||
};
|
||||
|
||||
const adminLoginDto = {
|
||||
|
|
@ -57,22 +55,6 @@ export const createUserDto = {
|
|||
};
|
||||
|
||||
export const userDto = {
|
||||
admin: {
|
||||
name: signupDto.admin.name,
|
||||
email: signupDto.admin.email,
|
||||
password: signupDto.admin.password,
|
||||
storageLabel: 'admin',
|
||||
oauthId: '',
|
||||
shouldChangePassword: false,
|
||||
profileImagePath: '',
|
||||
createdAt: new Date('2021-01-01'),
|
||||
deletedAt: null,
|
||||
updatedAt: new Date('2021-01-01'),
|
||||
tags: [],
|
||||
assets: [],
|
||||
quotaSizeInBytes: null,
|
||||
quotaUsageInBytes: 0,
|
||||
},
|
||||
user1: {
|
||||
name: createUserDto.user1.name,
|
||||
email: createUserDto.user1.email,
|
||||
|
|
|
|||
|
|
@ -40,41 +40,6 @@ export const errorDto = {
|
|||
},
|
||||
};
|
||||
|
||||
export const signupResponseDto = {
|
||||
admin: {
|
||||
avatarColor: expect.any(String),
|
||||
id: expect.any(String),
|
||||
name: 'Immich Admin',
|
||||
email: 'admin@immich.cloud',
|
||||
storageLabel: 'admin',
|
||||
profileImagePath: '',
|
||||
// why? lol
|
||||
shouldChangePassword: true,
|
||||
isAdmin: true,
|
||||
createdAt: expect.any(String),
|
||||
updatedAt: expect.any(String),
|
||||
deletedAt: null,
|
||||
oauthId: '',
|
||||
quotaUsageInBytes: 0,
|
||||
quotaSizeInBytes: null,
|
||||
status: 'active',
|
||||
license: null,
|
||||
profileChangedAt: expect.any(String),
|
||||
},
|
||||
};
|
||||
|
||||
export const loginResponseDto = {
|
||||
admin: {
|
||||
accessToken: expect.any(String),
|
||||
name: 'Immich Admin',
|
||||
isAdmin: true,
|
||||
isOnboarded: false,
|
||||
profileImagePath: '',
|
||||
shouldChangePassword: true,
|
||||
userEmail: 'admin@immich.cloud',
|
||||
userId: expect.any(String),
|
||||
},
|
||||
};
|
||||
export const deviceDto = {
|
||||
current: {
|
||||
id: expect.any(String),
|
||||
|
|
|
|||
|
|
@ -24,13 +24,6 @@ export const ASPECT_RATIO_WEIGHTS = {
|
|||
'3:1': 0.01, // 1% 3:1 panorama
|
||||
} as const;
|
||||
|
||||
export type AspectRatio = {
|
||||
width: number;
|
||||
height: number;
|
||||
ratio: number;
|
||||
name: string;
|
||||
};
|
||||
|
||||
// Mock configuration for asset generation - will be transformed to API response formats
|
||||
export type MockTimelineAsset = {
|
||||
id: string;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { BrowserContext, expect, Page } from '@playwright/test';
|
||||
import { expect, Page } from '@playwright/test';
|
||||
import { DateTime } from 'luxon';
|
||||
import { TimelineAssetConfig } from 'src/ui/generators/timeline';
|
||||
|
||||
|
|
@ -11,18 +11,6 @@ export const padYearMonth = (yearMonth: string) => {
|
|||
return `${year}-${month.padStart(2, '0')}`;
|
||||
};
|
||||
|
||||
export async function throttlePage(context: BrowserContext, page: Page) {
|
||||
const session = await context.newCDPSession(page);
|
||||
await session.send('Network.emulateNetworkConditions', {
|
||||
offline: false,
|
||||
downloadThroughput: (1.5 * 1024 * 1024) / 8,
|
||||
uploadThroughput: (750 * 1024) / 8,
|
||||
latency: 40,
|
||||
connectionType: 'cellular3g',
|
||||
});
|
||||
await session.send('Emulation.setCPUThrottlingRate', { rate: 10 });
|
||||
}
|
||||
|
||||
export const poll = async <T>(
|
||||
page: Page,
|
||||
query: () => Promise<T>,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { randomUUID } from 'node:crypto';
|
||||
import { dirname, join, resolve } from 'node:path';
|
||||
import { StorageAsset } from 'src/database';
|
||||
import {
|
||||
|
|
@ -352,10 +351,6 @@ export class StorageCore {
|
|||
return join(StorageCore.getNestedFolder(folder, ownerId, filename), filename);
|
||||
}
|
||||
|
||||
static getTempPathInDir(dir: string): string {
|
||||
return join(dir, `${randomUUID()}.tmp`);
|
||||
}
|
||||
|
||||
private async getDevices() {
|
||||
try {
|
||||
return await this.storageRepository.readdir('/dev/dri');
|
||||
|
|
|
|||
|
|
@ -1211,14 +1211,6 @@ export enum ApiTag {
|
|||
Workflows = 'Workflows',
|
||||
}
|
||||
|
||||
export enum PluginContext {
|
||||
Asset = 'asset',
|
||||
Album = 'album',
|
||||
Person = 'person',
|
||||
}
|
||||
|
||||
export const PluginContextSchema = z.enum(PluginContext).describe('Plugin context').meta({ id: 'PluginContextType' });
|
||||
|
||||
export const WorkflowTriggerSchema = z
|
||||
.enum(WorkflowTrigger)
|
||||
.describe('Plugin trigger type')
|
||||
|
|
|
|||
|
|
@ -1,11 +1,4 @@
|
|||
import {
|
||||
CanActivate,
|
||||
ExecutionContext,
|
||||
Injectable,
|
||||
SetMetadata,
|
||||
applyDecorators,
|
||||
createParamDecorator,
|
||||
} from '@nestjs/common';
|
||||
import { CanActivate, ExecutionContext, Injectable, SetMetadata, applyDecorators } from '@nestjs/common';
|
||||
import { Reflector } from '@nestjs/core';
|
||||
import { Request } from 'express';
|
||||
import { MaintenanceAuthDto } from 'src/dtos/maintenance.dto';
|
||||
|
|
@ -22,14 +15,6 @@ export interface MaintenanceAuthRequest extends Request {
|
|||
auth?: MaintenanceAuthDto;
|
||||
}
|
||||
|
||||
export interface MaintenanceAuthenticatedRequest extends Request {
|
||||
auth: MaintenanceAuthDto;
|
||||
}
|
||||
|
||||
export const MaintenanceAuth = createParamDecorator((data, context: ExecutionContext): MaintenanceAuthDto => {
|
||||
return context.switchToHttp().getRequest<MaintenanceAuthenticatedRequest>().auth;
|
||||
});
|
||||
|
||||
@Injectable()
|
||||
export class MaintenanceAuthGuard implements CanActivate {
|
||||
constructor(
|
||||
|
|
|
|||
|
|
@ -483,35 +483,6 @@ export class DatabaseRepository {
|
|||
await sql`SELECT pg_advisory_unlock(${lock})`.execute(connection);
|
||||
}
|
||||
|
||||
async revertLastMigration(): Promise<string | undefined> {
|
||||
this.logger.debug('Reverting last migration');
|
||||
|
||||
const migrator = this.createMigrator();
|
||||
const { error, results } = await migrator.migrateDown();
|
||||
|
||||
for (const result of results ?? []) {
|
||||
if (result.status === 'Success') {
|
||||
this.logger.log(`Reverted migration "${result.migrationName}"`);
|
||||
} else if (result.status === 'Error') {
|
||||
this.logger.warn(`Failed to revert migration "${result.migrationName}"`);
|
||||
}
|
||||
}
|
||||
|
||||
if (error) {
|
||||
this.logger.error(`Failed to revert migrations: ${error}`);
|
||||
throw error;
|
||||
}
|
||||
|
||||
const reverted = results?.find((result) => result.direction === 'Down' && result.status === 'Success');
|
||||
if (!reverted) {
|
||||
this.logger.debug('No migrations to revert');
|
||||
return undefined;
|
||||
}
|
||||
|
||||
this.logger.debug('Finished reverting migration');
|
||||
return reverted.migrationName;
|
||||
}
|
||||
|
||||
private createMigrator(): Migrator {
|
||||
return new Migrator({
|
||||
db: this.db,
|
||||
|
|
|
|||
|
|
@ -73,7 +73,6 @@ export interface Face {
|
|||
}
|
||||
|
||||
export type FacialRecognitionResponse = { [ModelTask.FACIAL_RECOGNITION]: Face[] } & VisualResponse;
|
||||
export type DetectedFaces = { faces: Face[] } & VisualResponse;
|
||||
export type MachineLearningRequest = ClipVisualRequest | ClipTextualRequest | FacialRecognitionRequest | OcrRequest;
|
||||
export type TextEncodingOptions = ModelOptions & { language?: string };
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { ExpressionBuilder, Insertable, Kysely, Selectable, sql, Updateable } from 'kysely';
|
||||
import { ExpressionBuilder, Insertable, Kysely, sql, Updateable } from 'kysely';
|
||||
import { jsonObjectFrom } from 'kysely/helpers/postgres';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { AssetFace } from 'src/database';
|
||||
|
|
@ -60,8 +60,6 @@ export interface GetAllFacesOptions {
|
|||
|
||||
export type UnassignFacesOptions = DeleteFacesOptions;
|
||||
|
||||
export type SelectFaceOptions = (keyof Selectable<AssetFaceTable>)[];
|
||||
|
||||
const withPerson = (eb: ExpressionBuilder<DB, 'asset_face'>) => {
|
||||
return jsonObjectFrom(
|
||||
eb.selectFrom('person').selectAll('person').whereRef('person.id', '=', 'asset_face.personId'),
|
||||
|
|
|
|||
|
|
@ -158,8 +158,6 @@ export type SmartSearchOptions = SearchDateOptions &
|
|||
SearchTagOptions &
|
||||
SearchOcrOptions & { visibility?: AssetVisibility | 'not-locked' };
|
||||
|
||||
export type OcrSearchOptions = SearchDateOptions & SearchOcrOptions;
|
||||
|
||||
export type LargeAssetSearchOptions = AssetSearchOptions & { minFileSize?: number };
|
||||
|
||||
export interface FaceEmbeddingSearch extends SearchEmbeddingOptions {
|
||||
|
|
|
|||
|
|
@ -8,16 +8,6 @@ import { ReleaseChannel } from 'src/dtos/system-config.dto';
|
|||
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||
|
||||
export interface GitHubRelease {
|
||||
id: number;
|
||||
url: string;
|
||||
tag_name: string;
|
||||
name: string;
|
||||
created_at: string;
|
||||
published_at: string;
|
||||
body: string;
|
||||
}
|
||||
|
||||
export interface VersionResponse {
|
||||
version: string;
|
||||
published_at: string;
|
||||
|
|
|
|||
|
|
@ -9,8 +9,6 @@ import { DB } from 'src/schema';
|
|||
import { SessionTable } from 'src/schema/tables/session.table';
|
||||
import { asUuid } from 'src/utils/database';
|
||||
|
||||
export type SessionSearchOptions = { updatedBefore: Date };
|
||||
|
||||
@Injectable()
|
||||
export class SessionRepository {
|
||||
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||
|
|
|
|||
|
|
@ -444,10 +444,6 @@ export class LibraryService extends BaseService {
|
|||
await this.jobRepository.queue({ name: JobName.LibrarySyncAssetsQueueAll, data: { id } });
|
||||
}
|
||||
|
||||
async queueScanAll() {
|
||||
await this.jobRepository.queue({ name: JobName.LibraryScanQueueAll, data: {} });
|
||||
}
|
||||
|
||||
@OnJob({ name: JobName.LibraryScanQueueAll, queue: QueueName.Library })
|
||||
async handleQueueScanAll(): Promise<JobStatus> {
|
||||
this.logger.log(`Initiating scan of all external libraries...`);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { WorkflowTrigger } from '@immich/plugin-sdk';
|
||||
import { ShallowDehydrateObject } from 'kysely';
|
||||
import { SystemConfig } from 'src/config';
|
||||
import { VECTOR_EXTENSIONS } from 'src/constants';
|
||||
|
|
@ -30,7 +29,6 @@ import {
|
|||
SystemMetadataKey,
|
||||
TranscodeTarget,
|
||||
UserMetadataKey,
|
||||
WorkflowType,
|
||||
} from 'src/enum';
|
||||
import { Mocked } from 'vitest';
|
||||
|
||||
|
|
@ -79,14 +77,6 @@ export interface DecodeToBufferOptions extends DecodeImageOptions {
|
|||
export type GenerateThumbnailOptions = Pick<ImageOptions, 'format' | 'quality' | 'progressive'> & DecodeToBufferOptions;
|
||||
export type GenerateThumbhashOptions = DecodeImageOptions;
|
||||
|
||||
export interface GenerateThumbnailsOptions {
|
||||
colorspace: string;
|
||||
preview?: ImageOptions;
|
||||
processInvalidImages: boolean;
|
||||
thumbhash?: boolean;
|
||||
thumbnail?: ImageOptions;
|
||||
}
|
||||
|
||||
export interface VideoStreamInfo {
|
||||
index: number;
|
||||
height: number;
|
||||
|
|
@ -143,10 +133,6 @@ export interface ImageDimensions {
|
|||
height: number;
|
||||
}
|
||||
|
||||
export interface InputDimensions extends ImageDimensions {
|
||||
inputPath: string;
|
||||
}
|
||||
|
||||
export interface VideoInfo {
|
||||
format: VideoFormat;
|
||||
videoStreams: VideoStreamInfo[];
|
||||
|
|
@ -189,11 +175,6 @@ export interface BitrateDistribution {
|
|||
unit: string;
|
||||
}
|
||||
|
||||
export interface ImageBuffer {
|
||||
data: Buffer;
|
||||
info: RawImageInfo;
|
||||
}
|
||||
|
||||
export interface VideoCodecSWConfig {
|
||||
getCommand(
|
||||
target: TranscodeTarget,
|
||||
|
|
@ -260,18 +241,10 @@ export interface ILibraryBulkIdsJob {
|
|||
totalAssets: number;
|
||||
}
|
||||
|
||||
export interface IBulkEntityJob {
|
||||
ids: string[];
|
||||
}
|
||||
|
||||
export interface IDeleteFilesJob extends IBaseJob {
|
||||
files: Array<string | null | undefined>;
|
||||
}
|
||||
|
||||
export interface ISidecarWriteJob extends IEntityJob {
|
||||
tags?: true;
|
||||
}
|
||||
|
||||
export interface IDeferrableJob extends IEntityJob {
|
||||
deferred?: boolean;
|
||||
}
|
||||
|
|
@ -307,12 +280,6 @@ export interface INotifyAlbumUpdateJob extends IEntityJob, IDelayedJob {
|
|||
recipientId: string;
|
||||
}
|
||||
|
||||
export type IWorkflowJob<T extends WorkflowType = WorkflowType> = {
|
||||
id: string;
|
||||
trigger: WorkflowTrigger;
|
||||
type: T;
|
||||
};
|
||||
|
||||
export interface IIntegrityJob {
|
||||
refreshOnly?: boolean;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,8 +81,6 @@ export const asUuid = (id: string | Expression<string>) => sql<string>`${id}::uu
|
|||
|
||||
export const anyUuid = (ids: string[]) => sql<string>`any(${`{${ids}}`}::uuid[])`;
|
||||
|
||||
export const asVector = (embedding: number[]) => sql<string>`${`[${embedding}]`}::vector`;
|
||||
|
||||
export const unnest = (array: string[]) => sql<Record<string, string>>`unnest(array[${sql.join(array)}]::text[])`;
|
||||
|
||||
export const removeUndefinedKeys = <T extends object>(update: T, template: unknown) => {
|
||||
|
|
|
|||
|
|
@ -712,10 +712,6 @@ export class NvencSwDecodeConfig extends BaseHWConfig {
|
|||
: ['-cq:v', String(this.config.crf)];
|
||||
}
|
||||
|
||||
getThreadOptions() {
|
||||
return [];
|
||||
}
|
||||
|
||||
getEncoderOptions(): string[] {
|
||||
const out = this.getOutputThreadOptions();
|
||||
if (this.tune.strictGop) {
|
||||
|
|
|
|||
13
server/test/fixtures/auth.stub.ts
vendored
13
server/test/fixtures/auth.stub.ts
vendored
|
|
@ -28,19 +28,6 @@ export const authStub = {
|
|||
id: 'token-id',
|
||||
} as AuthSession,
|
||||
}),
|
||||
user2: Object.freeze<AuthDto>({
|
||||
user: {
|
||||
id: 'user-2',
|
||||
name: 'User 2',
|
||||
email: 'user2@immich.cloud',
|
||||
isAdmin: false,
|
||||
quotaSizeInBytes: null,
|
||||
quotaUsageInBytes: 0,
|
||||
},
|
||||
session: {
|
||||
id: 'token-id',
|
||||
} as AuthSession,
|
||||
}),
|
||||
adminWithElevatedPermission: Object.freeze<AuthDto>({
|
||||
user: authUser.admin,
|
||||
session: {
|
||||
|
|
|
|||
7
server/test/fixtures/file.stub.ts
vendored
7
server/test/fixtures/file.stub.ts
vendored
|
|
@ -6,13 +6,6 @@ export const fileStub = {
|
|||
originalName: 'asset_1.jpeg',
|
||||
size: 42,
|
||||
}),
|
||||
livePhotoMotion: Object.freeze({
|
||||
uuid: 'live-photo-motion-asset',
|
||||
originalPath: 'fake_path/asset_1.mp4',
|
||||
checksum: Buffer.from('live photo file hash', 'utf8'),
|
||||
originalName: 'asset_1.mp4',
|
||||
size: 69,
|
||||
}),
|
||||
photo: Object.freeze({
|
||||
uuid: 'photo',
|
||||
originalPath: 'fake_path/photo1.jpeg',
|
||||
|
|
|
|||
22
server/test/fixtures/media.stub.ts
vendored
22
server/test/fixtures/media.stub.ts
vendored
|
|
@ -451,28 +451,6 @@ export const videoInfoStub = {
|
|||
},
|
||||
],
|
||||
}),
|
||||
videoStreamWithProfileLevel: Object.freeze<VideoInfo>({
|
||||
...probeStubDefault,
|
||||
videoStreams: [
|
||||
{
|
||||
...probeStubDefaultVideoStream[0],
|
||||
codecName: 'h264',
|
||||
profile: 100,
|
||||
level: 40,
|
||||
},
|
||||
],
|
||||
}),
|
||||
audioStreamAAC: Object.freeze<VideoInfo>({
|
||||
...probeStubDefault,
|
||||
audioStreams: [
|
||||
{
|
||||
index: 1,
|
||||
codecName: 'aac',
|
||||
profile: 2,
|
||||
bitrate: 128_000,
|
||||
},
|
||||
],
|
||||
}),
|
||||
};
|
||||
|
||||
interface SelectedStreams {
|
||||
|
|
|
|||
|
|
@ -1,27 +1,6 @@
|
|||
import { expect } from 'vitest';
|
||||
|
||||
export const errorDto = {
|
||||
unauthorized: {
|
||||
message: 'Authentication required',
|
||||
},
|
||||
forbidden: {
|
||||
message: expect.any(String),
|
||||
},
|
||||
missingPermission: (permission: string) => ({
|
||||
message: `Missing required permission: ${permission}`,
|
||||
}),
|
||||
wrongPassword: {
|
||||
message: 'Wrong password',
|
||||
},
|
||||
invalidToken: {
|
||||
message: 'Invalid user token',
|
||||
},
|
||||
invalidShareKey: {
|
||||
message: 'Invalid share key',
|
||||
},
|
||||
invalidSharePassword: {
|
||||
message: 'Invalid password',
|
||||
},
|
||||
badRequest: (message: any = null) => ({
|
||||
message: message ?? expect.anything(),
|
||||
}),
|
||||
|
|
@ -29,10 +8,4 @@ export const errorDto = {
|
|||
message: 'Validation failed',
|
||||
errors: errors ? expect.arrayContaining(errors.map((e) => expect.objectContaining(e))) : expect.any(Array),
|
||||
}),
|
||||
noPermission: {
|
||||
message: expect.stringContaining('Not found or no'),
|
||||
},
|
||||
incorrectLogin: {
|
||||
message: 'Incorrect email or password',
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { AuthApiKey, AuthSharedLink, AuthUser, Exif, Library, UserAdmin } from 'src/database';
|
||||
import { AuthApiKey, AuthSharedLink, AuthUser, Library, UserAdmin } from 'src/database';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { QueueStatisticsDto } from 'src/dtos/queue.dto';
|
||||
import { AssetFileType, Permission, UserStatus } from 'src/enum';
|
||||
import { Permission, UserStatus } from 'src/enum';
|
||||
import { v4, v7 } from 'uuid';
|
||||
import { expect } from 'vitest';
|
||||
|
||||
|
|
@ -168,31 +168,6 @@ const versionHistoryFactory = () => ({
|
|||
version: '1.123.45',
|
||||
});
|
||||
|
||||
const assetSidecarWriteFactory = () => {
|
||||
const id = newUuid();
|
||||
return {
|
||||
id,
|
||||
originalPath: '/path/to/original-path.jpg.xmp',
|
||||
tags: [],
|
||||
files: [
|
||||
{
|
||||
id: newUuid(),
|
||||
path: '/path/to/original-path.jpg.xmp',
|
||||
type: AssetFileType.Sidecar,
|
||||
isEdited: false,
|
||||
},
|
||||
],
|
||||
exifInfo: {
|
||||
assetId: id,
|
||||
description: 'this is a description',
|
||||
latitude: 12,
|
||||
longitude: 12,
|
||||
dateTimeOriginal: '2023-11-22T04:56:12.196Z',
|
||||
timeZone: 'UTC-6',
|
||||
} as unknown as Exif,
|
||||
};
|
||||
};
|
||||
|
||||
const assetOcrFactory = (
|
||||
ocr: {
|
||||
id?: string;
|
||||
|
|
@ -236,9 +211,6 @@ export const factory = {
|
|||
library: libraryFactory,
|
||||
queueStatistics: queueStatisticsFactory,
|
||||
versionHistory: versionHistoryFactory,
|
||||
jobAssets: {
|
||||
sidecarWrite: assetSidecarWriteFactory,
|
||||
},
|
||||
uuid: newUuid,
|
||||
buffer: () => Buffer.from('this is a fake buffer'),
|
||||
date: newDate,
|
||||
|
|
|
|||
|
|
@ -553,43 +553,6 @@ export const mockDuplex =
|
|||
return duplex;
|
||||
};
|
||||
|
||||
export const mockFork = vitest.fn((exitCode: number, stdout: string, stderr: string, error?: unknown) => {
|
||||
const stdoutStream = new Readable({
|
||||
read() {
|
||||
this.push(stdout); // write mock data to stdout
|
||||
this.push(null); // end stream
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
stdout: stdoutStream,
|
||||
stderr: new Readable({
|
||||
read() {
|
||||
this.push(stderr); // write mock data to stderr
|
||||
this.push(null); // end stream
|
||||
},
|
||||
}),
|
||||
stdin: new Writable({
|
||||
write(chunk, encoding, callback) {
|
||||
callback();
|
||||
},
|
||||
}),
|
||||
exitCode,
|
||||
on: vitest.fn((event, callback: any) => {
|
||||
if (event === 'close') {
|
||||
stdoutStream.once('end', () => callback(0));
|
||||
}
|
||||
if (event === 'error' && error) {
|
||||
stdoutStream.once('end', () => callback(error));
|
||||
}
|
||||
if (event === 'exit') {
|
||||
stdoutStream.once('end', () => callback(exitCode));
|
||||
}
|
||||
}),
|
||||
kill: vitest.fn(),
|
||||
} as unknown as ChildProcessWithoutNullStreams;
|
||||
});
|
||||
|
||||
export async function* makeStream<T>(items: T[] = []): AsyncGenerator<T> {
|
||||
for (const item of items) {
|
||||
await Promise.resolve();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue