diff --git a/src/models/src/ressource.ts b/src/models/src/ressource.ts new file mode 100644 index 0000000..326d5a0 --- /dev/null +++ b/src/models/src/ressource.ts @@ -0,0 +1,101 @@ +import { DateString, ToJson, UUID } from '@/types.ts' +import { regex } from '@/utils.ts' + +export class Ressource { + static fromJSON( + json: ToJson, + ): Ressource { + return new Ressource({ + name: json.name, + uuid: json.uuid, + createdAt: json.createdAt, + updatedAt: json.updatedAt, + }) + } + + static create({ name }: Pick): Ressource { + const uuid = crypto.randomUUID() as UUID + const createdAt = new Date().toISOString() as DateString + const updatedAt = createdAt + + return new Ressource({ name, uuid, createdAt, updatedAt }) + } + + #name: string + #uuid: UUID + #createdAt: DateString + #updatedAt: DateString + + protected constructor( + { name, uuid, createdAt, updatedAt }: Pick< + Ressource, + 'name' | 'uuid' | 'createdAt' | 'updatedAt' + >, + ) { + this.#name = name + if (!regex.uuidV4.test(uuid)) { + throw new SyntaxError( + `the following uuid "${uuid}" is not a valid UUID V4`, + ) + } + this.#uuid = uuid + if (!regex.isoDateString.test(createdAt)) { + throw new SyntaxError( + `the following create date "${createdAt}" is not a valid UTC ISO string`, + ) + } + this.#createdAt = createdAt + if (!regex.isoDateString.test(updatedAt)) { + throw new SyntaxError( + `the following update date "${updatedAt}" is not a valid UTC ISO string`, + ) + } + this.#updatedAt = updatedAt + } + + get type(): 'user' | 'machine' | 'service' | 'group' | 'credential' { + throw new Error('ressource super class has no type') + } + get uuid(): UUID { + return this.#uuid + } + get name(): string { + return this.#name + } + get createdAt(): DateString { + return this.#createdAt + } + get updatedAt(): DateString { + return this.#updatedAt + } + + update( + props: Partial>, + ): Ressource { + const updated = new Ressource({ ...this, ...props }) + updated.#updatedAt = new Date().toISOString() as DateString + return updated + } + + toJSON() { + return { + type: this.type, + uuid: this.uuid, + name: this.name, + createdAt: this.createdAt, + updatedAt: this.updatedAt, + } as const + } + + toString(): string { + return `Ressource (${JSON.stringify(this)})` + } +} + +export interface Ressource { + type: 'user' | 'machine' | 'service' | 'group' | 'credential' + uuid: UUID + name: string + createdAt: DateString + updatedAt: DateString +}