feat: plugins

This commit is contained in:
Jason Rasmussen
2025-10-21 16:45:23 -04:00
parent c3a533ab40
commit 9a35fc8631
15 changed files with 627 additions and 0 deletions

View File

@@ -34,6 +34,7 @@
"email:dev": "email dev -p 3050 --dir src/emails"
},
"dependencies": {
"@extism/extism": "2.0.0-rc13",
"@nestjs/bullmq": "^11.0.1",
"@nestjs/common": "^11.0.4",
"@nestjs/core": "^11.0.4",

View File

@@ -33,6 +33,11 @@ type Item<T extends EmitEvent> = {
label: string;
};
type AssetCreateV1 = {
id: string;
ownerId: string;
};
type EventMap = {
// app events
AppBootstrap: [];
@@ -53,6 +58,7 @@ type EventMap = {
AlbumInvite: [{ id: string; userId: string }];
// asset events
AssetCreate: [{ asset: AssetCreateV1 }];
AssetTag: [{ assetId: string }];
AssetUntag: [{ assetId: string }];
AssetHide: [{ assetId: string; userId: string }];

View File

@@ -426,6 +426,9 @@ export class AssetMediaService extends BaseService {
}
await this.storageRepository.utimes(file.originalPath, new Date(), new Date(dto.fileModifiedAt));
await this.assetRepository.upsertExif({ assetId: asset.id, fileSizeInByte: file.size });
await this.eventRepository.emit('AssetCreate', { asset });
await this.jobRepository.queue({ name: JobName.AssetExtractMetadata, data: { id: asset.id, source: 'upload' } });
return asset;

View File

@@ -22,6 +22,7 @@ import { NotificationAdminService } from 'src/services/notification-admin.servic
import { NotificationService } from 'src/services/notification.service';
import { PartnerService } from 'src/services/partner.service';
import { PersonService } from 'src/services/person.service';
import { PluginService } from 'src/services/plugin.service';
import { SearchService } from 'src/services/search.service';
import { ServerService } from 'src/services/server.service';
import { SessionService } from 'src/services/session.service';
@@ -66,6 +67,7 @@ export const services = [
NotificationAdminService,
PartnerService,
PersonService,
PluginService,
SearchService,
ServerService,
SessionService,

View File

@@ -0,0 +1,31 @@
import { CurrentPlugin, newPlugin } from '@extism/extism';
import { Updateable } from 'kysely';
import { resolve } from 'node:path';
import { OnEvent } from 'src/decorators';
import { ArgOf } from 'src/repositories/event.repository';
import { AssetTable } from 'src/schema/tables/asset.table';
import { BaseService } from 'src/services/base.service';
export class PluginService extends BaseService {
@OnEvent({ name: 'AssetCreate' })
async handleAssetCreate({ asset }: ArgOf<'AssetCreate'>) {
console.log(`PluginService.handleAssetCreate: ${asset.id}`);
const corePath = resolve('../plugins/dist/plugin.wasm');
const plugin = await newPlugin(corePath, {
useWasi: true,
functions: {
'extism:host/user': {
updateAsset: (cp: CurrentPlugin, offs: bigint) => this.updateAsset(JSON.parse(cp.read(offs)!.text())),
},
},
});
const event = { asset };
await plugin.call('archiveAssetAction', JSON.stringify(event));
}
async updateAsset(asset: Updateable<AssetTable> & { id: string }) {
console.log(`Updating asset ${asset.id} -- ${JSON.stringify({ ...asset, id: undefined })}`);
await this.assetRepository.update(asset);
}
}