Skip to content

Refactor: clean up what many devs left untouched (improves DX) #2588

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 17 commits into
base: refactor/docs
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
0980259
refactor: remove index file in entities folder for cleaner import str…
axe312ger Mar 25, 2025
b9d6dfa
refactor: ensure export types are really only used to export types
axe312ger Mar 25, 2025
72ed3f5
refactor: rename plain/common-types to actually describe what the fil…
axe312ger Mar 25, 2025
cbe77a4
fix: remove confusing outdated ClientParams type and finally export t…
axe312ger Mar 25, 2025
c633bbe
refactor: clean up messy imports and exports in main file - many cook…
axe312ger Mar 25, 2025
59ae491
chore: reinstall to clean up package.json and lock file
axe312ger Mar 25, 2025
38d9914
refactor: rename params to clientOptions in createClient function to …
axe312ger Mar 25, 2025
c5454cd
refactor: remove deprecated, unsupported and unused alphaFeatures
axe312ger Mar 25, 2025
54fcffa
refactor: clean up createClient overloads, add examples for each way …
axe312ger Mar 25, 2025
7afe777
docs: README - clearer distinction between plain and legacy client, h…
axe312ger Mar 27, 2025
5363aca
Refactor/restructure and improve docs (#2592)
axe312ger Apr 24, 2025
c7c3d93
fix: move type-fest to a regular dependency
axe312ger Apr 29, 2025
ffe8500
docs: set link to changelog to github releases page
axe312ger Apr 29, 2025
81f6f67
docs: prever ESM syntax over CommonJS
axe312ger Apr 29, 2025
7abf4ba
docs: remove broken link to runkit
axe312ger Apr 29, 2025
9727036
docs: remove unnesessary mention of version 1.0.0
axe312ger Apr 29, 2025
3621ffa
docs: remove unnesessary colons in node and browser headline
axe312ger Apr 29, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<a href="README.md">Readme</a> ·
<a href="SETUP.md">Setup</a> ·
<a href="MIGRATION.md">Migration</a> ·
<a href="CHANGELOG.md">Changelog</a> ·
<a href="https://github.com/contentful/contentful-management.js/releases">Changelog</a> ·
<a href="CONTRIBUTING.md">Contributing</a>
</p>

Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<a href="README.md">Readme</a> ·
<a href="SETUP.md">Setup</a> ·
<a href="MIGRATION.md">Migration</a> ·
<a href="CHANGELOG.md">Changelog</a> ·
<a href="https://github.com/contentful/contentful-management.js/releases">Changelog</a> ·
<a href="CONTRIBUTING.md">Contributing</a>
</p>

Expand Down
237 changes: 99 additions & 138 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<a href="README.md">Readme</a> ·
<a href="SETUP.md">Setup</a> ·
<a href="MIGRATION.md">Migration</a> ·
<a href="CHANGELOG.md">Changelog</a> ·
<a href="https://github.com/contentful/contentful-management.js/releases">Changelog</a> ·
<a href="CONTRIBUTING.md">Contributing</a>
</p>

Expand Down
2 changes: 1 addition & 1 deletion lib/adapters/REST/make-request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { AxiosInstance } from 'contentful-sdk-core'
import type { MakeRequestOptions, MakeRequestPayload } from '../../common-types'
import type { OpPatch } from 'json-patch'
import type { RawAxiosRequestHeaders } from 'axios'
import endpoints from './endpoints'
import endpoints from './endpoints/index'

type makeAxiosRequest = MakeRequestOptions & {
axiosInstance: AxiosInstance
Expand Down
19 changes: 9 additions & 10 deletions lib/common-utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */

import { toPlainObject } from 'contentful-sdk-core'
import copy from 'fast-copy'
import type {
Expand All @@ -17,10 +15,11 @@ export const wrapCollection =
<R, T, Rest extends any[]>(fn: (makeRequest: MakeRequest, entity: T, ...rest: Rest) => R) =>
(makeRequest: MakeRequest, data: CollectionProp<T>, ...rest: Rest): Collection<R, T> => {
const collectionData = toPlainObject(copy(data))
// @ts-expect-error
collectionData.items = collectionData.items.map((entity) => fn(makeRequest, entity, ...rest))
// @ts-expect-error
return collectionData

return {
...collectionData,
items: collectionData.items.map((entity) => fn(makeRequest, entity, ...rest)),
}
}

export const wrapCursorPaginatedCollection =
Expand All @@ -31,10 +30,10 @@ export const wrapCursorPaginatedCollection =
...rest: Rest
): CursorPaginatedCollection<R, T> => {
const collectionData = toPlainObject(copy(data))
// @ts-expect-error
collectionData.items = collectionData.items.map((entity) => fn(makeRequest, entity, ...rest))
// @ts-expect-error
return collectionData
return {
...collectionData,
items: collectionData.items.map((entity) => fn(makeRequest, entity, ...rest)),
}
}
export function isSuccessful(statusCode: number) {
return statusCode < 300
Expand Down
107 changes: 8 additions & 99 deletions lib/contentful-management.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,109 +4,18 @@
* @packageDocumentation
*/

import { getUserAgentHeader } from 'contentful-sdk-core'
import type { RestAdapterParams } from './adapters/REST/rest-adapter'
import type { MakeRequest, XOR } from './common-types'
import type { AdapterParams } from './create-adapter'
import { createAdapter } from './create-adapter'
import type { ClientAPI } from './create-contentful-api'
import createContentfulApi from './create-contentful-api'
import type { PlainClientAPI } from './plain/common-types'
import type { DefaultParams } from './plain/plain-client'
import { createPlainClient } from './plain/plain-client'
import * as editorInterfaceDefaults from './constants/editor-interface-defaults'
export type { PlainClientDefaultParams } from './plain/plain-client'

export type { ClientAPI } from './create-contentful-api'
export type { PlainClientAPI } from './plain/plain-client-types'
export type { RestAdapterParams } from './adapters/REST/rest-adapter'
export type * from './export-types'

export { asIterator } from './plain/as-iterator'
export { fetchAll } from './plain/pagination-helper'
export { isDraft, isPublished, isUpdated } from './plain/checks'
export type { PlainClientAPI } from './plain/common-types'
export { createClient }
export { RestAdapter } from './adapters/REST/rest-adapter'
export type { RestAdapterParams } from './adapters/REST/rest-adapter'
export { makeRequest } from './adapters/REST/make-request'
export { editorInterfaceDefaults }
export type PlainClientDefaultParams = DefaultParams
export * from './export-types'

interface UserAgentParams {
/**
* Application name and version e.g myApp/version
*/
application?: string
/**
* Integration name and version e.g react/version
*/
integration?: string

feature?: string
}

/**
* @deprecated
*/
export type ClientParams = RestAdapterParams & UserAgentParams
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is already labeled as deprecated, do you think this is safe to remove?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, as these are used by the legacy client.

The whole legacy vs plain client situation should be adressed by us soon IMHO

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@whitelisab so i checked, this is a left over from ages ago and just confuses people. so lets get rid of it! The real config types for plain and legacy client are available for our users


export type ClientOptions = UserAgentParams & XOR<RestAdapterParams, AdapterParams>

/**
* Create a client instance
* @param params - Client initialization parameters
*
* ```javascript
* const client = contentfulManagement.createClient({
* accessToken: 'myAccessToken'
* })
* ```
*/
function createClient(params: ClientOptions): ClientAPI
function createClient(
params: ClientOptions,
opts: {
type: 'plain'
defaults?: DefaultParams
}
): PlainClientAPI
// Usually, overloads with more specific signatures should come first but some IDEs are often not able to handle overloads with separate TSDocs correctly
/**
* @deprecated The `alphaFeatures` option is no longer supported. Please use the function without this option.
*/
function createClient(
params: ClientOptions,
opts: {
type?: 'plain'
alphaFeatures: string[]
defaults?: DefaultParams
}
): ClientAPI | PlainClientAPI
function createClient(
params: ClientOptions,
opts: {
type?: 'plain'
defaults?: DefaultParams
} = {}
): ClientAPI | PlainClientAPI {
const sdkMain =
opts.type === 'plain' ? 'contentful-management-plain.js' : 'contentful-management.js'
const userAgent = getUserAgentHeader(
// @ts-expect-error
`${sdkMain}/${__VERSION__}`,
params.application,
params.integration,
params.feature
)

const adapter = createAdapter({ ...params, userAgent })

// Parameters<?> and ReturnType<?> only return the types of the last overload
// https://github.com/microsoft/TypeScript/issues/26591
// @ts-expect-error
const makeRequest: MakeRequest = (options: Parameters<MakeRequest>[0]): ReturnType<MakeRequest> =>
adapter.makeRequest({ ...options, userAgent })
export { RestAdapter } from './adapters/REST/rest-adapter'
export * as editorInterfaceDefaults from './constants/editor-interface-defaults/index'

if (opts.type === 'plain') {
return createPlainClient(makeRequest, opts.defaults)
} else {
return createContentfulApi(makeRequest) as ClientAPI
}
}
export * from './create-client'
6 changes: 2 additions & 4 deletions lib/create-app-definition-api.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { MakeRequest, QueryOptions, SpaceQueryOptions } from './common-types'
import entities from './entities'
import { wrapAppBundle, wrapAppBundleCollection } from './entities/app-bundle'
import { wrapResourceProvider } from './entities/resource-provider'
import type { CreateAppBundleProps } from './entities/app-bundle'
import type { AppDefinitionProps } from './entities/app-definition'
import { wrapAppDefinition } from './entities/app-definition'
Expand All @@ -14,9 +15,6 @@ export type ContentfulAppDefinitionAPI = ReturnType<typeof createAppDefinitionAp
* @private
*/
export default function createAppDefinitionApi(makeRequest: MakeRequest) {
const { wrapAppBundle, wrapAppBundleCollection } = entities.appBundle
const { wrapResourceProvider } = entities.resourceProvider

const getParams = (data: AppDefinitionProps) => ({
appDefinitionId: data.sys.id,
organizationId: data.sys.organization.sys.id,
Expand Down
119 changes: 119 additions & 0 deletions lib/create-client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/**
* Navigate below to the `createClient` function to get started with using this library.
* @module
* @category Core
*/
import type { AdapterParams } from './create-adapter'
import type { ClientAPI } from './create-contentful-api'
import type { PlainClientDefaultParams } from './plain/plain-client'
import type { MakeRequest, XOR } from './common-types'
import type { PlainClientAPI } from './plain/plain-client-types'
import type { RestAdapterParams } from './adapters/REST/rest-adapter'

import { createAdapter } from './create-adapter'
import { createPlainClient } from './plain/plain-client'
import { getUserAgentHeader } from 'contentful-sdk-core'
import { createClientApi } from './create-contentful-api'

interface UserAgentParams {
/**
* Application name and version e.g myApp/version
*/
application?: string
/**
* Integration name and version e.g react/version
*/
integration?: string

feature?: string
}

export type ClientOptions = UserAgentParams & XOR<RestAdapterParams, AdapterParams>

declare global {
const __VERSION__: string
}

/**
* Create a plain client instance
*
* @param clientOptions
* @param opts
*
* @example Plain Client
* ```javascript
* const client = contentfulManagement.createClient({
* accessToken: 'myAccessToken',
* opts: {
* type: 'plain'
* }
* })
* ```
* @example Plain Client with defaults
* ```javascript
* const client = contentfulManagement.createClient({
* accessToken: 'myAccessToken',
* opts: {
* type: 'plain',
* defaults: {
* ...
* }
* }
* })
* ```
*/
export function createClient(
clientOptions: ClientOptions,
opts: {
type: 'plain'
defaults?: PlainClientDefaultParams
}
): PlainClientAPI
/**
* Create a legacy, chainable client instance
* @param clientOptions
*
* @example Legacy Chainable Client
* ```javascript
* const client = contentfulManagement.createClient({
* accessToken: 'myAccessToken'
* })
* ```
*/
export function createClient(clientOptions: ClientOptions): ClientAPI
/**
* Create a legacy or plain client instance
*
* Please check the corresponding section below:
*
* * [Plain Client](#createclient)
* * [Legacy Chainable Client](#createclient-1)
*/
export function createClient(
clientOptions: ClientOptions,
opts?: {
type?: string
defaults?: PlainClientDefaultParams
}
): ClientAPI | PlainClientAPI {
const sdkMain =
opts && opts.type === 'plain' ? 'contentful-management-plain.js' : 'contentful-management.js'
const userAgent = getUserAgentHeader(
`${sdkMain}/${__VERSION__}`,
clientOptions.application,
clientOptions.integration,
clientOptions.feature
)

const adapter = createAdapter({ ...clientOptions, userAgent })

// @ts-expect-error Parameters<?> and ReturnType<?> only return the types of the last overload (https://github.com/microsoft/TypeScript/issues/26591)
const makeRequest: MakeRequest = (options: Parameters<MakeRequest>[0]): ReturnType<MakeRequest> =>
adapter.makeRequest({ ...options, userAgent })

if (opts && opts.type === 'plain') {
return createPlainClient(makeRequest, opts.defaults)
} else {
return createClientApi(makeRequest) as ClientAPI
}
}
45 changes: 26 additions & 19 deletions lib/create-contentful-api.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* @module
* @category Legacy Client
*/
import { createRequestConfig } from 'contentful-sdk-core'
import type {
Collection,
Expand All @@ -12,7 +16,27 @@ import type {
GetOAuthApplicationParams,
GetUserParams,
} from './common-types'
import entities from './entities'
import { wrapSpace, wrapSpaceCollection } from './entities/space'
import { wrapUser } from './entities/user'
import {
wrapPersonalAccessToken,
wrapPersonalAccessTokenCollection,
} from './entities/personal-access-token'
import { wrapAccessToken, wrapAccessTokenCollection } from './entities/access-token'
import { wrapOrganization, wrapOrganizationCollection } from './entities/organization'
import { wrapUsageCollection } from './entities/usage'
import { wrapAppDefinition } from './entities/app-definition'
import {
wrapEnvironmentTemplate,
wrapEnvironmentTemplateCollection,
} from './entities/environment-template'
import type {
CreateOAuthApplicationProps,
OAuthApplication,
OAuthApplicationProps,
} from './entities/oauth-application'
import { wrapOAuthApplication, wrapOAuthApplicationCollection } from './entities/oauth-application'

import type { Organization, OrganizationProps } from './entities/organization'
import type { CreatePersonalAccessTokenProps } from './entities/personal-access-token'
import type { Space, SpaceProps } from './entities/space'
Expand All @@ -25,31 +49,14 @@ import type {
EnvironmentTemplateProps,
} from './entities/environment-template'
import type { RawAxiosRequestConfig } from 'axios'
import type {
CreateOAuthApplicationProps,
OAuthApplication,
OAuthApplicationProps,
} from './export-types'

export type ClientAPI = ReturnType<typeof createClientApi>
type CreateSpaceProps = Omit<SpaceProps, 'sys'> & { defaultLocale?: string }

/**
* @private
*/
export default function createClientApi(makeRequest: MakeRequest) {
const { wrapSpace, wrapSpaceCollection } = entities.space
const { wrapUser } = entities.user
const { wrapPersonalAccessToken, wrapPersonalAccessTokenCollection } =
entities.personalAccessToken
const { wrapAccessToken, wrapAccessTokenCollection } = entities.accessToken
const { wrapOrganization, wrapOrganizationCollection } = entities.organization
const { wrapUsageCollection } = entities.usage
const { wrapAppDefinition } = entities.appDefinition
const { wrapEnvironmentTemplate, wrapEnvironmentTemplateCollection } =
entities.environmentTemplate
const { wrapOAuthApplication, wrapOAuthApplicationCollection } = entities.oauthApplication

export function createClientApi(makeRequest: MakeRequest) {
return {
/**
* Gets all environment templates for a given organization with the lasted version
Expand Down
Loading