From 2ca1ceda602d3880ee0922d1eb63ebe9de3a554d Mon Sep 17 00:00:00 2001 From: Julien Oculi Date: Mon, 13 May 2024 16:57:42 +0200 Subject: [PATCH] feat(model): :sparkles: add `service` model --- src/models/src/service.ts | 122 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 src/models/src/service.ts diff --git a/src/models/src/service.ts b/src/models/src/service.ts new file mode 100644 index 0000000..20fceed --- /dev/null +++ b/src/models/src/service.ts @@ -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 { + return new Service({ + groups: groups.map((group) => Ref.fromString(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[] + #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>, + ): 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[] + avatar: URL +}