Skip to content

Commit

Permalink
feat: add Resource Type to contentful-management [DANTE-1832] (#2429)
Browse files Browse the repository at this point in the history
* feat: add Resource Type to contentful-management [DANTE-1832]

* feat: add tests

* feat: add getMany and orgId to ResourceType APIs

* fix: unit test

* fix: remove resource type id in test

* feat: update comments, add more tests

* fix: wait 1s after deletion

* fix: remove type id from getMany

* feat: clean up urls

* fix: types

* fix: remove empty headers

---------

Co-authored-by: Marouen Ben Salem <[email protected]>
  • Loading branch information
mayakarabula and Cyberxon authored Sep 16, 2024
1 parent 0b42925 commit 8fa9399
Show file tree
Hide file tree
Showing 16 changed files with 916 additions and 6 deletions.
2 changes: 2 additions & 0 deletions lib/adapters/REST/endpoints/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import * as PreviewApiKey from './preview-api-key'
import * as Release from './release'
import * as ReleaseAction from './release-action'
import * as ResourceProvider from './resource-provider'
import * as ResourceType from './resource-type'
import * as Role from './role'
import * as ScheduledAction from './scheduled-action'
import * as Snapshot from './snapshot'
Expand Down Expand Up @@ -96,6 +97,7 @@ export default {
Release,
ReleaseAction,
ResourceProvider,
ResourceType,
Role,
ScheduledAction,
Snapshot,
Expand Down
48 changes: 48 additions & 0 deletions lib/adapters/REST/endpoints/resource-type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import type { RawAxiosRequestHeaders } from 'axios'
import type { AxiosInstance } from 'contentful-sdk-core'
import * as raw from './raw'
import copy from 'fast-copy'
import type { CollectionProp } from '../../../common-types'
import { type GetResourceTypeParams } from '../../../common-types'
import type { RestEndpoint } from '../types'
import type { ResourceTypeProps, UpsertResourceTypeProps } from '../../../entities/resource-type'

const getBaseUrl = (
params: GetResourceTypeParams | Omit<GetResourceTypeParams, 'resourceTypeId'>
) =>
`/organizations/${params.organizationId}/app_definitions/${params.appDefinitionId}/resource_provider/resource_types`

const getEntityUrl = (params: GetResourceTypeParams) =>
`${getBaseUrl(params)}/${params.resourceTypeId}`

export const get: RestEndpoint<'ResourceType', 'get'> = (
http: AxiosInstance,
params: GetResourceTypeParams
) => {
return raw.get<ResourceTypeProps>(http, getEntityUrl(params))
}

export const upsert: RestEndpoint<'ResourceType', 'upsert'> = (
http: AxiosInstance,
params: GetResourceTypeParams,
rawData: UpsertResourceTypeProps,
headers?: RawAxiosRequestHeaders
) => {
const data = copy(rawData)

return raw.put<ResourceTypeProps>(http, getEntityUrl(params), data, { headers })
}

export const del: RestEndpoint<'ResourceType', 'delete'> = (
http: AxiosInstance,
params: GetResourceTypeParams
) => {
return raw.del(http, getEntityUrl(params))
}

export const getMany: RestEndpoint<'ResourceType', 'getMany'> = (
http: AxiosInstance,
params: Omit<GetResourceTypeParams, 'resourceTypeId'>
) => {
return raw.get<CollectionProp<ResourceTypeProps>>(http, getBaseUrl(params))
}
22 changes: 22 additions & 0 deletions lib/common-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ import type {
ResourceProviderProps,
UpsertResourceProviderProps,
} from './entities/resource-provider'
import type { ResourceTypeProps, UpsertResourceTypeProps } from './entities/resource-type'

export interface DefaultElements<TPlainObject extends object = object> {
toPlainObject(): TPlainObject
Expand Down Expand Up @@ -598,6 +599,11 @@ type MRInternal<UA extends boolean> = {
(opts: MROpts<'ResourceProvider', 'upsert', UA>): MRReturn<'ResourceProvider', 'upsert'>
(opts: MROpts<'ResourceProvider', 'delete', UA>): MRReturn<'ResourceProvider', 'delete'>

(opts: MROpts<'ResourceType', 'get', UA>): MRReturn<'ResourceType', 'get'>
(opts: MROpts<'ResourceType', 'upsert', UA>): MRReturn<'ResourceType', 'upsert'>
(opts: MROpts<'ResourceType', 'delete', UA>): MRReturn<'ResourceType', 'delete'>
(opts: MROpts<'ResourceType', 'getMany', UA>): MRReturn<'ResourceType', 'getMany'>

(opts: MROpts<'Role', 'get', UA>): MRReturn<'Role', 'get'>
(opts: MROpts<'Role', 'getMany', UA>): MRReturn<'Role', 'getMany'>
(opts: MROpts<'Role', 'getManyForOrganization', UA>): MRReturn<'Role', 'getManyForOrganization'>
Expand Down Expand Up @@ -780,6 +786,20 @@ export type MRActions = {
}
delete: { params: GetResourceProviderParams; return: any }
}
ResourceType: {
get: { params: GetResourceTypeParams; return: ResourceTypeProps }
getMany: {
params: Omit<GetResourceTypeParams, 'resourceTypeId'>
return: CollectionProp<ResourceTypeProps>
}
upsert: {
params: GetResourceTypeParams
payload: UpsertResourceTypeProps
headers?: RawAxiosRequestHeaders
return: ResourceTypeProps
}
delete: { params: GetResourceTypeParams; return: any }
}
Http: {
get: { params: { url: string; config?: RawAxiosRequestConfig }; return: any }
patch: { params: { url: string; config?: RawAxiosRequestConfig }; payload: any; return: any }
Expand Down Expand Up @@ -2096,6 +2116,8 @@ export type GetUserUIConfigParams = GetUIConfigParams

export type GetResourceProviderParams = GetOrganizationParams & { appDefinitionId: string }

export type GetResourceTypeParams = GetResourceProviderParams & { resourceTypeId: string }

export type QueryParams = { query?: QueryOptions }
export type SpaceQueryParams = { query?: SpaceQueryOptions }
export type PaginationQueryParams = { query?: PaginationQueryOptions }
Expand Down
2 changes: 2 additions & 0 deletions lib/entities/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import * as workflowDefinition from './workflow-definition'
import * as concept from './concept'
import * as conceptScheme from './concept-scheme'
import * as resourceProvider from './resource-provider'
import * as resourceType from './resource-type'

export default {
accessToken,
Expand Down Expand Up @@ -92,6 +93,7 @@ export default {
release,
releaseAction,
resourceProvider,
resourceType,
role,
scheduledAction,
snapshot,
Expand Down
52 changes: 51 additions & 1 deletion lib/entities/resource-provider.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import type { BasicMetaSysProps, DefaultElements, MakeRequest, SysLink } from '../common-types'
import type {
BasicMetaSysProps,
CollectionProp,
DefaultElements,
MakeRequest,
SysLink,
} from '../common-types'
import { toPlainObject, freezeSys } from 'contentful-sdk-core'
import copy from 'fast-copy'
import enhanceWithMethods from '../enhance-with-methods'
import type { ResourceType, UpsertResourceTypeProps } from './resource-type'
import entities from '.'

export type ResourceProviderProps = {
/**
Expand Down Expand Up @@ -30,12 +38,17 @@ export interface ResourceProvider
DefaultElements<ResourceProviderProps> {
upsert(): Promise<ResourceProvider>
delete(): Promise<void>
upsertResourceType(id: string, data: UpsertResourceTypeProps): Promise<ResourceType>
getResourceType(id: string): Promise<ResourceType>
getResourceTypes(): Promise<CollectionProp<ResourceType>>
}

/**
* @private
*/
function createResourceProviderApi(makeRequest: MakeRequest) {
const { wrapResourceType } = entities.resourceType

return {
/**
* Sends an update to the server with any changes made to the object's properties
Expand Down Expand Up @@ -92,6 +105,43 @@ function createResourceProviderApi(makeRequest: MakeRequest) {
params: getParams(data),
})
},

getResourceType: function getResourceType(id: string) {
return makeRequest({
entityType: 'ResourceType',
action: 'get',
params: {
organizationId: this.sys.organization.sys.id,
appDefinitionId: this.sys.appDefinition.sys.id,
resourceTypeId: id,
},
}).then((data) => wrapResourceType(makeRequest, data))
},
upsertResourceType: function upsertResourceType(id: string, data: UpsertResourceTypeProps) {
return makeRequest({
entityType: 'ResourceType',
action: 'upsert',
params: {
organizationId: this.sys.organization.sys.id,
appDefinitionId: this.sys.appDefinition.sys.id,
resourceTypeId: id,
},
payload: data,
}).then((data) => wrapResourceType(makeRequest, data))
},
getResourceTypes: function getResourceTypes() {
return makeRequest({
entityType: 'ResourceType',
action: 'getMany',
params: {
organizationId: this.sys.organization.sys.id,
appDefinitionId: this.sys.appDefinition.sys.id,
},
}).then((data) => {
data.items = data.items.map((item) => wrapResourceType(makeRequest, item))
return data as CollectionProp<ResourceType>
})
},
}
}
/**
Expand Down
140 changes: 140 additions & 0 deletions lib/entities/resource-type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import type {
BasicMetaSysProps,
DefaultElements,
GetResourceTypeParams,
MakeRequest,
SysLink,
} from '../common-types'
import { toPlainObject, freezeSys } from 'contentful-sdk-core'
import copy from 'fast-copy'
import enhanceWithMethods from '../enhance-with-methods'

export type ResourceTypeProps = {
/**
* System metadata
*/
sys: Omit<BasicMetaSysProps, 'version'> & {
appDefinition: SysLink
organization: SysLink
resourceProvider: SysLink
}
/**
* Resource Type name
*/
name: string
/**
* Resource Type defaultFieldMapping
*/
defaultFieldMapping: {
title: string
subtitle?: string
description?: string
externalUrl?: string
image?: {
url: string
altText?: string
}
badge?: {
label: string
variant: string
}
}
}

export type UpsertResourceTypeProps = Omit<ResourceTypeProps, 'sys'>

export interface ResourceType extends ResourceTypeProps, DefaultElements<ResourceTypeProps> {
upsert(): Promise<ResourceType>
delete(): Promise<void>
}

/**
* @private
*/
function createResourceTypeApi(makeRequest: MakeRequest) {
return {
/**
* Sends an update to the server with any changes made to the object's properties
* @return Object returned from the server with updated changes.
* @example ```javascript
* const contentful = require('contentful-management')
*
* const client = contentful.createClient({
* accessToken: '<content_management_api_key>'
* })
*
* client.getOrganization('<org_id>')
* .then((org) => org.getAppDefinition('<app_def_id>'))
* .then((appDefinition) => appDefinition.getResourceType())
* .then((resourceType) => {
* resourceType.name = '<new_name>'
* return resourceType.upsert()
* })
* .catch(console.error)
* ```
*/
upsert: function upsert() {
const data = this.toPlainObject() as ResourceTypeProps

return makeRequest({
entityType: 'ResourceType',
action: 'upsert',
params: getParams(data),
headers: {},
payload: getUpsertParams(data),
}).then((data) => wrapResourceType(makeRequest, data))
},
/**
* Deletes this object on the server.
* @return Promise for the deletion. It contains no data, but the Promise error case should be handled.
* @example ```javascript
* const contentful = require('contentful-management')
*
* const client = contentful.createClient({
* accessToken: '<content_management_api_key>'
* })
*
* client.getOrganization('<org_id>')
* .then((org) => org.getAppDefinition('<app_def_id>'))
* .then((appDefinition) => appDefinition.getResourceType())
* .then((resourceType) => resourceType.delete())
* .catch(console.error)
* ```
*/
delete: function del() {
const data = this.toPlainObject() as ResourceTypeProps

return makeRequest({
entityType: 'ResourceType',
action: 'delete',
params: getParams(data),
})
},
}
}

const getParams = (data: ResourceTypeProps): GetResourceTypeParams => ({
organizationId: data.sys.organization.sys.id,
appDefinitionId: data.sys.appDefinition.sys.id,
resourceTypeId: data.sys.id,
})

const getUpsertParams = (data: ResourceTypeProps): UpsertResourceTypeProps => ({
name: data.name,
defaultFieldMapping: data.defaultFieldMapping,
})

/**
* @private
* @param makeRequest - function to make requests via an adapter
* @param data - Raw Resource Type data
* @return Wrapped Resource Type data
*/
export function wrapResourceType(makeRequest: MakeRequest, data: ResourceTypeProps): ResourceType {
const resourceType = toPlainObject(copy(data))
const ResourceTypeWithMethods = enhanceWithMethods(
resourceType,
createResourceTypeApi(makeRequest)
)
return freezeSys(ResourceTypeWithMethods)
}
5 changes: 5 additions & 0 deletions lib/export-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,3 +287,8 @@ export type {
ResourceProviderProps,
UpsertResourceProviderProps,
} from './entities/resource-provider'
export type {
ResourceType,
ResourceTypeProps,
UpsertResourceTypeProps,
} from './entities/resource-type'
2 changes: 2 additions & 0 deletions lib/plain/common-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ import type { AppAccessTokenPlainClientAPI } from './entities/app-access-token'
import type { ConceptPlainClientAPI } from './entities/concept'
import type { ConceptSchemePlainClientAPI } from './entities/concept-scheme'
import type { ResourceProviderPlainClientAPI } from './entities/resource-provider'
import type { ResourceTypePlainClientAPI } from './entities/resource-type'

export type PlainClientAPI = {
raw: {
Expand Down Expand Up @@ -505,6 +506,7 @@ export type PlainClientAPI = {
appDefinition: AppDefinitionPlainClientAPI
appInstallation: AppInstallationPlainClientAPI
resourceProvider: ResourceProviderPlainClientAPI
resourceType: ResourceTypePlainClientAPI
extension: ExtensionPlainClientAPI
webhook: WebhookPlainClientAPI
snapshot: {
Expand Down
Loading

0 comments on commit 8fa9399

Please sign in to comment.