feat(model): add service model

This commit is contained in:
Julien Oculi 2024-05-13 16:57:42 +02:00
parent f7f3b48ad1
commit 2ca1ceda60

122
src/models/src/service.ts Normal file
View file

@ -0,0 +1,122 @@
import { ToJson } from '@/types.ts'
import { Group } from '@models/group.ts'
import { Ressource } from '@models/ressource.ts'
import { Ref } from '@/src/models/utils/ref.ts'
export class Service extends Ressource {
static fromJSON(
{ groups, url, avatar, ...json }: ToJson<Service>,
): Service {
return new Service({
groups: groups.map((group) => Ref.fromString<Group>(group)),
url: new URL(url),
avatar: new URL(avatar),
...json,
})
}
static create(
{ category, url, groups, avatar, name }: Pick<
Service,
'category' | 'url' | 'groups' | 'avatar' | 'name'
>,
): Service {
const { uuid, createdAt, updatedAt } = super.create({ name })
return new Service({
uuid,
createdAt,
updatedAt,
name,
category,
url,
groups,
avatar,
})
}
#category: 'bin' | 'web' | 'fs' | 'git'
#url: URL
#groups: readonly Ref<Group>[]
#avatar: URL
private constructor({
category,
url,
groups,
avatar,
...ressource
}: Pick<
Service,
| 'uuid'
| 'createdAt'
| 'updatedAt'
| 'name'
| 'category'
| 'url'
| 'groups'
| 'avatar'
>) {
super(ressource)
if (!['bin', 'web', 'fs', 'git'].includes(category)) {
throw new TypeError(
`category is "${category}" but ('bin' | 'web' | 'fs' | 'git') is required`,
)
}
this.#category = category
this.#url = url
this.#groups = Object.freeze(groups)
this.#avatar = avatar
}
get type(): 'service' {
return 'service'
}
get category() {
return this.#category
}
get url() {
return new URL(this.#url)
}
get groups() {
return Object.freeze(this.#groups)
}
get avatar() {
return new URL(this.#avatar)
}
update(
props: Partial<Omit<Service, 'type' | 'uuid' | 'createdAt'>>,
): Service {
const { updatedAt } = super.update(props)
const service = new Service({ ...this, ...props, updatedAt })
return service
}
toJSON() {
return {
...super.toJSON(),
type: this.type,
category: this.category,
url: this.url.toJSON(),
groups: this.groups.map((group) => group.toJSON()),
avatar: this.avatar.toJSON(),
} as const
}
toString(): string {
return `Service (${JSON.stringify(this)})`
}
}
export interface Service extends Ressource {
type: 'service'
category: 'bin' | 'web' | 'fs' | 'git'
url: URL
groups: readonly Ref<Group>[]
avatar: URL
}