2025-11-27 22:15:38 +00:00
|
|
|
/**
|
|
|
|
|
* Team model for Stack.Gallery Registry
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import * as plugins from '../plugins.ts';
|
|
|
|
|
import type { ITeam } from '../interfaces/auth.interfaces.ts';
|
2025-11-27 23:47:33 +00:00
|
|
|
import { db } from './db.ts';
|
2025-11-27 22:15:38 +00:00
|
|
|
|
2025-11-27 23:47:33 +00:00
|
|
|
@plugins.smartdata.Collection(() => db)
|
2025-11-27 22:15:38 +00:00
|
|
|
export class Team extends plugins.smartdata.SmartDataDbDoc<Team, Team> implements ITeam {
|
|
|
|
|
@plugins.smartdata.unI()
|
|
|
|
|
public id: string = '';
|
|
|
|
|
|
|
|
|
|
@plugins.smartdata.svDb()
|
|
|
|
|
@plugins.smartdata.index()
|
|
|
|
|
public organizationId: string = '';
|
|
|
|
|
|
|
|
|
|
@plugins.smartdata.svDb()
|
|
|
|
|
@plugins.smartdata.searchable()
|
|
|
|
|
public name: string = '';
|
|
|
|
|
|
|
|
|
|
@plugins.smartdata.svDb()
|
|
|
|
|
public description?: string;
|
|
|
|
|
|
|
|
|
|
@plugins.smartdata.svDb()
|
|
|
|
|
public isDefaultTeam: boolean = false;
|
|
|
|
|
|
|
|
|
|
@plugins.smartdata.svDb()
|
|
|
|
|
@plugins.smartdata.index()
|
|
|
|
|
public createdAt: Date = new Date();
|
|
|
|
|
|
|
|
|
|
@plugins.smartdata.svDb()
|
|
|
|
|
public updatedAt: Date = new Date();
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Create a new team
|
|
|
|
|
*/
|
|
|
|
|
public static async createTeam(data: {
|
|
|
|
|
organizationId: string;
|
|
|
|
|
name: string;
|
|
|
|
|
description?: string;
|
|
|
|
|
isDefaultTeam?: boolean;
|
|
|
|
|
}): Promise<Team> {
|
|
|
|
|
// Validate name
|
|
|
|
|
const nameRegex = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;
|
|
|
|
|
if (!nameRegex.test(data.name.toLowerCase())) {
|
|
|
|
|
throw new Error('Team name must be lowercase alphanumeric with optional hyphens');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check for duplicate name in org
|
|
|
|
|
const existing = await Team.getInstance({
|
|
|
|
|
organizationId: data.organizationId,
|
|
|
|
|
name: data.name.toLowerCase(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (existing) {
|
|
|
|
|
throw new Error('Team with this name already exists in the organization');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const team = new Team();
|
|
|
|
|
team.id = await Team.getNewId();
|
|
|
|
|
team.organizationId = data.organizationId;
|
|
|
|
|
team.name = data.name.toLowerCase();
|
|
|
|
|
team.description = data.description;
|
|
|
|
|
team.isDefaultTeam = data.isDefaultTeam || false;
|
|
|
|
|
team.createdAt = new Date();
|
|
|
|
|
team.updatedAt = new Date();
|
|
|
|
|
await team.save();
|
|
|
|
|
return team;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Find team by name in organization
|
|
|
|
|
*/
|
|
|
|
|
public static async findByName(organizationId: string, name: string): Promise<Team | null> {
|
|
|
|
|
return await Team.getInstance({
|
|
|
|
|
organizationId,
|
|
|
|
|
name: name.toLowerCase(),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get all teams in an organization
|
|
|
|
|
*/
|
|
|
|
|
public static async getOrgTeams(organizationId: string): Promise<Team[]> {
|
|
|
|
|
return await Team.getInstances({
|
|
|
|
|
organizationId,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Lifecycle hook
|
|
|
|
|
*/
|
|
|
|
|
public async beforeSave(): Promise<void> {
|
|
|
|
|
this.updatedAt = new Date();
|
|
|
|
|
if (!this.id) {
|
|
|
|
|
this.id = await Team.getNewId();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|