diff --git a/packages/models/src/config/config.ts b/packages/models/src/config/config.ts index c20a52c3..969c32bb 100644 --- a/packages/models/src/config/config.ts +++ b/packages/models/src/config/config.ts @@ -6,6 +6,7 @@ import { ContractBehaviors } from "../contract/Contract/behaviors/index.js"; import { AppInstallationBehaviors } from "../app/AppInstallation/behaviors/index.js"; import { ContractItemBehaviors } from "../contract/ContractItem/behaviors/index.js"; import { ArticleBehaviors } from "../article/Article/behaviors/index.js"; +import { DomainBehaviors } from "../domain/Domain/behaviors/types.js"; interface Config { defaultPaginationLimit: number; @@ -17,6 +18,7 @@ interface Config { server: ServerBehaviors; customer: CustomerBehaviors; ingress: IngressBehaviors; + domain: DomainBehaviors; appInstallation: AppInstallationBehaviors; }; } @@ -31,6 +33,7 @@ export const config: Config = { server: undefined as unknown as ServerBehaviors, customer: undefined as unknown as CustomerBehaviors, ingress: undefined as unknown as IngressBehaviors, + domain: undefined as unknown as DomainBehaviors, appInstallation: undefined as unknown as AppInstallationBehaviors, }, }; diff --git a/packages/models/src/domain/Domain/Domain.ts b/packages/models/src/domain/Domain/Domain.ts new file mode 100644 index 00000000..631b8ce5 --- /dev/null +++ b/packages/models/src/domain/Domain/Domain.ts @@ -0,0 +1,124 @@ +import { classes } from "polytype"; +import { + DataModel, + ListDataModel, + ListQueryModel, + ReferenceModel, +} from "../../base/index.js"; +import { + DomainData, + DomainListItemData, + DomainListQueryData, + DomainListQueryModelData, +} from "./types.js"; +import { provideReact } from "../../react/provideReact.js"; +import { config } from "../../config/config.js"; +import assertObjectFound from "../../base/assertObjectFound.js"; + +export class Domain extends ReferenceModel { + public static ofId(id: string): Domain { + return new Domain(id); + } + + public static find = provideReact( + async (id: string): Promise => { + const data = await config.behaviors.domain.find(id); + if (data !== undefined) { + return new DomainDetailed(data); + } + }, + ); + + public static get = provideReact( + async (id: string): Promise => { + const domain = await this.find(id); + assertObjectFound(domain, this, id); + return domain; + }, + ); + + public static query = (query: DomainListQueryModelData = {}) => { + return new DomainListQuery(query); + }; +} + +export class DomainCommon extends classes(DataModel, Domain) { + public readonly id: string; + public readonly hostname: string; + + public constructor(data: DomainData) { + super([data], [data.domainId]); + this.hostname = data.domain; + this.id = data.domainId; + } +} + +export class DomainDetailed extends classes( + DomainCommon, + DataModel, +) { + public constructor(data: DomainData) { + super([data], [data]); + } +} + +export class DomainListItem extends classes( + DomainCommon, + DataModel, +) { + public constructor(data: DomainListItemData) { + super([data]); + } +} + +export class DomainListQuery extends ListQueryModel { + public constructor(data: DomainListQueryModelData = {}) { + super(data); + } + + public refine(query: DomainListQueryModelData) { + return new DomainListQuery({ + ...this.query, + ...query, + }); + } + + public execute = provideReact(async () => { + const { ...query } = this.query; + const { items, totalCount } = await config.behaviors.domain.query({ + limit: config.defaultPaginationLimit, + ...query, + }); + + return new DomainList( + this.query, + items.map((d) => new DomainListItem(d)), + totalCount, + ); + }, [this.queryId]); + + public getTotalCount = provideReact(async () => { + const { totalCount } = await this.refine({ limit: 1 }).execute(); + return totalCount; + }, [this.queryId]); + + public findOneAndOnly = provideReact(async () => { + const { items, totalCount } = await this.refine({ limit: 1 }).execute(); + if (totalCount === 1) { + return items[0]; + } + }, [this.queryId]); +} + +export class DomainList extends classes( + DomainListQuery, + ListDataModel, +) { + public constructor( + query: DomainListQueryData, + domains: DomainListItem[], + totalCount: number, + ) { + super([query], [domains, totalCount]); + } +} diff --git a/packages/models/src/domain/Domain/behaviors/types.ts b/packages/models/src/domain/Domain/behaviors/types.ts new file mode 100644 index 00000000..21992e1f --- /dev/null +++ b/packages/models/src/domain/Domain/behaviors/types.ts @@ -0,0 +1,13 @@ +import { + DomainData, + DomainListItemData, + DomainListQueryData, +} from "../types.js"; +import { QueryResponseData } from "../../../base/index.js"; + +export interface DomainBehaviors { + find: (id: string) => Promise; + query: ( + query?: DomainListQueryData, + ) => Promise>; +} diff --git a/packages/models/src/domain/Domain/index.ts b/packages/models/src/domain/Domain/index.ts new file mode 100644 index 00000000..b309cafd --- /dev/null +++ b/packages/models/src/domain/Domain/index.ts @@ -0,0 +1,2 @@ +export * from "./Domain.js"; +export * from "types.js"; diff --git a/packages/models/src/domain/Domain/types.ts b/packages/models/src/domain/Domain/types.ts new file mode 100644 index 00000000..98b2e6ea --- /dev/null +++ b/packages/models/src/domain/Domain/types.ts @@ -0,0 +1,17 @@ +import { MittwaldAPIV2 } from "@mittwald/api-client"; +import { Project } from "../../project/index.js"; + +export type DomainListQueryData = + MittwaldAPIV2.Paths.V2Domains.Get.Parameters.Query; + +export type DomainListQueryModelData = Omit< + DomainListQueryData, + "projectId" +> & { + project?: Project; +}; + +export type DomainData = MittwaldAPIV2.Operations.DomainGetDomain.ResponseData; + +export type DomainListItemData = + MittwaldAPIV2.Operations.DomainListDomains.ResponseData[number];