import PocketBase from 'pocketbase'; import { EventEmitter } from 'eventemitter3' type PBOptions = { url: string; token?: string; } export class PBCore { declare client: PocketBase; emitter = new EventEmitter(); token?: string; constructor(options: PBOptions) { this.client = new PocketBase(options.url); this.token = options.token || ''; if (this.token) { this.client.authStore.save(this.token); } } async loginByPassword(email: string, password: string, admin: boolean = true) { const collectionName = admin ? '_superusers' : 'users'; const authData = await this.client.collection(collectionName).authWithPassword(email, password); this.emitter.emit('login', authData); return authData; } async login({ username, password, admin = true }: { username: string; password: string, admin?: boolean }) { if (this.client.authStore.isValid) { return true; } try { await this.loginByPassword(username, password, admin); return true; } catch (error) { console.error('PocketBase login error:', error); return false; } } /** * * https://pocketbase.io/docs/api-collections/#create-collection * * */ async createCollection({ name, type, fields }: CreateCollection) { const collections = await this.client.collections.getFullList(); const existing = collections.find(c => c.name === name); if (existing) { const collection = this.client.collection(name); const schema = await this.client.collections.getOne(name); return { schema: schema, existing: true, collection }; } const schema = await this.client.collections.create({ name, type: type ?? 'base', fields: fields ?? defaultFields, }); const collection = this.client.collection(name); return { collection, schema } } } export const defaultFields: CollectionFields[] = [ { name: 'title', type: 'text', }, { name: 'summary', type: 'text', }, { name: 'description', type: 'text', }, { name: 'tags', type: 'json', }, { name: 'data', type: 'json', }, { name: 'status', type: 'text', }, { name: 'created', type: 'autodate', onCreate: true, }, { name: 'updated', type: 'autodate', onCreate: true, onUpdate: true, } ] export type CollectionFields = { name: string; type: string; required?: boolean; options?: any; onCreate?: boolean; onUpdate?: boolean; } export type CreateCollectioRule = { listRule?: string; viewRule?: string; /** * createRule: 'id = @request.auth.id', */ createRule?: string; updateRule?: string; deleteRule?: string; } export type CreateCollection = { name: string; type?: 'base' | 'viwer' | 'auth'; fields?: CollectionFields[]; /** * viewer: * viewQuery: 'SELECT id, name from posts', */ viewQuery?: string; } & CreateCollectioRule; export class PBService extends PBCore { collectionName = 'images_generation_tasks'; constructor(options: PBOptions) { super(options); this.client.autoCancellation(false) } getCollection(name: string) { return this.client.collection(name); } async initPbService() { const isLogin = this.client.authStore.isValid; console.log('PocketBase is logged in:', isLogin); } async importData(data: any[]) { const collection = this.getCollection(this.collectionName); for (const item of data) { await collection.create(item); } } get collection() { return this.client.collection(this.collectionName); } } const ImageTaskStatus = ['提示词优化中', '计划中', '生成图片中', '图片下载中', '暂停中', '已完成', '失败'] as const; type Data = { images: { type: 'jimeng' | 'tos', url: string }[]; } & T export type ImageCollection = { id: string; created: string; updated: string; title: string; tags: any; summary: string; description: string; data: Data; status: typeof ImageTaskStatus[number]; }