diff --git a/packages/clients/src/api/index.ts b/packages/clients/src/api/index.ts index d95d69542..1dca733e0 100644 --- a/packages/clients/src/api/index.ts +++ b/packages/clients/src/api/index.ts @@ -21,3 +21,4 @@ export * as Test from './test' export * as TransactionalEmail from './tem' export * as VPC from './vpc' export * as VPCGW from './vpcgw' +export * as Webhosting from './webhosting' diff --git a/packages/clients/src/api/webhosting/index.ts b/packages/clients/src/api/webhosting/index.ts new file mode 100644 index 000000000..e49bded05 --- /dev/null +++ b/packages/clients/src/api/webhosting/index.ts @@ -0,0 +1 @@ +export * as v1alpha1 from './v1alpha1/index.gen' diff --git a/packages/clients/src/api/webhosting/v1alpha1/api.gen.ts b/packages/clients/src/api/webhosting/v1alpha1/api.gen.ts new file mode 100644 index 000000000..e43c510f5 --- /dev/null +++ b/packages/clients/src/api/webhosting/v1alpha1/api.gen.ts @@ -0,0 +1,243 @@ +// This file was automatically generated. DO NOT EDIT. +// If you have any remark or suggestion do not hesitate to open an issue. +import { + API as ParentAPI, + enrichForPagination, + urlParams, + validatePathParam, + waitForResource, +} from '../../../bridge' +import type { Region, WaitForOptions } from '../../../bridge' +import { HOSTING_TRANSIENT_STATUSES } from './content.gen' +import { + marshalCreateHostingRequest, + marshalUpdateHostingRequest, + unmarshalDnsRecords, + unmarshalHosting, + unmarshalListHostingsResponse, + unmarshalListOffersResponse, +} from './marshalling.gen' +import type { + CreateHostingRequest, + DeleteHostingRequest, + DnsRecords, + GetDomainDnsRecordsRequest, + GetHostingRequest, + Hosting, + ListHostingsRequest, + ListHostingsResponse, + ListOffersRequest, + ListOffersResponse, + RestoreHostingRequest, + UpdateHostingRequest, +} from './types.gen' + +const jsonContentHeaders = { + 'Content-Type': 'application/json; charset=utf-8', +} + +/** Webhosting API. */ +export class API extends ParentAPI { + /** Lists the available regions of the API. */ + public static readonly LOCALITIES: Region[] = ['fr-par'] + + /** + * Create a hosting + * + * @param request - The request {@link CreateHostingRequest} + * @returns A Promise of Hosting + */ + createHosting = (request: Readonly) => + this.client.fetch( + { + body: JSON.stringify( + marshalCreateHostingRequest(request, this.client.settings), + ), + headers: jsonContentHeaders, + method: 'POST', + path: `/webhosting/v1alpha1/regions/${validatePathParam( + 'region', + request.region ?? this.client.settings.defaultRegion, + )}/hostings`, + }, + unmarshalHosting, + ) + + protected pageOfListHostings = ( + request: Readonly = {}, + ) => + this.client.fetch( + { + method: 'GET', + path: `/webhosting/v1alpha1/regions/${validatePathParam( + 'region', + request.region ?? this.client.settings.defaultRegion, + )}/hostings`, + urlParams: urlParams( + ['domain', request.domain], + ['order_by', request.orderBy ?? 'created_at_asc'], + ['organization_id', request.organizationId], + ['page', request.page], + [ + 'page_size', + request.pageSize ?? this.client.settings.defaultPageSize, + ], + ['project_id', request.projectId], + ['statuses', request.statuses], + ['tags', request.tags], + ), + }, + unmarshalListHostingsResponse, + ) + + /** + * List all hostings + * + * @param request - The request {@link ListHostingsRequest} + * @returns A Promise of ListHostingsResponse + */ + listHostings = (request: Readonly = {}) => + enrichForPagination('hostings', this.pageOfListHostings, request) + + /** + * Get the details of a Hosting with the given ID. + * + * @param request - The request {@link GetHostingRequest} + * @returns A Promise of Hosting + */ + getHosting = (request: Readonly) => + this.client.fetch( + { + method: 'GET', + path: `/webhosting/v1alpha1/regions/${validatePathParam( + 'region', + request.region ?? this.client.settings.defaultRegion, + )}/hostings/${validatePathParam('hostingId', request.hostingId)}`, + }, + unmarshalHosting, + ) + + /** + * Waits for {@link Hosting} to be in a final state. + * + * @param request - The request {@link GetHostingRequest} + * @param options - The waiting options + * @returns A Promise of Hosting + */ + waitForHosting = ( + request: Readonly, + options?: Readonly>, + ) => + waitForResource( + options?.stop ?? + (res => + Promise.resolve(!HOSTING_TRANSIENT_STATUSES.includes(res.status))), + this.getHosting, + request, + options, + ) + + /** + * Update a hosting + * + * @param request - The request {@link UpdateHostingRequest} + * @returns A Promise of Hosting + */ + updateHosting = (request: Readonly) => + this.client.fetch( + { + body: JSON.stringify( + marshalUpdateHostingRequest(request, this.client.settings), + ), + headers: jsonContentHeaders, + method: 'PATCH', + path: `/webhosting/v1alpha1/regions/${validatePathParam( + 'region', + request.region ?? this.client.settings.defaultRegion, + )}/hostings/${validatePathParam('hostingId', request.hostingId)}`, + }, + unmarshalHosting, + ) + + /** + * Delete a hosting with the given ID. + * + * @param request - The request {@link DeleteHostingRequest} + * @returns A Promise of Hosting + */ + deleteHosting = (request: Readonly) => + this.client.fetch( + { + method: 'DELETE', + path: `/webhosting/v1alpha1/regions/${validatePathParam( + 'region', + request.region ?? this.client.settings.defaultRegion, + )}/hostings/${validatePathParam('hostingId', request.hostingId)}`, + }, + unmarshalHosting, + ) + + /** + * Restore a hosting with the given ID. + * + * @param request - The request {@link RestoreHostingRequest} + * @returns A Promise of Hosting + */ + restoreHosting = (request: Readonly) => + this.client.fetch( + { + body: '{}', + headers: jsonContentHeaders, + method: 'POST', + path: `/webhosting/v1alpha1/regions/${validatePathParam( + 'region', + request.region ?? this.client.settings.defaultRegion, + )}/hostings/${validatePathParam( + 'hostingId', + request.hostingId, + )}/restore`, + }, + unmarshalHosting, + ) + + /** + * Get the DNS records of a specified domain. + * + * @param request - The request {@link GetDomainDnsRecordsRequest} + * @returns A Promise of DnsRecords + */ + getDomainDnsRecords = (request: Readonly) => + this.client.fetch( + { + method: 'GET', + path: `/webhosting/v1alpha1/regions/${validatePathParam( + 'region', + request.region ?? this.client.settings.defaultRegion, + )}/domains/${validatePathParam('domain', request.domain)}/dns-records`, + }, + unmarshalDnsRecords, + ) + + /** + * List all offers + * + * @param request - The request {@link ListOffersRequest} + * @returns A Promise of ListOffersResponse + */ + listOffers = (request: Readonly) => + this.client.fetch( + { + method: 'GET', + path: `/webhosting/v1alpha1/regions/${validatePathParam( + 'region', + request.region ?? this.client.settings.defaultRegion, + )}/offers`, + urlParams: urlParams( + ['only_options', request.onlyOptions], + ['order_by', request.orderBy ?? 'price_asc'], + ['without_options', request.withoutOptions], + ), + }, + unmarshalListOffersResponse, + ) +} diff --git a/packages/clients/src/api/webhosting/v1alpha1/content.gen.ts b/packages/clients/src/api/webhosting/v1alpha1/content.gen.ts new file mode 100644 index 000000000..807488868 --- /dev/null +++ b/packages/clients/src/api/webhosting/v1alpha1/content.gen.ts @@ -0,0 +1,9 @@ +// This file was automatically generated. DO NOT EDIT. +// If you have any remark or suggestion do not hesitate to open an issue. +import type { HostingStatus } from './types.gen' + +/** Lists transient statutes of the enum {@link HostingStatus}. */ +export const HOSTING_TRANSIENT_STATUSES: HostingStatus[] = [ + 'delivering', + 'deleting', +] diff --git a/packages/clients/src/api/webhosting/v1alpha1/index.gen.ts b/packages/clients/src/api/webhosting/v1alpha1/index.gen.ts new file mode 100644 index 000000000..678f78c0c --- /dev/null +++ b/packages/clients/src/api/webhosting/v1alpha1/index.gen.ts @@ -0,0 +1,33 @@ +// This file was automatically generated. DO NOT EDIT. +// If you have any remark or suggestion do not hesitate to open an issue. +export { API } from './api.gen' +export * from './content.gen' +export type { + CreateHostingRequest, + DeleteHostingRequest, + DnsRecord, + DnsRecordStatus, + DnsRecordType, + DnsRecords, + DnsRecordsStatus, + GetDomainDnsRecordsRequest, + GetHostingRequest, + Hosting, + HostingCpanelUrls, + HostingDnsStatus, + HostingOption, + HostingStatus, + ListHostingsRequest, + ListHostingsRequestOrderBy, + ListHostingsResponse, + ListOffersRequest, + ListOffersRequestOrderBy, + ListOffersResponse, + Nameserver, + NameserverStatus, + Offer, + OfferProduct, + RestoreHostingRequest, + UpdateHostingRequest, +} from './types.gen' +export * as ValidationRules from './validation-rules.gen' diff --git a/packages/clients/src/api/webhosting/v1alpha1/marshalling.gen.ts b/packages/clients/src/api/webhosting/v1alpha1/marshalling.gen.ts new file mode 100644 index 000000000..c4c247e07 --- /dev/null +++ b/packages/clients/src/api/webhosting/v1alpha1/marshalling.gen.ts @@ -0,0 +1,203 @@ +// This file was automatically generated. DO NOT EDIT. +// If you have any remark or suggestion do not hesitate to open an issue. +import { + isJSONObject, + unmarshalArrayOfObject, + unmarshalDate, + unmarshalMoney, +} from '../../../bridge' +import type { DefaultValues } from '../../../bridge' +import type { + CreateHostingRequest, + DnsRecord, + DnsRecords, + Hosting, + HostingCpanelUrls, + HostingOption, + ListHostingsResponse, + ListOffersResponse, + Nameserver, + Offer, + OfferProduct, + UpdateHostingRequest, +} from './types.gen' + +const unmarshalHostingCpanelUrls = (data: unknown) => { + if (!isJSONObject(data)) { + throw new TypeError( + `Unmarshalling the type 'HostingCpanelUrls' failed as data isn't a dictionary.`, + ) + } + + return { + dashboard: data.dashboard, + webmail: data.webmail, + } as HostingCpanelUrls +} + +const unmarshalHostingOption = (data: unknown) => { + if (!isJSONObject(data)) { + throw new TypeError( + `Unmarshalling the type 'HostingOption' failed as data isn't a dictionary.`, + ) + } + + return { id: data.id, name: data.name } as HostingOption +} + +const unmarshalOfferProduct = (data: unknown) => { + if (!isJSONObject(data)) { + throw new TypeError( + `Unmarshalling the type 'OfferProduct' failed as data isn't a dictionary.`, + ) + } + + return { + databasesQuota: data.databases_quota, + emailAccountsQuota: data.email_accounts_quota, + emailStorageQuota: data.email_storage_quota, + hostingStorageQuota: data.hosting_storage_quota, + name: data.name, + option: data.option, + ram: data.ram, + supportIncluded: data.support_included, + vCpu: data.v_cpu, + } as OfferProduct +} + +const unmarshalDnsRecord = (data: unknown) => { + if (!isJSONObject(data)) { + throw new TypeError( + `Unmarshalling the type 'DnsRecord' failed as data isn't a dictionary.`, + ) + } + + return { + name: data.name, + priority: data.priority, + status: data.status, + ttl: data.ttl, + type: data.type, + value: data.value, + } as DnsRecord +} + +export const unmarshalHosting = (data: unknown) => { + if (!isJSONObject(data)) { + throw new TypeError( + `Unmarshalling the type 'Hosting' failed as data isn't a dictionary.`, + ) + } + + return { + cpanelUrls: data.cpanel_urls + ? unmarshalHostingCpanelUrls(data.cpanel_urls) + : undefined, + createdAt: unmarshalDate(data.created_at), + dnsStatus: data.dns_status, + domain: data.domain, + id: data.id, + offerId: data.offer_id, + offerName: data.offer_name, + options: unmarshalArrayOfObject(data.options, unmarshalHostingOption), + organizationId: data.organization_id, + platformHostname: data.platform_hostname, + platformNumber: data.platform_number, + projectId: data.project_id, + region: data.region, + status: data.status, + tags: data.tags, + updatedAt: unmarshalDate(data.updated_at), + username: data.username, + } as Hosting +} + +const unmarshalNameserver = (data: unknown) => { + if (!isJSONObject(data)) { + throw new TypeError( + `Unmarshalling the type 'Nameserver' failed as data isn't a dictionary.`, + ) + } + + return { + hostname: data.hostname, + isDefault: data.is_default, + status: data.status, + } as Nameserver +} + +const unmarshalOffer = (data: unknown) => { + if (!isJSONObject(data)) { + throw new TypeError( + `Unmarshalling the type 'Offer' failed as data isn't a dictionary.`, + ) + } + + return { + billingOperationPath: data.billing_operation_path, + id: data.id, + price: data.price ? unmarshalMoney(data.price) : undefined, + product: data.product ? unmarshalOfferProduct(data.product) : undefined, + } as Offer +} + +export const unmarshalDnsRecords = (data: unknown) => { + if (!isJSONObject(data)) { + throw new TypeError( + `Unmarshalling the type 'DnsRecords' failed as data isn't a dictionary.`, + ) + } + + return { + nameServers: unmarshalArrayOfObject(data.name_servers, unmarshalNameserver), + records: unmarshalArrayOfObject(data.records, unmarshalDnsRecord), + status: data.status, + } as DnsRecords +} + +export const unmarshalListHostingsResponse = (data: unknown) => { + if (!isJSONObject(data)) { + throw new TypeError( + `Unmarshalling the type 'ListHostingsResponse' failed as data isn't a dictionary.`, + ) + } + + return { + hostings: unmarshalArrayOfObject(data.hostings, unmarshalHosting), + totalCount: data.total_count, + } as ListHostingsResponse +} + +export const unmarshalListOffersResponse = (data: unknown) => { + if (!isJSONObject(data)) { + throw new TypeError( + `Unmarshalling the type 'ListOffersResponse' failed as data isn't a dictionary.`, + ) + } + + return { + offers: unmarshalArrayOfObject(data.offers, unmarshalOffer), + } as ListOffersResponse +} + +export const marshalCreateHostingRequest = ( + request: CreateHostingRequest, + defaults: DefaultValues, +): Record => ({ + domain: request.domain, + email: request.email, + offer_id: request.offerId, + option_ids: request.optionIds, + project_id: request.projectId ?? defaults.defaultProjectId, + tags: request.tags, +}) + +export const marshalUpdateHostingRequest = ( + request: UpdateHostingRequest, + defaults: DefaultValues, +): Record => ({ + email: request.email, + offer_id: request.offerId, + option_ids: request.optionIds, + tags: request.tags, +}) diff --git a/packages/clients/src/api/webhosting/v1alpha1/types.gen.ts b/packages/clients/src/api/webhosting/v1alpha1/types.gen.ts new file mode 100644 index 000000000..5ddbad3e8 --- /dev/null +++ b/packages/clients/src/api/webhosting/v1alpha1/types.gen.ts @@ -0,0 +1,279 @@ +// This file was automatically generated. DO NOT EDIT. +// If you have any remark or suggestion do not hesitate to open an issue. +import type { Money, Region } from '../../../bridge' + +export type DnsRecordStatus = 'unknown_status' | 'valid' | 'invalid' + +export type DnsRecordType = + | 'unknown_type' + | 'a' + | 'cname' + | 'mx' + | 'txt' + | 'ns' + | 'aaaa' + +export type DnsRecordsStatus = 'unknown' | 'valid' | 'invalid' + +export type HostingDnsStatus = 'unknown_dns_status' | 'valid' | 'invalid' + +export type HostingStatus = + | 'unknown_status' + | 'delivering' + | 'ready' + | 'deleting' + | 'error' + | 'locked' + +export type ListHostingsRequestOrderBy = 'created_at_asc' | 'created_at_desc' + +export type ListOffersRequestOrderBy = 'price_asc' + +export type NameserverStatus = 'unknown_status' | 'valid' | 'invalid' + +/** Dns record. */ +export interface DnsRecord { + /** Record name. */ + name: string + /** Record type. */ + type: DnsRecordType + /** Record time to live. */ + ttl: number + /** Record value. */ + value: string + /** Record priority level. */ + priority?: number + /** Record status. */ + status: DnsRecordStatus +} + +/** Dns records. */ +export interface DnsRecords { + /** List of DNS records. */ + records: DnsRecord[] + /** List of nameservers. */ + nameServers: Nameserver[] + /** Status of the records. */ + status: DnsRecordsStatus +} + +/** Hosting. */ +export interface Hosting { + /** ID of the hosting. */ + id: string + /** Organization ID of the hosting. */ + organizationId: string + /** Project ID of the hosting. */ + projectId: string + /** Last update date. */ + updatedAt?: Date + /** Creation date. */ + createdAt?: Date + /** The hosting status. */ + status: HostingStatus + /** Hostname of the host platform. */ + platformHostname: string + /** Number of the host platform. */ + platformNumber?: number + /** ID of the active offer. */ + offerId: string + /** Name of the active offer. */ + offerName: string + /** Main domain of the hosting. */ + domain: string + /** Tags of the hosting. */ + tags: string[] + /** Active options of the hosting. */ + options: HostingOption[] + /** DNS status of the hosting. */ + dnsStatus: HostingDnsStatus + /** URL to connect to cPanel Dashboard and to Webmail interface. */ + cpanelUrls?: HostingCpanelUrls + /** Main hosting cPanel username. */ + username: string + /** Region of the hosting. */ + region: Region +} + +export interface HostingCpanelUrls { + dashboard: string + webmail: string +} + +/** Hosting. option. */ +export interface HostingOption { + /** Option ID. */ + id: string + /** Option name. */ + name: string +} + +/** List hostings response. */ +export interface ListHostingsResponse { + /** Number of returned hostings. */ + totalCount: number + /** List of hostings. */ + hostings: Hosting[] +} + +/** List offers response. */ +export interface ListOffersResponse { + /** List of returned offers. */ + offers: Offer[] +} + +/** Nameserver. */ +export interface Nameserver { + /** Hostname of the nameserver. */ + hostname: string + /** Status of the nameserver. */ + status: NameserverStatus + /** If the nameserver is the default. */ + isDefault: boolean +} + +/** Offer. */ +export interface Offer { + /** Offer ID. */ + id: string + /** Unique identifier used for billing. */ + billingOperationPath: string + /** Offer product. */ + product?: OfferProduct + /** Offer price. */ + price?: Money +} + +/** Offer. product. */ +export interface OfferProduct { + /** Product name. */ + name: string + /** Product option. */ + option: boolean + emailAccountsQuota: number + emailStorageQuota: number + databasesQuota: number + hostingStorageQuota: number + supportIncluded: boolean + vCpu: number + ram: number +} + +export type CreateHostingRequest = { + /** + * Region to target. If none is passed will use default region from the + * config. + */ + region?: Region + /** ID of the selected offer for the hosting. */ + offerId: string + /** Project ID of the hosting. */ + projectId?: string + /** Contact email of the client for the hosting. */ + email?: string + /** The tags of the hosting. */ + tags?: string[] + /** The domain name of the hosting. */ + domain: string + /** IDs of the selected options for the hosting. */ + optionIds?: string[] +} + +export type ListHostingsRequest = { + /** + * Region to target. If none is passed will use default region from the + * config. + */ + region?: Region + /** A positive integer to choose the page to return. */ + page?: number + /** + * A positive integer lower or equal to 100 to select the number of items to + * return. + */ + pageSize?: number + /** Define the order of the returned hostings. */ + orderBy?: ListHostingsRequestOrderBy + /** Return hostings with these tags. */ + tags?: string[] + /** Return hostings with these statuses. */ + statuses?: HostingStatus[] + /** Return hostings with this domain. */ + domain?: string + /** Return hostings from this project ID. */ + projectId?: string + /** Return hostings from this organization ID. */ + organizationId?: string +} + +export type GetHostingRequest = { + /** + * Region to target. If none is passed will use default region from the + * config. + */ + region?: Region + /** Hosting ID. */ + hostingId: string +} + +export type UpdateHostingRequest = { + /** + * Region to target. If none is passed will use default region from the + * config. + */ + region?: Region + /** Hosting ID. */ + hostingId: string + /** New contact email for the hosting. */ + email?: string + /** New tags for the hosting. */ + tags?: string[] + /** New options IDs for the hosting. */ + optionIds?: string[] + /** New offer ID for the hosting. */ + offerId?: string +} + +export type DeleteHostingRequest = { + /** + * Region to target. If none is passed will use default region from the + * config. + */ + region?: Region + /** Hosting ID. */ + hostingId: string +} + +export type RestoreHostingRequest = { + /** + * Region to target. If none is passed will use default region from the + * config. + */ + region?: Region + /** Hosting ID. */ + hostingId: string +} + +export type GetDomainDnsRecordsRequest = { + /** + * Region to target. If none is passed will use default region from the + * config. + */ + region?: Region + /** Domain associated to the DNS records. */ + domain: string +} + +export type ListOffersRequest = { + /** + * Region to target. If none is passed will use default region from the + * config. + */ + region?: Region + /** Define the order of the returned hostings. */ + orderBy?: ListOffersRequestOrderBy + /** Select only offers, no options. */ + withoutOptions: boolean + /** Select only options. */ + onlyOptions: boolean +} diff --git a/packages/clients/src/api/webhosting/v1alpha1/validation-rules.gen.ts b/packages/clients/src/api/webhosting/v1alpha1/validation-rules.gen.ts new file mode 100644 index 000000000..59dc683bb --- /dev/null +++ b/packages/clients/src/api/webhosting/v1alpha1/validation-rules.gen.ts @@ -0,0 +1,12 @@ +// This file was automatically generated. DO NOT EDIT. +// If you have any remark or suggestion do not hesitate to open an issue. + +export const ListHostingsRequest = { + page: { + greaterThan: 0, + }, + pageSize: { + greaterThan: 0, + lessThanOrEqual: 100, + }, +}