mirror of
https://github.com/immich-app/immich.git
synced 2025-07-13 20:38:46 +02:00
feat: sync albums and album users (#18377)
This commit is contained in:
parent
58af574241
commit
cd288533a1
41 changed files with 2811 additions and 934 deletions
server/test
|
@ -4,9 +4,11 @@ import { DateTime } from 'luxon';
|
|||
import { createHash, randomBytes } from 'node:crypto';
|
||||
import { Writable } from 'node:stream';
|
||||
import { AssetFace } from 'src/database';
|
||||
import { AssetJobStatus, Assets, DB, FaceSearch, Person, Sessions } from 'src/db';
|
||||
import { AssetType, AssetVisibility, SourceType } from 'src/enum';
|
||||
import { Albums, AssetJobStatus, Assets, DB, FaceSearch, Person, Sessions } from 'src/db';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { AssetType, AssetVisibility, SourceType, SyncRequestType } from 'src/enum';
|
||||
import { ActivityRepository } from 'src/repositories/activity.repository';
|
||||
import { AlbumUserRepository } from 'src/repositories/album-user.repository';
|
||||
import { AlbumRepository } from 'src/repositories/album.repository';
|
||||
import { AssetJobRepository } from 'src/repositories/asset-job.repository';
|
||||
import { AssetRepository } from 'src/repositories/asset.repository';
|
||||
|
@ -28,8 +30,9 @@ import { UserRepository } from 'src/repositories/user.repository';
|
|||
import { VersionHistoryRepository } from 'src/repositories/version-history.repository';
|
||||
import { UserTable } from 'src/schema/tables/user.table';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { SyncService } from 'src/services/sync.service';
|
||||
import { RepositoryInterface } from 'src/types';
|
||||
import { newDate, newEmbedding, newUuid } from 'test/small.factory';
|
||||
import { factory, newDate, newEmbedding, newUuid } from 'test/small.factory';
|
||||
import { automock, ServiceOverrides } from 'test/utils';
|
||||
import { Mocked } from 'vitest';
|
||||
|
||||
|
@ -39,6 +42,7 @@ const sha256 = (value: string) => createHash('sha256').update(value).digest('bas
|
|||
type RepositoriesTypes = {
|
||||
activity: ActivityRepository;
|
||||
album: AlbumRepository;
|
||||
albumUser: AlbumUserRepository;
|
||||
asset: AssetRepository;
|
||||
assetJob: AssetJobRepository;
|
||||
config: ConfigRepository;
|
||||
|
@ -76,6 +80,61 @@ export type Context<R extends RepositoryOptions, S extends BaseService> = {
|
|||
getRepository<T extends keyof RepositoriesTypes>(key: T): RepositoriesTypes[T];
|
||||
};
|
||||
|
||||
export type SyncTestOptions = {
|
||||
db: Kysely<DB>;
|
||||
};
|
||||
|
||||
export const newSyncAuthUser = () => {
|
||||
const user = mediumFactory.userInsert();
|
||||
const session = mediumFactory.sessionInsert({ userId: user.id });
|
||||
|
||||
const auth = factory.auth({
|
||||
session,
|
||||
user: {
|
||||
id: user.id,
|
||||
name: user.name,
|
||||
email: user.email,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
auth,
|
||||
session,
|
||||
user,
|
||||
create: async (db: Kysely<DB>) => {
|
||||
await new UserRepository(db).create(user);
|
||||
await new SessionRepository(db).create(session);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const newSyncTest = (options: SyncTestOptions) => {
|
||||
const { sut, mocks, repos, getRepository } = newMediumService(SyncService, {
|
||||
database: options.db,
|
||||
repos: {
|
||||
sync: 'real',
|
||||
session: 'real',
|
||||
},
|
||||
});
|
||||
|
||||
const testSync = async (auth: AuthDto, types: SyncRequestType[]) => {
|
||||
const stream = mediumFactory.syncStream();
|
||||
// Wait for 2ms to ensure all updates are available and account for setTimeout inaccuracy
|
||||
await new Promise((resolve) => setTimeout(resolve, 2));
|
||||
await sut.stream(auth, stream, { types });
|
||||
|
||||
return stream.getResponse();
|
||||
};
|
||||
|
||||
return {
|
||||
sut,
|
||||
mocks,
|
||||
repos,
|
||||
getRepository,
|
||||
testSync,
|
||||
};
|
||||
};
|
||||
|
||||
export const newMediumService = <R extends RepositoryOptions, S extends BaseService>(
|
||||
Service: ClassConstructor<S>,
|
||||
options: {
|
||||
|
@ -125,6 +184,14 @@ export const getRepository = <K extends keyof RepositoriesTypes>(key: K, db: Kys
|
|||
return new ActivityRepository(db);
|
||||
}
|
||||
|
||||
case 'album': {
|
||||
return new AlbumRepository(db);
|
||||
}
|
||||
|
||||
case 'albumUser': {
|
||||
return new AlbumUserRepository(db);
|
||||
}
|
||||
|
||||
case 'asset': {
|
||||
return new AssetRepository(db);
|
||||
}
|
||||
|
@ -380,6 +447,19 @@ const assetInsert = (asset: Partial<Insertable<Assets>> = {}) => {
|
|||
};
|
||||
};
|
||||
|
||||
const albumInsert = (album: Partial<Insertable<Albums>> & { ownerId: string }) => {
|
||||
const id = album.id || newUuid();
|
||||
const defaults: Omit<Insertable<Albums>, 'ownerId'> = {
|
||||
albumName: 'Album',
|
||||
};
|
||||
|
||||
return {
|
||||
...defaults,
|
||||
...album,
|
||||
id,
|
||||
};
|
||||
};
|
||||
|
||||
const faceInsert = (face: Partial<Insertable<FaceSearch>> & { faceId: string }) => {
|
||||
const defaults = {
|
||||
faceId: face.faceId,
|
||||
|
@ -502,6 +582,7 @@ export const mediumFactory = {
|
|||
assetInsert,
|
||||
assetFaceInsert,
|
||||
assetJobStatusInsert,
|
||||
albumInsert,
|
||||
faceInsert,
|
||||
personInsert,
|
||||
sessionInsert,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue