refactor(model): ♻️ move avatar attribute to Ressource base model

This commit is contained in:
Julien Oculi 2024-06-18 13:34:39 +02:00
parent 1fb1f1ce15
commit 5ecebbec14
6 changed files with 50 additions and 52 deletions

View file

@ -10,13 +10,21 @@ export class Credential<T extends CredentialCategory> extends Ressource {
} }
static create<T extends CredentialCategory>( static create<T extends CredentialCategory>(
{ category, store, name }: Pick< { category, store, name, avatar }: Pick<
Credential<T>, Credential<T>,
'category' | 'store' | 'name' 'category' | 'store' | 'name' | 'avatar'
>, >,
): Credential<T> { ): Credential<T> {
const { uuid, createdAt, updatedAt } = super.create({ name }) const { uuid, createdAt, updatedAt } = super.create({ name, avatar })
return new Credential({ uuid, createdAt, updatedAt, name, category, store }) return new Credential({
uuid,
createdAt,
updatedAt,
name,
category,
store,
avatar,
})
} }
#category: T #category: T
@ -25,7 +33,7 @@ export class Credential<T extends CredentialCategory> extends Ressource {
private constructor( private constructor(
{ category, store, ...props }: { category, store, ...props }:
& Pick<Credential<T>, 'category' | 'store'> & Pick<Credential<T>, 'category' | 'store'>
& Pick<Ressource, 'name' | 'uuid' | 'createdAt' | 'updatedAt'>, & Pick<Ressource, 'name' | 'uuid' | 'avatar' | 'createdAt' | 'updatedAt'>,
) { ) {
super(props) super(props)

View file

@ -14,14 +14,15 @@ export class Group extends Ressource {
} }
static create( static create(
{ posix, permissions, name, groups }: Pick< { posix, permissions, name, avatar, groups }: Pick<
Group, Group,
'posix' | 'permissions' | 'name' | 'groups' 'posix' | 'permissions' | 'name' | 'avatar' | 'groups'
>, >,
): Group { ): Group {
const { uuid, createdAt, updatedAt } = super.create({ name }) const { uuid, createdAt, updatedAt } = super.create({ name, avatar })
return new Group({ return new Group({
uuid, uuid,
avatar,
createdAt, createdAt,
updatedAt, updatedAt,
name, name,
@ -44,7 +45,7 @@ export class Group extends Ressource {
private constructor( private constructor(
{ posix, permissions, groups, ...props }: { posix, permissions, groups, ...props }:
& Pick<Group, 'posix' | 'permissions' | 'groups'> & Pick<Group, 'posix' | 'permissions' | 'groups'>
& Pick<Ressource, 'name' | 'uuid' | 'createdAt' | 'updatedAt'>, & Pick<Ressource, 'name' | 'avatar' | 'uuid' | 'createdAt' | 'updatedAt'>,
) { ) {
super(props) super(props)

View file

@ -5,19 +5,19 @@ import { Ressource } from '@models/ressource.ts'
export class Machine extends Ressource { export class Machine extends Ressource {
static fromJSON( static fromJSON(
{ url, avatar, ...json }: ToJson<Machine>, { url, ...json }: ToJson<Machine>,
): Machine { ): Machine {
const groups = json.groups.map((group) => Ref.fromString<Group>(group)) const groups = json.groups.map((group) => Ref.fromString<Group>(group))
return new Machine({ ...json, url, avatar, groups }) return new Machine({ ...json, url, groups })
} }
static create( static create(
{ tags, url, status, avatar, groups, ...props }: { tags, url, status, groups, ...props }:
& Pick<Machine, 'tags' | 'url' | 'status' | 'avatar' | 'groups'> & Pick<Machine, 'tags' | 'url' | 'status' | 'avatar' | 'groups'>
& Pick<Ressource, 'name' | 'uuid' | 'createdAt' | 'updatedAt'>, & Pick<Ressource, 'name' | 'uuid' | 'avatar' | 'createdAt' | 'updatedAt'>,
): Machine { ): Machine {
return new Machine({ ...props, tags, url, status, avatar, groups }) return new Machine({ ...props, tags, url, status, groups })
} }
#tags: readonly string[] #tags: readonly string[]
@ -29,13 +29,12 @@ export class Machine extends Ressource {
| 'discontinued' | 'discontinued'
| 'error' | 'error'
| 'unknown' | 'unknown'
#avatar: UrlString
#groups: readonly Ref<Group>[] #groups: readonly Ref<Group>[]
private constructor( private constructor(
{ tags, url, status, avatar, groups, ...props }: { tags, url, status, groups, ...props }:
& Pick<Machine, 'tags' | 'url' | 'status' | 'avatar' | 'groups'> & Pick<Machine, 'tags' | 'url' | 'status' | 'avatar' | 'groups'>
& Pick<Ressource, 'name' | 'uuid' | 'createdAt' | 'updatedAt'>, & Pick<Ressource, 'name' | 'uuid' | 'avatar' | 'createdAt' | 'updatedAt'>,
) { ) {
super(props) super(props)
@ -47,7 +46,6 @@ export class Machine extends Ressource {
) )
} }
this.#status = status this.#status = status
this.#avatar = new URL(avatar).href as UrlString
this.#groups = Object.freeze(groups) this.#groups = Object.freeze(groups)
} }
@ -63,9 +61,6 @@ export class Machine extends Ressource {
get status() { get status() {
return this.#status return this.#status
} }
get avatar() {
return this.#avatar
}
get groups() { get groups() {
return this.#groups return this.#groups
} }
@ -85,7 +80,6 @@ export class Machine extends Ressource {
tags: this.tags, tags: this.tags,
url: this.url, url: this.url,
status: this.status, status: this.status,
avatar: this.avatar,
groups: Object.freeze(this.groups.map((group) => group.toJSON())), groups: Object.freeze(this.groups.map((group) => group.toJSON())),
} as const } as const
} }
@ -110,6 +104,5 @@ export interface Machine extends Ressource {
| 'discontinued' | 'discontinued'
| 'error' | 'error'
| 'unknown' | 'unknown'
avatar: UrlString
groups: readonly Ref<Group>[] groups: readonly Ref<Group>[]
} }

View file

@ -1,5 +1,5 @@
import { Ref } from '@/src/models/utils/ref.ts' import { Ref } from '@/src/models/utils/ref.ts'
import type { DateString, ToJson, UUID } from '@/types.ts' import type { DateString, ToJson, UrlString, UUID } from '@/types.ts'
import { regex } from '@/utils.ts' import { regex } from '@/utils.ts'
export class Ressource { export class Ressource {
@ -8,29 +8,33 @@ export class Ressource {
): Ressource { ): Ressource {
return new Ressource({ return new Ressource({
name: json.name, name: json.name,
avatar: json.avatar,
uuid: json.uuid, uuid: json.uuid,
createdAt: json.createdAt, createdAt: json.createdAt,
updatedAt: json.updatedAt, updatedAt: json.updatedAt,
}) })
} }
static create({ name }: Pick<Ressource, 'name'>): Ressource { static create(
{ name, avatar }: Pick<Ressource, 'name' | 'avatar'>,
): Ressource {
const uuid = crypto.randomUUID() as UUID const uuid = crypto.randomUUID() as UUID
const createdAt = new Date().toISOString() as DateString const createdAt = new Date().toISOString() as DateString
const updatedAt = createdAt const updatedAt = createdAt
return new Ressource({ name, uuid, createdAt, updatedAt }) return new Ressource({ name, avatar, uuid, createdAt, updatedAt })
} }
#name: string #name: string
#uuid: UUID #uuid: UUID
#createdAt: DateString #createdAt: DateString
#updatedAt: DateString #updatedAt: DateString
#avatar: UrlString
protected constructor( protected constructor(
{ name, uuid, createdAt, updatedAt }: Pick< { name, avatar, uuid, createdAt, updatedAt }: Pick<
Ressource, Ressource,
'name' | 'uuid' | 'createdAt' | 'updatedAt' 'name' | 'avatar' | 'uuid' | 'createdAt' | 'updatedAt'
>, >,
) { ) {
this.#name = name this.#name = name
@ -39,6 +43,7 @@ export class Ressource {
`the following uuid "${uuid}" is not a valid UUID V4`, `the following uuid "${uuid}" is not a valid UUID V4`,
) )
} }
this.#avatar = new URL(avatar).href as UrlString
this.#uuid = uuid this.#uuid = uuid
if (!regex.isoDateString.test(createdAt)) { if (!regex.isoDateString.test(createdAt)) {
throw new SyntaxError( throw new SyntaxError(
@ -63,6 +68,9 @@ export class Ressource {
get name(): string { get name(): string {
return this.#name return this.#name
} }
get avatar(): UrlString {
return this.#avatar
}
get createdAt(): DateString { get createdAt(): DateString {
return this.#createdAt return this.#createdAt
} }
@ -83,6 +91,7 @@ export class Ressource {
type: this.type, type: this.type,
uuid: this.uuid, uuid: this.uuid,
name: this.name, name: this.name,
avatar: this.avatar,
createdAt: this.createdAt, createdAt: this.createdAt,
updatedAt: this.updatedAt, updatedAt: this.updatedAt,
} as const } as const
@ -101,6 +110,7 @@ export interface Ressource {
type: 'user' | 'machine' | 'service' | 'group' | 'credential' type: 'user' | 'machine' | 'service' | 'group' | 'credential'
uuid: UUID uuid: UUID
name: string name: string
avatar: UrlString
createdAt: DateString createdAt: DateString
updatedAt: DateString updatedAt: DateString
} }

View file

@ -19,7 +19,7 @@ export class Service extends Ressource {
'category' | 'tags' | 'url' | 'groups' | 'avatar' | 'name' 'category' | 'tags' | 'url' | 'groups' | 'avatar' | 'name'
>, >,
): Service { ): Service {
const { uuid, createdAt, updatedAt } = super.create({ name }) const { uuid, createdAt, updatedAt } = super.create({ name, avatar })
return new Service({ return new Service({
uuid, uuid,
createdAt, createdAt,
@ -36,7 +36,6 @@ export class Service extends Ressource {
#category: 'web' | 'fs' | 'git' #category: 'web' | 'fs' | 'git'
#url: UrlString #url: UrlString
#groups: readonly Ref<Group>[] #groups: readonly Ref<Group>[]
#avatar: UrlString
#tags: readonly string[] #tags: readonly string[]
private constructor({ private constructor({
@ -44,7 +43,6 @@ export class Service extends Ressource {
tags, tags,
url, url,
groups, groups,
avatar,
...ressource ...ressource
}: Pick< }: Pick<
Service, Service,
@ -68,7 +66,6 @@ export class Service extends Ressource {
this.#category = category this.#category = category
this.#url = new URL(url).href as UrlString this.#url = new URL(url).href as UrlString
this.#groups = Object.freeze(groups) this.#groups = Object.freeze(groups)
this.#avatar = new URL(avatar).href as UrlString
this.#tags = Object.freeze(tags) this.#tags = Object.freeze(tags)
} }
@ -92,10 +89,6 @@ export class Service extends Ressource {
return this.#groups return this.#groups
} }
get avatar() {
return this.#avatar
}
update( update(
props: Partial<Omit<Service, 'type' | 'uuid' | 'createdAt'>>, props: Partial<Omit<Service, 'type' | 'uuid' | 'createdAt'>>,
): Service { ): Service {
@ -112,7 +105,6 @@ export class Service extends Ressource {
tags: this.tags, tags: this.tags,
url: this.url, url: this.url,
groups: this.groups.map((group) => group.toJSON()), groups: this.groups.map((group) => group.toJSON()),
avatar: this.avatar,
} as const } as const
} }
@ -131,5 +123,4 @@ export interface Service extends Ressource {
tags: readonly string[] tags: readonly string[]
url: UrlString url: UrlString
groups: readonly Ref<Group>[] groups: readonly Ref<Group>[]
avatar: UrlString
} }

View file

@ -1,14 +1,12 @@
import { Ref } from '@/src/models/utils/ref.ts' import { Ref } from '@/src/models/utils/ref.ts'
import type { Login, MailAddress, Posix, ToJson, UrlString } from '@/types.ts' import type { Login, MailAddress, Posix, ToJson } from '@/types.ts'
import { regex, toLogin } from '@/utils.ts' import { regex, toLogin } from '@/utils.ts'
import type { Credential, CredentialCategory } from '@models/credential.ts' import type { Credential, CredentialCategory } from '@models/credential.ts'
import type { Group } from '@models/group.ts' import type { Group } from '@models/group.ts'
import { Ressource } from '@models/ressource.ts' import { Ressource } from '@models/ressource.ts'
export class User extends Ressource { export class User extends Ressource {
static fromJSON( static fromJSON(json: ToJson<User>): User {
json: ToJson<User>,
): User {
if (json.type !== 'user') { if (json.type !== 'user') {
throw new TypeError(`type is "${json.type}" but "user" is required`) throw new TypeError(`type is "${json.type}" but "user" is required`)
} }
@ -22,7 +20,10 @@ export class User extends Ressource {
`firstname type is "${typeof json.firstname}" but "string" is required`, `firstname type is "${typeof json.firstname}" but "string" is required`,
) )
} }
if (typeof json.login !== 'string' && /(\w|_)+\.(\w|_)+/.test(json.login)) { if (
typeof json.login !== 'string' &&
/(\w|_)+\.(\w|_)+/.test(json.login)
) {
throw new TypeError( throw new TypeError(
`login is "${json.login}" but "\${string}.\${string}" is required`, `login is "${json.login}" but "\${string}.\${string}" is required`,
) )
@ -48,6 +49,7 @@ export class User extends Ressource {
static create({ static create({
name, name,
avatar,
...props ...props
}: Pick< }: Pick<
User, User,
@ -60,8 +62,8 @@ export class User extends Ressource {
| 'avatar' | 'avatar'
| 'credentials' | 'credentials'
>): User { >): User {
const { uuid, createdAt, updatedAt } = super.create({ name }) const { uuid, createdAt, updatedAt } = super.create({ name, avatar })
return new User({ name, uuid, createdAt, updatedAt, ...props }) return new User({ name, avatar, uuid, createdAt, updatedAt, ...props })
} }
#lastname: string #lastname: string
@ -70,7 +72,6 @@ export class User extends Ressource {
#mail: MailAddress #mail: MailAddress
#groups: readonly Ref<Group>[] #groups: readonly Ref<Group>[]
#posix?: Posix #posix?: Posix
#avatar: UrlString
#credentials: readonly Ref<Credential<CredentialCategory>>[] #credentials: readonly Ref<Credential<CredentialCategory>>[]
private constructor({ private constructor({
@ -79,7 +80,6 @@ export class User extends Ressource {
mail, mail,
groups, groups,
posix, posix,
avatar,
credentials, credentials,
...ressource ...ressource
}: Pick< }: Pick<
@ -112,7 +112,6 @@ export class User extends Ressource {
} }
} }
this.#posix = posix this.#posix = posix
this.#avatar = new URL(avatar).href as UrlString
this.#login = toLogin({ firstname, lastname }) this.#login = toLogin({ firstname, lastname })
this.#credentials = Object.freeze(credentials) this.#credentials = Object.freeze(credentials)
} }
@ -138,9 +137,6 @@ export class User extends Ressource {
get posix() { get posix() {
return this.#posix return this.#posix
} }
get avatar() {
return this.#avatar
}
get credentials() { get credentials() {
return this.#credentials return this.#credentials
} }
@ -182,6 +178,5 @@ export interface User extends Ressource {
mail: MailAddress mail: MailAddress
groups: readonly Ref<Group>[] groups: readonly Ref<Group>[]
posix: Posix | undefined posix: Posix | undefined
avatar: UrlString
credentials: readonly Ref<Credential<CredentialCategory>>[] credentials: readonly Ref<Credential<CredentialCategory>>[]
} }