import { Item } from '@beyond-js/reactive/entities/item';
import { Collection } from '@beyond-js/reactive/entities/collection';
import { IEntityProvider } from '@beyond-js/reactive/entities/item';
import { ICollectionProvider } from '@beyond-js/reactive/entities/collection';
interface IUser {
id: string;
name: string;
email: string;
role: 'user' | 'admin' | 'moderator';
status: 'active' | 'inactive' | 'banned';
}
class UserProvider implements IEntityProvider {
constructor(private parent: User) {}
async load(args?: { id?: string }): Promise<IUser> {
const id = args?.id || this.parent.id;
const response = await fetch(`/api/users/${id}`);
if (!response.ok) throw new Error('Error al cargar usuario');
return await response.json();
}
async publish(data: IUser): Promise<{ status: number; data: IUser }> {
const method = data.id ? 'PUT' : 'POST';
const url = data.id ? `/api/users/${data.id}` : '/api/users';
const response = await fetch(url, {
method,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.message || 'Error al guardar usuario');
}
return { status: 200, data: await response.json() };
}
async delete(id?: string | number): Promise<boolean> {
const userId = id || this.parent.id;
const response = await fetch(`/api/users/${userId}`, { method: 'DELETE' });
return response.ok;
}
}
class UsersProvider implements ICollectionProvider {
constructor(private parent: any) {}
async list(args?: any): Promise<{ items: IUser[], total: number, next?: any }> {
const params = new URLSearchParams();
if (args?.limit) params.append('limit', args.limit);
if (args?.next) params.append('next', args.next);
if (args?.where) params.append('filters', JSON.stringify(args.where));
const response = await fetch(`/api/users?${params}`);
if (!response.ok) throw new Error('Error al cargar usuarios');
const data = await response.json();
return {
items: data.items || data,
total: data.total || 0,
next: data.next || null
};
}
async deleteMany(ids: string[]): Promise<boolean> {
const response = await fetch('/api/users/bulk-delete', {
method: 'DELETE',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ids }),
});
return response.ok;
}
}
export class User extends Item<IUser, UserProvider> {
declare id: string;
declare name: string;
declare email: string;
declare role: 'user' | 'admin' | 'moderator';
declare status: 'active' | 'inactive' | 'banned';
constructor(specs: Partial<IUser> = {}) {
super({
entity: 'users',
provider: UserProvider,
properties: ['id', 'name', 'email', 'role', 'status'],
...specs,
});
}
get isAdmin(): boolean {
return this.role === 'admin';
}
get isActive(): boolean {
return this.status === 'active';
}
async activate() {
this.set({ status: 'active' });
await this.publish();
}
}
export class Users extends Collection<User, UsersProvider> {
constructor() {
super({
entity: 'users',
provider: UsersProvider,
item: User,
defaultLimit: 50,
});
}
get activeUsers(): User[] {
return this.items.filter(u => u.isActive);
}
async loadActiveUsers() {
return await this.load({
where: {
status: { equals: 'active' }
}
});
}
async searchUsers(query: string) {
return await this.load({
where: {
OR: [
{ name: { contains: query } },
{ email: { contains: query } }
]
}
});
}
}
// Uso
async function ejemploCompleto() {
const users = new Users();
await users.loadActiveUsers();
console.log(`Usuarios activos: ${users.activeUsers.length}`);
await users.searchUsers('juan');
const user = users.map.get('user-123');
if (user) {
await user.activate();
user.set({ name: 'Juan Pérez' });
await user.publish();
}
}